diff options
author | Sam Potts <sam@potts.es> | 2019-01-29 21:34:40 +1100 |
---|---|---|
committer | Sam Potts <sam@potts.es> | 2019-01-29 21:34:40 +1100 |
commit | b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb (patch) | |
tree | c799fb2b444482f6d99dcdf3f16a957b290888c0 | |
parent | afc969bac322f9b17dc0554a65fa848eb998c8e6 (diff) | |
parent | b798368ba68853558819d79a995aa0deec27f95e (diff) | |
download | plyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.tar.lz plyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.tar.xz plyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.zip |
Merge branch 'develop' into beta
126 files changed, 60239 insertions, 29602 deletions
diff --git a/.eslintrc.json b/.eslintrc.json index 63fefe4d..ae86f34f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,8 +5,12 @@ "browser": true, "es6": true }, - "globals": { "Plyr": false, "jQuery": false }, + "globals": { + "Plyr": false, + "jQuery": false + }, "rules": { + "import/no-cycle": 1, "no-const-assign": 1, "no-shadow": 0, "no-this-before-super": 1, @@ -21,19 +25,9 @@ "eqeqeq": [2, "always"], "one-var": [2, "never"], "comma-dangle": [2, "always-multiline"], - "no-restricted-globals": [ - "error", - { - "name": "event", - "message": "Use local parameter instead." - }, - { - "name": "error", - "message": "Use local parameter instead." - } - ], - "array-bracket-newline": [2, { "minItems": 2 }], - "array-element-newline": [2, { "minItems": 2 }] + "spaced-comment": [2, "always"], + "no-restricted-globals": 2, + "no-param-reassign": [2, { "props": false }] }, "parserOptions": { "sourceType": "module" diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 00000000..d4bebdfa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,55 @@ +--- +name: Bug report +about: Report an issue or unexpected behaviour with Plyr +--- + +<!-- + +Before creating the issue, please make sure that... + +* You aren't getting any errors in your own code, causing the problem. +* You are using the latest version of Plyr. +* There isn't already an open issue for your problem. +* You are following the documentation correctly (https://github.com/sampotts/plyr/) +* Your problem doesn't happen if you remove Plyr and use native HTML5 media (when applicable). + +For problems with autoplay, see our FAQ (https://github.com/sampotts/plyr/wiki/FAQ) + +If you have multiple unrelated problems, create separate issues rather than combining them into one. + +Note that leaving sections blank or being vague will make it difficult for us to troubleshoot and we may close the issue. +--> + +### Expected behaviour + +### Actual behaviour + +### Steps to reproduce + +### Environment + +- Browser: +- Version: +- Operating System: +- Version: + +### Console errors (if any) + +### Link to where the bug is happening + +<!-- +This link can be either to our demo at https://plyr.io/ if the problem can be observed there, or to a code playground with a **minimal** test case that demonstrates the problem. + +You can use one of our prepared templates to get started creating the test case: + +* HTML5 video: https://codepen.io/pen?template=bKeqpr +* HTML5 audio: https://codepen.io/pen?template=rKLywR +* YouTube: https://codepen.io/pen?template=GGqbbJ +* Vimeo: https://codepen.io/pen?template=bKeXNq +* Dash.js integration: https://codepen.io/pen?template=zaBgBy +* Hls.js integration: https://codepen.io/pen?template=oyLKQb +* Shaka Player integration: https://codepen.io/pen?template=ZRpzZO + +It's important that you keep the issue description and replication demo **minimal**. If your replication includes frameworks, libraries or customizations, this makes it much harder to understand the problem and find the bug. For more help on how to create the demo, see https://github.com/sampotts/plyr/wiki/Writing-helpful-issue-descriptions + +--> diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 00000000..342ab0f0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,10 @@ +--- +name: New feature +about: Request new functionality +--- + +<!-- +Please describe the behaviour that you want to add, and why. Be as clear as possible to avoid confusion. + +If you want to request multiple features that aren't directly related, then create one issue per feature. +--> diff --git a/.github/ISSUE_TEMPLATE/improvement.md b/.github/ISSUE_TEMPLATE/improvement.md new file mode 100644 index 00000000..de7e0576 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improvement.md @@ -0,0 +1,10 @@ +--- +name: Improvement +about: Request a change that isn't a bug or new feature +--- + +<!-- +Please describe the behaviour that you want to change, and why. Be as clear as possible to avoid confusion. + +If you want to request multiple changes that aren't directly related, then create one issue per change. +--> diff --git a/.github/issue_template.md b/.github/issue_template.md index f503b944..54f4550b 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,17 +1,3 @@ -<!--- -Please use this issue template as it makes replicating and fixing the issue easier! ----> +PLEASE USE OUR SPECIFIC ISSUE TEMPLATES for bug reports, features and improvement suggestions. -### Expected behaviour - -### Actual behaviour - -### Environment - -- Browser: -- Version: -- Operating System: -- Version: - -### Steps to reproduce --
\ No newline at end of file +Our issue tracker is not for support questions. If you need help, follow our support instructions: https://github.com/sampotts/plyr/blob/master/contributing.md#support diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c4779d3c..f67d769f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,8 @@ ### Link to related issue (if applicable) -### Sumary of proposed changes +### Summary of proposed changes -### Task list - -- [ ] Tested on [supported browsers](https://github.com/sampotts/plyr#browser-support) -- [ ] Gulp build completed
\ No newline at end of file +### Checklist +- [ ] Use `develop` as the base branch +- [ ] Exclude the gulp build (`/dist` changes) from the PR +- [ ] Test on [supported browsers](https://github.com/sampotts/plyr#browser-support) @@ -1,11 +1,11 @@ node_modules .DS_Store -aws.json +credentials.json *.mp4 !dist/blank.mp4 index-*.html npm-debug.log +yarn-error.log +package-lock.json *.webm -/package-lock.json .idea/ - @@ -2,3 +2,10 @@ demo .github .vscode *.code-workspace +credentials.json +bundles.json +yarn.lock +package-lock.json +*.mp4 +*.webm +!dist/blank.mp4
\ No newline at end of file diff --git a/.prettierrc b/.prettierrc index e1544230..cee783d4 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,7 @@ { "useTabs": false, "tabWidth": 4, - "printWidth": 160, "singleQuote": true, - "trailingComma": "all" + "trailingComma": "all", + "printWidth": 120 } diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 00000000..717ba28c --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,5 @@ +linters: + eslint: +files: + ignore: + - 'node_modules/*' diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..3203fb95 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: lts/* + +script: +- bash .travis/prevent-base-master.sh +- bash .travis/omit-dist.sh +- npm run lint +- npm run build diff --git a/.travis/omit-dist.sh b/.travis/omit-dist.sh new file mode 100755 index 00000000..f107a6b9 --- /dev/null +++ b/.travis/omit-dist.sh @@ -0,0 +1,5 @@ +#!/bin/bash +if [ $TRAVIS_BRANCH == "develop" ] && $(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qE "^(demo/)?dist/"); then + echo 'Build output ("dist" and "demo/dist") not permitted in develop' >&2 + exit 1 +fi diff --git a/.travis/prevent-base-master.sh b/.travis/prevent-base-master.sh new file mode 100755 index 00000000..54536a66 --- /dev/null +++ b/.travis/prevent-base-master.sh @@ -0,0 +1,5 @@ +#!/bin/bash +if [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ $TRAVIS_BRANCH == "master" ] && $(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -q "^src/"); then + echo 'The base branch for pull requests must be "develop"' >&2 + exit 1 +fi diff --git a/bower.json b/bower.json deleted file mode 100644 index 53c921b7..00000000 --- a/bower.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "plyr", - "description": "A simple HTML5 media player using custom controls", - "homepage": "http://plyr.io", - "keywords": [ - "Audio", - "Video", - "HTML5 Audio", - "HTML5 Video" - ], - "authors": [ - "Sam Potts <sam@potts.es>" - ], - "dependencies": {}, - "main": [ - "dist/plyr.css", - "dist/plyr.js", - "dist/plyr.svg", - "src/less/plyr.less", - "src/scss/plyr.scss", - "src/js/plyr.js" - ], - "ignore": [ - "node_modules", - "bower_components", - ".gitignore" - ], - "repository": { - "type": "git", - "url": "git://github.com/sampotts/plyr.git" - }, - "license": "MIT" -}
\ No newline at end of file diff --git a/changelog.md b/changelog.md index b4051587..cdbaba59 100644 --- a/changelog.md +++ b/changelog.md @@ -1,146 +1,317 @@ -# v3.3.6 +## v3.5.0 -* Vimeo fixes for mute state -* Vimeo ID fix (fixes #945) -* Use `<div>` for poster container -* Tooltip fixes for unicode languages (fixes #943) +- Preview seek/scrubbing thumbnails (thanks @jamesoflol) +- Fixes for proxy listeners (thanks @gurupras) +- Fix for buffer progress transition on WebKit (thanks @samuelgozi) +- Fix for error when mime type not specified (fixes #1274) +- Support YouTube noCookie (thanks Omar Khatib) +- Add Angular plugin reference (thanks @smnbbrv) +- Use `Math.trunc` instead of `parseInt` (thanks @taion) +- Many fixes for fullscreen in embedded players with non 16:9 screens or videos +- Added 'force' fallback option for fullscreen -# v3.3.5 +### v3.4.8 -* Removed `.load()` call as it breaks HLS (see #870) +- Calling customized controls function with proper arguments (thanks @a60814billy) -# v3.3.4 +### v3.4.7 -* Fix for controls sometimes not showing while video is playing -* Fixed logic for show home tab on option select +- Fix for Vimeo fullscreen with non native aspect ratios (fixes #854) -# v3.3.3 +### v3.4.6 -* Reverted change to show home tab on option select due to usability regression +- Added picture-in-picture support for Chrome 70+ +- Fixed issue with versioning the SVG sprite in the gulp build script -# v3.3.2 +### v3.4.5 -* Fix for ads running in audio -* Fix for setting poster on source change +- Added download button option to download either current source or a custom URL you specify in options +- Prevent immediate hiding of controls on mobile (thanks @jamesoflol) +- Don't hide controls on focusout event (fixes #1122) (thanks @jamesoflol) +- Fix HTML5 quality settings being incorrectly set in local storage (thanks @TechGuard) -## v3.3.0 +### v3.4.4 -* Now using a custom poster image element to hide the YouTube play button and give more control over when the poster image shows -* Renamed `showPosterOnEnd` to `resetOnEnd` as it makes more sense and now works for all players and does not reload media -* Fix for same domain SVG URLs (raised by Jochem in Slack) -* [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/Window/URL) is polyfill now required -* Added pause className (fixes #941) -* Button height set in CSS (auto) (fixes #928) -* Don't autoplay cloned original media (fixes #936) -* Return to the home menu pane after selecting an option +- Fixed issue with double binding for `click` and `touchstart` for `clickToPlay` option +- Improved "faux" fullscreen on iPhone X/XS phones with notch +- Babel 7 upgrade (which reduced the polyfilled build by ~10kb!) -## v3.2.4 +### v3.4.3 -* Fix issue wher player never reports as ready if controls is empty array -* Fix issue where screen reader labels were removed from time displays -* Fix issue where custom controls placeholders were not populated -* Custom controls HTML example updated -* Fix for aria-label being set to the initial state on toggle buttons, overriding the inner labels -* Fix for hidden mute button on iOS (not functional for Vimeo due to API limitations) (fixes #656) +- Fixed issue with nodeList for custom playback controls -## v3.2.3 +### v3.4.2 -* Fix for iOS 9 throwing error for `name` property in fullscreen API (fixes #908) +- Fix play/pause button state -## v3.2.2 +### v3.4.1 -* Fix for regression in 3.2.1 resulting in hidden buffer display (fixes #920) -* Cleaned up incorrect use of `aria-hidden` attribute +- Bug fix for custom controls (fixes #1161) -## v3.2.1 +## v3.4.0 -* Accessibility improvements for the controls (part of #905 fixes) -* Fix for context menu showing on YouTube (thanks Anthony Recenello in Slack) -* Vimeo fix for their API not returning the right duration until playback begins (fixes #891) +- Accessibility improvements (see #905) +- Improvements to the way the controls work on iOS +- Demo code clean up +- YouTube quality selection removed due to their poor support for it. As a result, the `qualityrequested` event has been removed +- Controls spacing improvements +- Fix for pressed property missing with custom controls (Fixes #1062) +- Fix #1153: Captions language fallback (thanks @friday) +- Fix for setting pressed property of undefined (Fixes #1102) -## v3.2.0 +### v3.3.23 -* Fullscreen fixes (thanks @friday) -* Menu fix for if speed not in config -* Menu z-index fix (thanks @danielsarin) -* i18n fix for missing "Normal" string (thanks @danielsarin) -* Safer check for active caption (thanks @Antonio-Laguna) -* Add custom property fallback (thanks @friday) -* Fixed bug for captions with no srclang and labels and improved logic (fixes #875) -* Fix for `playing` false positive (fixes #898) -* Fix for IE issue with navigator.language (thanks @nicolasthy) (fixes #893) -* Fix for Vimeo controls missing on iOS (thanks @verde-io) (fixes #807) -* Fix for double vimeo caption rendering (fixes #877) +- Add support for YouTube's hl param (thanks @renaudleo) +- Fix for captions positioning when no controls (thanks @friday and @mjfwebb) +- Fix #1108: Make sure youtube.onReady doesn't run twice (thanks @friday) +- Fix for WebKit repaint loop on the `<input type="range">` elements -## v3.1.0 +### v3.3.22 + +- Travis & CI improvements (thanks @friday) +- Add navigator.languages fallback for iOS 9 (thanks @friday) + +### v3.3.21 + +- Hide currentTime and progress for streams (thanks @mimse) +- Fixed condition check (thanks @mimse) +- Handle undefined this.player.elements.buttons.play (thanks @klassicd) +- Fix captions.toggle() if there is no toggle button (thanks @friday) + +### v3.3.20 + +- Fix for bug where controls wouldn't show on hover over YouTube video + +### v3.3.19 + +- Remove `pointer-events: none` on embed `<iframe>` to comply with YouTube ToS + +### 3.3.18 + +- Ads are now only supported on HTML5 videos as it violates terms of service for YouTube and Vimeo 😢 +- Fix i18n defaults path on README (thanks @meyt!) +- Minor increaseVolume and decreaseVolume changes (thanks @friday!) + +### v3.3.17 + +- Fix YouTube muting after seeking with the progress slider (thanks @friday!) +- Respect preload="none" when setting quality if the media hasn't been loaded some other way (thanks @friday!) + +### v3.3.16 + +- Fixed regression relating the play button status (fixes #1048) -* Styling fixes +### v3.3.15 -## v3.1.0-beta.2 +- Fix for error relating to play buttons when switching source -* YouTube playback speed fixes +### v3.3.14 -## v3.1.0-beta.1 +- Fix sprite loading regression -* HTML5 quality selection -* Improvements to the YouTube quality selection +### v3.3.13 -## v3.0.11 +You guessed it, a load of awesome changes from contributors: -* Muted and autoplay fixes -* Small bug fixes from Sentry logs +Thanks @friday for the following: -## v3.0.10 +- Captions fixes +- Fix poster race conditions +- Minor code improvements for quality switching +- Minor event changes +- Fix condition in events.toggleListener to allow non-elements +- Suggestion: Remove array newline rule +- Contributions improvements -* Docs fix -* Package upgrades +- fix: html5.cancelRequest not remove source tag correctly (thanks @a60814billy) +- remove event listeners in destroy() (thanks @cky917) +- Fix markdown in README (thanks @azu) +- Some parts of the accessibility improvements outlined in #905 (more on the way...) +- Fix for bug where volume slider didn't always show -## v3.0.9 +### v3.3.12 -* Demo fix -* Fix Vimeo regression +- Fix synthetic event bubble/proxy loses detail (thanks @friday!) +- Make utils static (thanks @friday!) +- Fix for YouTube and Vimeo pausing after seek (thanks @friday!) +- Vimeo: Update playback state and assure events are triggered on load (thanks @friday!) +- Captions rewrite (use index internally to support missing or duplicate languages) (thanks @friday and @philipgiuliani!) +- Contributing document and codepen demo updates (thanks @friday!) +- Fix for after clicking on the progress bar, keyboard operations will not work (thanks @cky917!) -## v3.0.8 +### v3.3.10 -* Vimeo hotfix for private videos +- Fix for buffer display alignment and incorrect BEM classname +- Fix for playback not resuming position after quality swap (fixes #991, thanks @philipgiuliani!) +- Travis integration (thanks @friday!) +- Translate quality badges and quality names (thanks @philipgiuliani!) +- Improve captions handling for streaming (thanks @friday!) +- Call duration update method manually if user config has duration (thanks @friday!) -## v3.0.7 +### v3.3.9 -* Fix for keyboard shortcut error with fast forward -* Fix for Vimeo trying to set playback rate when not allowed +Again, more changes from @friday! -## v3.0.6 +- Restore window reference in `is.cue()` +- Fix InvalidStateError and IE11 issues +- Respect storage being disabled for storage getter -* Improved the logic for the custom handlers preventing default handlers +### v3.3.8 -## v3.0.5 +Many changes here thanks to @friday: + +- Added missing URL polyfill +- Pause while seeking to mimic default HTML5 behaviour +- Add `seeked` event listener to update progress (fixes #966) +- Trigger seeked event in youtube plugin if either playing or paused (fixes #921) +- Fix for YouTube and Vimeo autoplays on seek (fixes #876) +- Toggle controls improvements +- Cleanup unused code +- Poster image loading improvements +- Fix for seek tooltip vs click accuracy + +### v3.3.7 + +- Poster fixes (thanks @friday) +- Grid tweak + +### v3.3.6 + +- Vimeo fixes for mute state +- Vimeo ID fix (fixes #945) +- Use `<div>` for poster container +- Tooltip fixes for unicode languages (fixes #943) + +### v3.3.5 + +- Removed `.load()` call as it breaks HLS (see #870) + +### v3.3.4 + +- Fix for controls sometimes not showing while video is playing +- Fixed logic for show home tab on option select + +### v3.3.3 + +- Reverted change to show home tab on option select due to usability regression + +### v3.3.2 + +- Fix for ads running in audio +- Fix for setting poster on source change + +## v3.3.0 -* Removed console messages +- Now using a custom poster image element to hide the YouTube play button and give more control over when the poster image shows +- Renamed `showPosterOnEnd` to `resetOnEnd` as it makes more sense and now works for all players and does not reload media +- Fix for same domain SVG URLs (raised by Jochem in Slack) +- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/Window/URL) is polyfill now required +- Added pause className (fixes #941) +- Button height set in CSS (auto) (fixes #928) +- Don't autoplay cloned original media (fixes #936) +- Return to the home menu pane after selecting an option -## v3.0.4 +### v3.2.4 -* Fixes for fullscreen not working inside iframes -* Fixes for custom handlers being able to prevent default -* Fixes for controls not hiding/showing correctly on Mobile Safari +- Fix issue wher player never reports as ready if controls is empty array +- Fix issue where screen reader labels were removed from time displays +- Fix issue where custom controls placeholders were not populated +- Custom controls HTML example updated +- Fix for aria-label being set to the initial state on toggle buttons, overriding the inner labels +- Fix for hidden mute button on iOS (not functional for Vimeo due to API limitations) (fixes #656) -## v3.0.3 +### v3.2.3 -* Vimeo offset tweak (fixes #826) -* Fix for .stop() method (fixes #819) -* Check for array for speed options (fixes #817) -* Restore as float (fixes #828) -* Fix for Firefox fullscreen oddness (Fixes #821) -* Improve Sprite checking (fixes #827) -* Fix fast-forward control (thanks @saadshahd) -* Fix the options link in the readme (thanks @DanielRuf) +- Fix for iOS 9 throwing error for `name` property in fullscreen API (fixes #908) -## v3.0.2 +### v3.2.2 -* Fix for Safari not firing error events when trying to load blocked scripts +- Fix for regression in 3.2.1 resulting in hidden buffer display (fixes #920) +- Cleaned up incorrect use of `aria-hidden` attribute -## v3.0.1 +### v3.2.1 -* Fix for trying to accessing local storage when it's blocked +- Accessibility improvements for the controls (part of #905 fixes) +- Fix for context menu showing on YouTube (thanks Anthony Recenello in Slack) +- Vimeo fix for their API not returning the right duration until playback begins (fixes #891) + +## v3.2.0 + +- Fullscreen fixes (thanks @friday) +- Menu fix for if speed not in config +- Menu z-index fix (thanks @danielsarin) +- i18n fix for missing "Normal" string (thanks @danielsarin) +- Safer check for active caption (thanks @Antonio-Laguna) +- Add custom property fallback (thanks @friday) +- Fixed bug for captions with no srclang and labels and improved logic (fixes #875) +- Fix for `playing` false positive (fixes #898) +- Fix for IE issue with navigator.language (thanks @nicolasthy) (fixes #893) +- Fix for Vimeo controls missing on iOS (thanks @verde-io) (fixes #807) +- Fix for double vimeo caption rendering (fixes #877) + +## v3.1.0 + +- Styling fixes +- YouTube playback speed fixes +- HTML5 quality selection +- Improvements to the YouTube quality selection + +### v3.0.11 + +- Muted and autoplay fixes +- Small bug fixes from Sentry logs + +### v3.0.10 + +- Docs fix +- Package upgrades + +### v3.0.9 + +- Demo fix +- Fix Vimeo regression + +### v3.0.8 + +- Vimeo hotfix for private videos + +### v3.0.7 + +- Fix for keyboard shortcut error with fast forward +- Fix for Vimeo trying to set playback rate when not allowed + +### v3.0.6 + +- Improved the logic for the custom handlers preventing default handlers + +### v3.0.5 + +- Removed console messages + +### v3.0.4 + +- Fixes for fullscreen not working inside iframes +- Fixes for custom handlers being able to prevent default +- Fixes for controls not hiding/showing correctly on Mobile Safari + +### v3.0.3 + +- Vimeo offset tweak (fixes #826) +- Fix for .stop() method (fixes #819) +- Check for array for speed options (fixes #817) +- Restore as float (fixes #828) +- Fix for Firefox fullscreen oddness (Fixes #821) +- Improve Sprite checking (fixes #827) +- Fix fast-forward control (thanks @saadshahd) +- Fix the options link in the readme (thanks @DanielRuf) + +### v3.0.2 + +- Fix for Safari not firing error events when trying to load blocked scripts + +### v3.0.1 + +- Fix for trying to accessing local storage when it's blocked # v3.0.0 @@ -148,37 +319,37 @@ This is a massive release. A _mostly_ complete rewrite in ES6. What started out ### Big changes -* New settings menu complete with funky animations -* Ability to adjust speed of playback -* Ability to toggle caption language (HTML5 and Vimeo only) -* Ability to set YouTube quality (HTML5 will follow) -* Added support for Vimeo captions -* Added Picture-in-Picture support (Safari only) -* Added AirPlay support (again, Safari only) -* Added `playsinline` support for iOS 10+ -* Soundcloud removed until I can work on a plugin framework -* Embedded players are now progressively enhanced - no more empty `<div>`s! +- New settings menu complete with funky animations +- Ability to adjust speed of playback +- Ability to toggle caption language (HTML5 and Vimeo only) +- Ability to set YouTube quality (HTML5 will follow) +- Added support for Vimeo captions +- Added Picture-in-Picture support (Safari only) +- Added AirPlay support (again, Safari only) +- Added `playsinline` support for iOS 10+ +- Soundcloud removed until I can work on a plugin framework +- Embedded players are now progressively enhanced - no more empty `<div>`s! ### Other stuff -* Now using SASS exclusively. Sorry, LESS folk it just made sense to maintain one method as SASS is what the cool kids use. It may come back if we work out an automated way to convert the SASS -* Moved to ES6. All the rage these days. You'll need to look at polyfills. The demo uses [polyfill.io](https://polyfill.io) -* Added basic looping support -* Added an aspect ratio option for those that can't leave the 90s and want 4:3 -* `controlshidden` and `controlsshown` events added for when the controls show or hide -* `qualityrequested` and `qualitychange` events for YouTube quality control (HTML5 will follow) -* Volume is now `0` to `1` as per HTML5 spec -* No longer bodging a `<progress>` behind the `<input type="range">` to make up for WebKit's lack of lower fill styling -* Captions now render with line breaks as intended -* Captions now render without AJAX using the native events etc -* Added a fallback for getting YouTube video data incase `.getVideoData()` disappears when one of their developers randomly deletes it again -* Setup and building of the UI should be way "snappier" -* Click to toggle inverted time (e.g. 0:01 or -2:59 for a 3 minute video at 1 seconds) - new `toggleInvert` and `invertTime` options -* Added `autopause` option for Vimeo -* Added `muted` option for you guessed it, muted playback -* Restored the `.off()` API method -* `.play()` will now return a promise to prevent that pesky uncaught promise issue in Chrome etc -* Pressing and hold the seek bar no longer freezes all other updates of the UI +- Now using SASS exclusively. Sorry, LESS folk it just made sense to maintain one method as SASS is what the cool kids use. It may come back if we work out an automated way to convert the SASS +- Moved to ES6. All the rage these days. You'll need to look at polyfills. The demo uses [polyfill.io](https://polyfill.io) +- Added basic looping support +- Added an aspect ratio option for those that can't leave the 90s and want 4:3 +- `controlshidden` and `controlsshown` events added for when the controls show or hide +- `qualityrequested` and `qualitychange` events for YouTube quality control (HTML5 will follow) +- Volume is now `0` to `1` as per HTML5 spec +- No longer bodging a `<progress>` behind the `<input type="range">` to make up for WebKit's lack of lower fill styling +- Captions now render with line breaks as intended +- Captions now render without AJAX using the native events etc +- Added a fallback for getting YouTube video data incase `.getVideoData()` disappears when one of their developers randomly deletes it again +- Setup and building of the UI should be way "snappier" +- Click to toggle inverted time (e.g. 0:01 or -2:59 for a 3 minute video at 1 seconds) - new `toggleInvert` and `invertTime` options +- Added `autopause` option for Vimeo +- Added `muted` option for you guessed it, muted playback +- Restored the `.off()` API method +- `.play()` will now return a promise to prevent that pesky uncaught promise issue in Chrome etc +- Pressing and hold the seek bar no longer freezes all other updates of the UI ...plus loads of bug fixes. @@ -186,703 +357,707 @@ This is a massive release. A _mostly_ complete rewrite in ES6. What started out You gotta break eggs to make an omelette. Sadly, there's quite a few breaking changes: -* Setup now uses proper constructor, accepts a single selector/element/node and returns a single instance - much simpler than before -* Much of the API is now using getters and setters rather than methods (where it makes sense) to match the HTML5 API - see the docs for more info -* The data attributes for the embeds are now `data-plyr-provider` and `data-plyr-embed-id` to prevent compatibility issues. These can be changed under `config.attributes.embed` if required -* `blankUrl` -> `blankVideo` -* `volume` is now `0` to `1` as per HTML5 spec -* `keyboardShorcuts` (typo) is now just `keyboard` -* `loop` is now `loop.active` in preparation for loop enhancements later -* `html` option for custom controls removed in favour of the `controls` option which now accepts an array (to use built in controls) or a string of HTML for custom controls. -* `classes` -> `classNames` -* `classes.videoWrapper` -> `classNames.video` -* `classes.embedWrapper` -> `classNames.embed` -* `classes.ready` removed -* `classes.setup` removed -* `classes.muted` removed -* `classes.fullscreen.active` removed in favour of the `:fullscreen` selector -* `selectors.html5` removed -* `selectors.embed` removed -* `selectors.buttons.seek` -> `selectors.inputs.seek` -* `selectors.volume.input` -> `selectors.inputs.volume` -* `selectors.volume.display` -> `selectors.display.volume` -* `selectors.currentTime` -> `selectors.display.currentTime` -* `selectors.duration` -> `selectors.display.duration` +- Setup now uses proper constructor, accepts a single selector/element/node and returns a single instance - much simpler than before +- Much of the API is now using getters and setters rather than methods (where it makes sense) to match the HTML5 API - see the docs for more info +- The data attributes for the embeds are now `data-plyr-provider` and `data-plyr-embed-id` to prevent compatibility issues. These can be changed under `config.attributes.embed` if required +- `blankUrl` -> `blankVideo` +- `volume` is now `0` to `1` as per HTML5 spec +- `keyboardShorcuts` (typo) is now just `keyboard` +- `loop` is now `loop.active` in preparation for loop enhancements later +- `html` option for custom controls removed in favour of the `controls` option which now accepts an array (to use built in controls) or a string of HTML for custom controls. +- `classes` -> `classNames` +- `classes.videoWrapper` -> `classNames.video` +- `classes.embedWrapper` -> `classNames.embed` +- `classes.ready` removed +- `classes.setup` removed +- `classes.muted` removed +- `classes.fullscreen.active` removed in favour of the `:fullscreen` selector +- `selectors.html5` removed +- `selectors.embed` removed +- `selectors.buttons.seek` -> `selectors.inputs.seek` +- `selectors.volume.input` -> `selectors.inputs.volume` +- `selectors.volume.display` -> `selectors.display.volume` +- `selectors.currentTime` -> `selectors.display.currentTime` +- `selectors.duration` -> `selectors.display.duration` ### Polyfilling Because we're using the fancy new ES6 syntax, you will need to polyfill for vintage browsers if you want to use Plyr and still support them. Luckily there's a decent service for this that makes it painless, [polyfill.io](https://polyfill.io). Alternatively, you can use the prebuilt polyfilled build but bear in mind this is 20kb larger. I'd suggest working our your own polyfill strategy. -## v2.0.18 +### v2.0.18 -* Fix for YouTube .getVideoData() issue (fixes #709) +- Fix for YouTube .getVideoData() issue (fixes #709) -## v2.0.17 +### v2.0.17 -* Vimeo controls fix (fixes #697) -* SVG4everybody compatibility fix -* Allow Plyr.setup event listeners to be set up as separate event listeners (https://github.com/sampotts/plyr/pull/703) -* Added title to the layer html template (for custom controls) (https://github.com/sampotts/plyr/pull/649) -* Target is null bug fix (https://github.com/sampotts/plyr/pull/617) -* fix #684 memory leaks issues after destroy (https://github.com/sampotts/plyr/pull/700) +- Vimeo controls fix (fixes #697) +- SVG4everybody compatibility fix +- Allow Plyr.setup event listeners to be set up as separate event listeners (https://github.com/sampotts/plyr/pull/703) +- Added title to the layer html template (for custom controls) (https://github.com/sampotts/plyr/pull/649) +- Target is null bug fix (https://github.com/sampotts/plyr/pull/617) +- fix #684 memory leaks issues after destroy (https://github.com/sampotts/plyr/pull/700) -## v2.0.16 +### v2.0.16 -* Fullscreen bug fix (fixes #664) +- Fullscreen bug fix (fixes #664) -## v2.0.15 +### v2.0.15 -* Demo fix +- Demo fix -## v2.0.14 +### v2.0.14 -* CDN URL updates. Sorry, still working on V3 as hard as I can... +- CDN URL updates. Sorry, still working on V3 as hard as I can... -## v2.0.13 +### v2.0.13 -* Repo moved and Vimeo demo fix +- Repo moved and Vimeo demo fix -## v2.0.12 +### v2.0.12 -* Ability to set custom `blankUrl` for source changes (https://github.com/sampotts/plyr/pull/504) -* Ability to set caption button listener (https://github.com/sampotts/plyr/pull/468) +- Ability to set custom `blankUrl` for source changes (https://github.com/sampotts/plyr/pull/504) +- Ability to set caption button listener (https://github.com/sampotts/plyr/pull/468) -## v2.0.11 +### v2.0.11 -* Fix for `cleanUp` being called twice (thanks to @sebastiancarlsson) -* Fix for YouTube controls on iPad (fixes #391) +- Fix for `cleanUp` being called twice (thanks to @sebastiancarlsson) +- Fix for YouTube controls on iPad (fixes #391) -## v2.0.10 +### v2.0.10 -* Added seek event fixes for Vimeo and YouTube (fixes #409) -* Added support for embed URLs rather than ID only (fixes #345) +- Added seek event fixes for Vimeo and YouTube (fixes #409) +- Added support for embed URLs rather than ID only (fixes #345) -## v2.0.9 +### v2.0.9 -* Temporary patch for the YouTube API issues with `getDuration()` (relates to #374) +- Temporary patch for the YouTube API issues with `getDuration()` (relates to #374) -## v2.0.8 +### v2.0.8 -* Added `isPaused()` API method (thanks to @darrena092) -* Allowed `.on()` API method to be chainable (thanks to @gurupras) (fixes #357) -* Improved the "awful" rendering of captions on small screens in fullscreen mode (fixes #390) -* Fix for Firefox VTT compatibility (thanks to @magourex) -* Fix for Firefox Developer Edition blank video due to `-webkit-mask-image` issue (fixes #392) -* Added Issue and PR templates with the aim of reducing duplicate or duff issues +- Added `isPaused()` API method (thanks to @darrena092) +- Allowed `.on()` API method to be chainable (thanks to @gurupras) (fixes #357) +- Improved the "awful" rendering of captions on small screens in fullscreen mode (fixes #390) +- Fix for Firefox VTT compatibility (thanks to @magourex) +- Fix for Firefox Developer Edition blank video due to `-webkit-mask-image` issue (fixes #392) +- Added Issue and PR templates with the aim of reducing duplicate or duff issues -## v2.0.7 +### v2.0.7 -* Fixed `getCurrentTime()` method (fixes #351) -* Added `getVolume()` , `isMuted()` and `getDuration()` API methods (fixes #346) +- Fixed `getCurrentTime()` method (fixes #351) +- Added `getVolume()` , `isMuted()` and `getDuration()` API methods (fixes #346) -## v2.0.6 +### v2.0.6 -* Fixed merge issue with `Updated define to work with AMD imports #326` PR -* Code formatting +- Fixed merge issue with `Updated define to work with AMD imports #326` PR +- Code formatting -## v2.0.5 +### v2.0.5 -* Fix for Vimeo in IE9 & IE10 -* Fix for HTML5 elements not firing `ready` event +- Fix for Vimeo in IE9 & IE10 +- Fix for HTML5 elements not firing `ready` event -## v2.0.4 +### v2.0.4 -* Fix for Firefox full screen (fixes #343) +- Fix for Firefox full screen (fixes #343) -## v2.0.3 +### v2.0.3 -* Set 'global' keyboard shortcut option to false as default, added `<textarea>` to editable elements to be ignored +- Set 'global' keyboard shortcut option to false as default, added `<textarea>` to editable elements to be ignored -## v2.0.2 +### v2.0.2 -* Added 'global' keyboard shortcut option +- Added 'global' keyboard shortcut option -## v2.0.1 +### v2.0.1 -* Version bump for NPM (sorry for folks who upgraded to the now deleted v1.9.0 through NPM) +- Version bump for NPM (sorry for folks who upgraded to the now deleted v1.9.0 through NPM) # v2.0.0 This version contains several potential **_breaking changes_**: -* `setup()` has been reverted to pre v1.8.0 behaviour; meaning it will return the _instance_ rather than the _element_. This is because the reference to the instance is no longer added to the original element (see below). -* The reference to the `plyr` instance is now added to the media element rather than original container. This is because if a container with multiple children was passed to `setup()` the references to all instances would have been added to the container, creating issues. I would recommend using the return value from `setup()` or the new `get()` method to access the instance. -* Players will always be wrapped in their own div now - this makes `setup()` and `destroy()` cleaner. This _may_ break any custom styling based on DOM position. -* Players no longer seek to 0 on 'ended' - this is to fix a bug with Microsoft Edge as it triggers 'ended' on media change for whatever reason. They'll never change ;-) +- `setup()` has been reverted to pre v1.8.0 behaviour; meaning it will return the _instance_ rather than the _element_. This is because the reference to the instance is no longer added to the original element (see below). +- The reference to the `plyr` instance is now added to the media element rather than original container. This is because if a container with multiple children was passed to `setup()` the references to all instances would have been added to the container, creating issues. I would recommend using the return value from `setup()` or the new `get()` method to access the instance. +- Players will always be wrapped in their own div now - this makes `setup()` and `destroy()` cleaner. This _may_ break any custom styling based on DOM position. +- Players no longer seek to 0 on 'ended' - this is to fix a bug with Microsoft Edge as it triggers 'ended' on media change for whatever reason. They'll never change ;-) And some other changes and bug fixes: -* New `get()` method on the global plyr object to get all instances inside a container -* New API methods: - `getOriginal()` to get the original, _unmodified_ element plyr was setup on (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getContainer()` to get the players outer wrapper element - `getMedia()` to get the players media element (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getEmbed()` to access the YouTube or Vimeo API directly - `getType()` to get the type of the player - `isReady()` to determine if an instance has completed setup and necessary APIs are loaded (for YouTube / Vimeo) - `on()` to provide an easy way to listen to events - `stop()` to, you guessed it, stop the player -* `destroy()` now works correctly for YouTube and Vimeo (fixes #272) -* New `destroyed` event when `destroy()` has completed (original element is passed as event.target) -* Default volume is now 10 (max) rather than 5 -* Sprite is only loaded once (fixes #259) -* Fixes for Vimeo post message bugs on source change or destroy (fixes #318) -* Save caption state in storage (fixes #311) -* Added keyboard shortcuts to the current focused player (with `keyboardShortcuts` boolean option to disable) (fixes #309) -* Fix for captions bug (fixes #332) -* Change to AMD (fixes #298) +- New `get()` method on the global plyr object to get all instances inside a container +- New API methods: - `getOriginal()` to get the original, _unmodified_ element plyr was setup on (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getContainer()` to get the players outer wrapper element - `getMedia()` to get the players media element (`<video>`, `<audio>` or empty `<div>` for YouTube and Vimeo) - `getEmbed()` to access the YouTube or Vimeo API directly - `getType()` to get the type of the player - `isReady()` to determine if an instance has completed setup and necessary APIs are loaded (for YouTube / Vimeo) - `on()` to provide an easy way to listen to events - `stop()` to, you guessed it, stop the player +- `destroy()` now works correctly for YouTube and Vimeo (fixes #272) +- New `destroyed` event when `destroy()` has completed (original element is passed as event.target) +- Default volume is now 10 (max) rather than 5 +- Sprite is only loaded once (fixes #259) +- Fixes for Vimeo post message bugs on source change or destroy (fixes #318) +- Save caption state in storage (fixes #311) +- Added keyboard shortcuts to the current focused player (with `keyboardShortcuts` boolean option to disable) (fixes #309) +- Fix for captions bug (fixes #332) +- Change to AMD (fixes #298) -## v1.8.12 +### v1.8.12 -* Vimeo keyboard focus fix (Fixes #317) -* Fix for Vimeo on basic support devices +- Vimeo keyboard focus fix (Fixes #317) +- Fix for Vimeo on basic support devices -## v1.8.11 +### v1.8.11 -* Fix for keyboard navigation on Vimeo (Fixes #317) -* Fix for bug introduced in v1.8.9 related to additional controls -* Vimeo API upgrade -* Fix for YouTube bug introduced in v1.8.9 -* Added support for passing array to .setup() (Fixes #319) +- Fix for keyboard navigation on Vimeo (Fixes #317) +- Fix for bug introduced in v1.8.9 related to additional controls +- Vimeo API upgrade +- Fix for YouTube bug introduced in v1.8.9 +- Added support for passing array to .setup() (Fixes #319) -## v1.8.10 +### v1.8.10 -* Fix for seek issues introduced in v1.8.9 +- Fix for seek issues introduced in v1.8.9 -## v1.8.9 +### v1.8.9 -* Fix for fullscreen not being defined (Fixes #295) -* Fix for multiline captions (Fixes #314) -* Clean up of type checks and fix for `restart()` (Fixes #315) -* Fix for `MEDIA_ERR_SRC_NOT_SUPPORTED` when calling `.source()` API method +- Fix for fullscreen not being defined (Fixes #295) +- Fix for multiline captions (Fixes #314) +- Clean up of type checks and fix for `restart()` (Fixes #315) +- Fix for `MEDIA_ERR_SRC_NOT_SUPPORTED` when calling `.source()` API method -## v1.8.8 +### v1.8.8 -* Added getCurrentTime API method (fixes #292) -* Fix for !hideControls on touch devices (fixes #303) +- Added getCurrentTime API method (fixes #292) +- Fix for !hideControls on touch devices (fixes #303) -## v1.8.7 +### v1.8.7 -* Line height fix +- Line height fix -## v1.8.6 +### v1.8.6 -* Reverted font size change +- Reverted font size change -## v1.8.5 +### v1.8.5 -* Fixed overflow issues (fixes #286) +- Fixed overflow issues (fixes #286) -## v1.8.4 +### v1.8.4 -* Fix for large play button on small videos +- Fix for large play button on small videos -## v1.8.3 +### v1.8.3 -* Disabled iPad support for YouTube and Vimeo due to iOS limitations with iFrame playback -* Fixed IE11 icon loading (fixes #269) -* Updated screenshot (fixes #281) -* Added WordPress plugin (fixes #239) -* Added Neos plugin -* Added HLS, Shaka and dash.js examples (see #235 for more) -* Improvements for controls hiding and showing on touch devices +- Disabled iPad support for YouTube and Vimeo due to iOS limitations with iFrame playback +- Fixed IE11 icon loading (fixes #269) +- Updated screenshot (fixes #281) +- Added WordPress plugin (fixes #239) +- Added Neos plugin +- Added HLS, Shaka and dash.js examples (see #235 for more) +- Improvements for controls hiding and showing on touch devices -## v1.8.2 +### v1.8.2 -* Fixed event bubbling +- Fixed event bubbling -## v1.8.1 +### v1.8.1 -* Fixed inaccurate log message +- Fixed inaccurate log message -# v1.8.0 +## v1.8.0 -* **_(Important)_** `setup()` now returns the element Plyr was setup on rather than the `plyr` object. This means `var player = plyr.setup()[0];` would now be `var player = plyr.setup()[0].plyr;`. This improves support for React and other virtual dom frameworks as mentioned in #254 -* Fixed using a relative URL for `iconUrl` in IE (fixes #269) +- **_(Important)_** `setup()` now returns the element Plyr was setup on rather than the `plyr` object. This means `var player = plyr.setup()[0];` would now be `var player = plyr.setup()[0].plyr;`. This improves support for React and other virtual dom frameworks as mentioned in #254 +- Fixed using a relative URL for `iconUrl` in IE (fixes #269) -# v1.7.0 +## v1.7.0 -* SASS cleanup (fixes #265) -* Docs tidy up to help quick start (fixes #253) -* Fix for issues with data attribute options passing (fixes #257) -* **_(Important)_** Removed the requirement for a wrapper div to setup Plyr and removed the dependency on the `plyr` classname as a JS hook. By default it will now look for `<video>`, `<audio>` and `[data-type]` elements. If you are just calling `setup()` with a `<div class="plyr">` you may want to give it a good test after upgrading. You can probably remove the wrapper div. The reason behind this is to make setup easier for newcomers and prevent the styling being used on unsupported players (because the plyr classname was used as a CSS and JS hook - which isn't ideal) -* Renamed the 'docs' folder to `demo` to avoid confusion - the readme is the docs after all +- SASS cleanup (fixes #265) +- Docs tidy up to help quick start (fixes #253) +- Fix for issues with data attribute options passing (fixes #257) +- **_(Important)_** Removed the requirement for a wrapper div to setup Plyr and removed the dependency on the `plyr` classname as a JS hook. By default it will now look for `<video>`, `<audio>` and `[data-type]` elements. If you are just calling `setup()` with a `<div class="plyr">` you may want to give it a good test after upgrading. You can probably remove the wrapper div. The reason behind this is to make setup easier for newcomers and prevent the styling being used on unsupported players (because the plyr classname was used as a CSS and JS hook - which isn't ideal) +- Renamed the 'docs' folder to `demo` to avoid confusion - the readme is the docs after all -## v1.6.20 +### v1.6.20 -* Fix for multiple sprites being requested (fixes #259) +- Fix for multiple sprites being requested (fixes #259) -## v1.6.19 +### v1.6.19 -* Fix for scroll direction issues on volume control (fixes #258) +- Fix for scroll direction issues on volume control (fixes #258) -## v1.6.18 +### v1.6.18 -* Reduced rounding of seek value from 1 decimal point to 4 (fixes #242) +- Reduced rounding of seek value from 1 decimal point to 4 (fixes #242) -## v1.6.17 +### v1.6.17 -* Added `disableContextMenu` option to hide the right click context menu (fixes #248 and #225) +- Added `disableContextMenu` option to hide the right click context menu (fixes #248 and #225) -## v1.6.16 +### v1.6.16 -* Always hide standard controls (fixes #225) -* Fix for Tooltips overflowing (fixes #230) +- Always hide standard controls (fixes #225) +- Fix for Tooltips overflowing (fixes #230) -## v1.6.15 +### v1.6.15 -* Restore scroll position when exiting full screen (fixes #236) +- Restore scroll position when exiting full screen (fixes #236) -## v1.6.14 +### v1.6.14 -* SVG sprite loading automatically for an easier setup -* Touch devices now show controls on touch rather than pausing playback +- SVG sprite loading automatically for an easier setup +- Touch devices now show controls on touch rather than pausing playback -## v1.6.13 +### v1.6.13 -* Decreased sensitivity and inverted scroll on volume slider (scroll up to increase, down to decrease) +- Decreased sensitivity and inverted scroll on volume slider (scroll up to increase, down to decrease) -## v1.6.12 +### v1.6.12 -* Fix for undefined buffer error -* Add scroll listener on volume slider (PR #227 bty @igoradamenko) +- Fix for undefined buffer error +- Add scroll listener on volume slider (PR #227 bty @igoradamenko) -## v1.6.11 +### v1.6.11 -* Fix for Vimeo fullscreen (fixes #214) +- Fix for Vimeo fullscreen (fixes #214) -## v1.6.10 +### v1.6.10 -* Changed default icon prefix from 'icon' to 'plyr' to avoid clashes +- Changed default icon prefix from 'icon' to 'plyr' to avoid clashes -## v1.6.9 +### v1.6.9 -* Added 'latest' CDN option -* Renamed `sprite.svg` to `plyr.svg` to be inline with the other package files +- Added 'latest' CDN option +- Renamed `sprite.svg` to `plyr.svg` to be inline with the other package files -## v1.6.8 +### v1.6.8 -* Fix for bug introduced in v1.6.7 +- Fix for bug introduced in v1.6.7 -## v1.6.7 +### v1.6.7 -* Fixes for using `source` API method on iOS +- Fixes for using `source` API method on iOS -## v1.6.6 +### v1.6.6 -* Icons cleaned up -* IE11 button fix for tooltips (fixes #210) +- Icons cleaned up +- IE11 button fix for tooltips (fixes #210) -## v1.6.5 +### v1.6.5 -* IE UI bug fixes +- IE UI bug fixes -## v1.6.4 +### v1.6.4 -* Bug fix for undefined progress bar +- Bug fix for undefined progress bar -## v1.6.3 +### v1.6.3 -* Seek back to 0 for all media on ended -* Check for HTML5 video on ended reload -* Update to docs for `showPosterOnEnd` option +- Seek back to 0 for all media on ended +- Check for HTML5 video on ended reload +- Update to docs for `showPosterOnEnd` option -## v1.6.2 +### v1.6.2 -* Fix for tooltip displaying when duration is not set (fixes #177) -* `showPosterOnEnd` option to show poster when HTML5 video ended (fixes #59) -* Error handler for YouTube (fixes #189) -* Initial SoundCloud support (fixes #194) -* Other minor bug fixes +- Fix for tooltip displaying when duration is not set (fixes #177) +- `showPosterOnEnd` option to show poster when HTML5 video ended (fixes #59) +- Error handler for YouTube (fixes #189) +- Initial SoundCloud support (fixes #194) +- Other minor bug fixes -## v1.6.1 +### v1.6.1 -* Tooltip changes for accessibility +- Tooltip changes for accessibility ## v1.6.0 -* New, cleaner, UI: - Controls are now overlaid, maintaining the video's ratio and making sizing easier - A large play button can now be overlaid over videos - Default number of control buttons reduced - New play, pause, rewind and fast forward icons - Flexbox all the things! -* Tidied up the LESS (and SCSS) as part of the above, variables and mixins in seprate files amking customization and upgrades easier -* Toggle mute bug fix; if a player was muted previously and the user refreshed, unmuting would have meant volume was still zero (effectively muted), now the config default value is used. Not ideal but good for now -* New `iconUrl` option allowing specifying a same origin SVG sprite location. Loading this way means you don't need the AJAX sprite loading JavaScript -* `click` option renamed to `clickToPlay` to make it a bit more self explanatory. Unfortunately cross origin SVG sprites is not supported in any browser yet :-( -* `hideControls` is now a global option, rather than being exclusive to fullscreen. Controls are now hidden after 2 seconds of no mouse movement. Controls are always shown when media is paused or stopped. This is defaulted to true. -* `sass` folder in `src` renamed from to `scss` +- New, cleaner, UI: - Controls are now overlaid, maintaining the video's ratio and making sizing easier - A large play button can now be overlaid over videos - Default number of control buttons reduced - New play, pause, rewind and fast forward icons - Flexbox all the things! +- Tidied up the LESS (and SCSS) as part of the above, variables and mixins in seprate files amking customization and upgrades easier +- Toggle mute bug fix; if a player was muted previously and the user refreshed, unmuting would have meant volume was still zero (effectively muted), now the config default value is used. Not ideal but good for now +- New `iconUrl` option allowing specifying a same origin SVG sprite location. Loading this way means you don't need the AJAX sprite loading JavaScript +- `click` option renamed to `clickToPlay` to make it a bit more self explanatory. Unfortunately cross origin SVG sprites is not supported in any browser yet :-( +- `hideControls` is now a global option, rather than being exclusive to fullscreen. Controls are now hidden after 2 seconds of no mouse movement. Controls are always shown when media is paused or stopped. This is defaulted to true. +- `sass` folder in `src` renamed from to `scss` + +### v1.5.21 + +- Bug fix for embeds: `play` not being defined (fixes #185 and #186) -## v1.5.21 +### v1.5.20 -* Bug fix for embeds: `play` not being defined (fixes #185 and #186) +- Bug fix for autoplay option -## v1.5.20 +### v1.5.19 -* Bug fix for autoplay option +- Fix for accessing `embed` property after `ready` event fired -## v1.5.19 +### v1.5.18 -* Fix for accessing `embed` property after `ready` event fired +- Added 'ready' event for initial setup complete or source change occurs +- Fixed SASS stylesheet references to transparentize +- Added default font stack to controls +- Docs fixes inc controls HTML (fixes #180) -## v1.5.18 +### v1.5.17 -* Added 'ready' event for initial setup complete or source change occurs -* Fixed SASS stylesheet references to transparentize -* Added default font stack to controls -* Docs fixes inc controls HTML (fixes #180) +- Expose YouTube and Vimeo API (docs update required) (fixes #176) +- Auto set title based on YouTube getVideoData() title property +- Bug fix for Vimeo API change (Uncaught TypeError: Cannot read property 'value' of undefined) due to a change their end -## v1.5.17 +### v1.5.16 -* Expose YouTube and Vimeo API (docs update required) (fixes #176) -* Auto set title based on YouTube getVideoData() title property -* Bug fix for Vimeo API change (Uncaught TypeError: Cannot read property 'value' of undefined) due to a change their end +- Cancel requests on source change (fixes #174) -## v1.5.16 +### v1.5.15 -* Cancel requests on source change (fixes #174) +- Fix for CustomEvent polyfill and related bug (see #172) -## v1.5.15 +### v1.5.14 -* Fix for CustomEvent polyfill and related bug (see #172) +- Volume storage fix (fixes #171) -## v1.5.14 +### v1.5.13 -* Volume storage fix (fixes #171) +- Fix for manual caption rendering -## v1.5.13 +### v1.5.12 -* Fix for manual caption rendering +- Added a duration option to pass the duration of the file +- Added the ability to set options per element by setting a data-plyr attribute on the target elements (this might be useful for the duration option for example) +- Fixes for Chrome and Safari caption rendering, they now use the default texttrack and cuechange events +- Firefox bug fix for event not defined -## v1.5.12 +### v1.5.11 -* Added a duration option to pass the duration of the file -* Added the ability to set options per element by setting a data-plyr attribute on the target elements (this might be useful for the duration option for example) -* Fixes for Chrome and Safari caption rendering, they now use the default texttrack and cuechange events -* Firefox bug fix for event not defined +- iOS embed bug fixes (fixes #166) +- Hide IE/Edge <input type='range'> tooltip (since we have a styled one) (fixes #160) +- SASS bug fix for default values (fixes #158) -## v1.5.11 +### v1.5.9 -* iOS embed bug fixes (fixes #166) -* Hide IE/Edge <input type='range'> tooltip (since we have a styled one) (fixes #160) -* SASS bug fix for default values (fixes #158) +- NPM bug fixes -## v1.5.9 + v1.5.10 +### v1.5.10 -* NPM bug fixes +- NPM bug fixes -## v1.5.8 +### v1.5.8 -* Fix for touch device seek tooltip -* Seek improvements +- Fix for touch device seek tooltip +- Seek improvements -## v1.5.7 +### v1.5.7 -* Fix for control tooltips always showing +- Fix for control tooltips always showing -## v1.5.6 +### v1.5.6 -* Seek tooltip (option for tooltips changed, please check docs) -* SASS compile error fixes (fixes #148) -* Fullscreen fixes for controls not always hiding/showing (fixes #149) -* Screen reader icon fixes (title was being read twice due to the tooltip/hidden label) +- Seek tooltip (option for tooltips changed, please check docs) +- SASS compile error fixes (fixes #148) +- Fullscreen fixes for controls not always hiding/showing (fixes #149) +- Screen reader icon fixes (title was being read twice due to the tooltip/hidden label) -## v1.5.5 +### v1.5.5 -* Fixed controls.md example -* Bug fix for docs error page -* Bug fix for controls tooltips +- Fixed controls.md example +- Bug fix for docs error page +- Bug fix for controls tooltips -## v1.5.4 +### v1.5.4 -* Minor bug fix for clicking video to play/pause after source change +- Minor bug fix for clicking video to play/pause after source change -## v1.5.3 +### v1.5.3 -* Minor bug fix for occasional display of 0:00 as the media duration +- Minor bug fix for occasional display of 0:00 as the media duration -## v1.5.2 +### v1.5.2 -* `handlers` option renamed to `listeners` -* Added event listeners for all types to the plyr container (playback, fullscreen, captions etc - see docs) -* Removed onSetup config option (use the 'setup' event instead, plyr element is event.plyr) -* Style bug fixes -* Vimeo seek bug fix (requires whole seconds when seeking) -* Fix for fullscreen player (using class hook, not browser fullscreen) +- `handlers` option renamed to `listeners` +- Added event listeners for all types to the plyr container (playback, fullscreen, captions etc - see docs) +- Removed onSetup config option (use the 'setup' event instead, plyr element is event.plyr) +- Style bug fixes +- Vimeo seek bug fix (requires whole seconds when seeking) +- Fix for fullscreen player (using class hook, not browser fullscreen) -## v1.5.1 +### v1.5.1 -* Fix for event listeners being duplicated on source change +- Fix for event listeners being duplicated on source change -# v1.5.0 +## v1.5.0 -* Vimeo support (fixes #8) -* New options for initialization (you can now pass a selector, HTMLElement or NodeList) (fixes #118) -* Switched to BEM methodology (you will need to change CSS and probably HTML) -* Decoupled CSS and JS hooks (fixes #129) -* Custom controls container (fixes #98) -* Fix for private/incognito mode local storage bug (fixes #131) -* UMD module setup (fixes #121) -* Specify iframe title for Vimeo and YouTube (fixes #124) -* Better handling of mission controls (fixes #132) -* Retain classname on source change (fixes #120) -* Increased thumb size on seek (partially fixes #130) -* Passing no argument to `source` api method, now returns current source (by @gurupras) -* Ability to add custom handlers to controls prior to Plyr bindings (by @gurupras) -* Keyboard navigation improvements (focus on seek, focus trap in fullscreen) (fixes #135) +- Vimeo support (fixes #8) +- New options for initialization (you can now pass a selector, HTMLElement or NodeList) (fixes #118) +- Switched to BEM methodology (you will need to change CSS and probably HTML) +- Decoupled CSS and JS hooks (fixes #129) +- Custom controls container (fixes #98) +- Fix for private/incognito mode local storage bug (fixes #131) +- UMD module setup (fixes #121) +- Specify iframe title for Vimeo and YouTube (fixes #124) +- Better handling of mission controls (fixes #132) +- Retain classname on source change (fixes #120) +- Increased thumb size on seek (partially fixes #130) +- Passing no argument to `source` api method, now returns current source (by @gurupras) +- Ability to add custom handlers to controls prior to Plyr bindings (by @gurupras) +- Keyboard navigation improvements (focus on seek, focus trap in fullscreen) (fixes #135) -## v1.3.5 +### v1.3.5 -* Fixed bug with API use on basic supported browsers +- Fixed bug with API use on basic supported browsers -## v1.3.4 +### v1.3.4 -* Code cleanup by @calvintam236 +- Code cleanup by @calvintam236 -## v1.3.3 +### v1.3.3 -* Removed captions being read by screen readers +- Removed captions being read by screen readers -## v1.3.2 +### v1.3.2 -* Voiceover fix for captions +- Voiceover fix for captions -## v1.3.1 +### v1.3.1 -* ARIA improvements for captions being read +- ARIA improvements for captions being read -## v1.3.0 +### v1.3.0 -* Internationalization support (i18n) using default controls (required markup changes to controls) -* ARIA enhancements for controls (required markup changes to controls) -* Captions legibility improvements -* YouTube bug fixes +- Internationalization support (i18n) using default controls (required markup changes to controls) +- ARIA enhancements for controls (required markup changes to controls) +- Captions legibility improvements +- YouTube bug fixes -## v1.2.6 +### v1.2.6 -* SASS updates and fixes (cheers @ChristianPV) +- SASS updates and fixes (cheers @ChristianPV) -## v1.2.5 +### v1.2.5 -* Fix for YouTube quality (let them decide quality) +- Fix for YouTube quality (let them decide quality) -## v1.2.4 +### v1.2.4 -* Fix for omitted kind attribute on <track> (fixes #88) +- Fix for omitted kind attribute on <track> (fixes #88) -## v1.2.3 +### v1.2.3 -* Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native) -* Docs tidy up -* Fullscreen for Safari fix (fixes #96) +- Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native) +- Docs tidy up +- Fullscreen for Safari fix (fixes #96) -## v1.2.2 +### v1.2.2 -* Fix for :focus keyboard vs mouse (fixes #61) -* Fix for caption positioning in full screen (fixes #92) +- Fix for :focus keyboard vs mouse (fixes #61) +- Fix for caption positioning in full screen (fixes #92) -## v1.2.1 +### v1.2.1 -* Tooltip bug fix +- Tooltip bug fix -# v1.2.0 +## v1.2.0 -* Added YouTube support +- Added YouTube support -## v1.1.13 +### v1.1.13 -* Added icon prefix option for when using default controls +- Added icon prefix option for when using default controls -## v1.1.13 +### v1.1.13 -* Logic tweaks for hiding controls in fullscreen +- Logic tweaks for hiding controls in fullscreen -## v1.1.12 +### v1.1.12 -* Bug fix for Chrome Canary +- Bug fix for Chrome Canary -## v1.1.11 +### v1.1.11 -* Bug fix +- Bug fix -## v1.1.10 +### v1.1.10 -* Bug fix +- Bug fix -## v1.1.9 +### v1.1.9 -* Bug fix for 1.1.8 +- Bug fix for 1.1.8 -## v1.1.8 +### v1.1.8 -* setVolume API method improvements (fixes #83) +- setVolume API method improvements (fixes #83) -## v1.1.7 +### v1.1.7 -* Restore classname on destroy() +- Restore classname on destroy() -## v1.1.6 +### v1.1.6 -* New API methods (fixes #77), Fix for non strict mode (fixes #78) +- New API methods (fixes #77), Fix for non strict mode (fixes #78) -## v1.1.5 +### v1.1.5 -* Fix for incorrect `isFullscreen()` return value in Mozilla (fixes #38) +- Fix for incorrect `isFullscreen()` return value in Mozilla (fixes #38) -## v1.1.4 +### v1.1.4 -* Minor bug fixes +- Minor bug fixes -## v1.1.3 +### v1.1.3 -* Fixes for random id used in controls with multiple instances and one call to setup -* Audio player UI improvements +- Fixes for random id used in controls with multiple instances and one call to setup +- Audio player UI improvements -## v1.1.2 +### v1.1.2 -* Added an onSetup callback option -* Added fullscreen API methods `toggleFullscreen()` (must be user iniated), and `isFullscreen()` +- Added an onSetup callback option +- Added fullscreen API methods `toggleFullscreen()` (must be user iniated), and `isFullscreen()` -## v1.1.1 +### v1.1.1 -* Fix for unsupported browser handling -* Fix for config.controls having no effect +- Fix for unsupported browser handling +- Fix for config.controls having no effect ## v1.1.0 -* Added config option to set which controls are shown (if using the default controls html) and better handling of missing controls +- Added config option to set which controls are shown (if using the default controls html) and better handling of missing controls -## v1.0.31 +### v1.0.31 -* Display duration on `metadataloaded` +- Display duration on `metadataloaded` -## v1.0.30 +### v1.0.30 -* Fixed bug with media longer than 60 minutes (fixes #69) +- Fixed bug with media longer than 60 minutes (fixes #69) -## v1.0.29 +### v1.0.29 -* Added option to hide controls on fullscreen (default `true`) while palying, after 1s. Pause, mouse hover on progress, or focus on a child control re-shows the controls. On touch a tap of the video (which plays/pauses the video by default) is required. (fixes #47) -* Fixed a bug with caption toggle in 1.0.28 +- Added option to hide controls on fullscreen (default `true`) while palying, after 1s. Pause, mouse hover on progress, or focus on a child control re-shows the controls. On touch a tap of the video (which plays/pauses the video by default) is required. (fixes #47) +- Fixed a bug with caption toggle in 1.0.28 -## v1.0.28 +### v1.0.28 -* Added API support for browsers that don't have full plyr support (pretty much <=IE9 and `<video>` on iPhone/iPod) +- Added API support for browsers that don't have full plyr support (pretty much <=IE9 and `<video>` on iPhone/iPod) -## v1.0.27 +### v1.0.27 -* Keyboard accessibility improvements (fixes #66) +- Keyboard accessibility improvements (fixes #66) -## v1.0.26 +### v1.0.26 -* Fixes for SASS (cheers @brunowego) -* Indentation reset to 4 spaces +- Fixes for SASS (cheers @brunowego) +- Indentation reset to 4 spaces -## v1.0.25 +### v1.0.25 -* Fixes for iOS volume controls (hidden) -* Classnames for left/right controls changed +- Fixes for iOS volume controls (hidden) +- Classnames for left/right controls changed -## v1.0.24 +### v1.0.24 -* Added tooltip option to display labels as tooltips (fixes #50) +- Added tooltip option to display labels as tooltips (fixes #50) -## v1.0.23 +### v1.0.23 -* Handling loading states in the UI (fixes #36) +- Handling loading states in the UI (fixes #36) -## v1.0.22 +### v1.0.22 -* Added support() API method for checking mimetype support -* Added source() API method for setting media source(s) (fixes #44) -* Added poster() API method for setting poster source -* Refactored captions logic for manual captions +- Added support() API method for checking mimetype support +- Added source() API method for setting media source(s) (fixes #44) +- Added poster() API method for setting poster source +- Refactored captions logic for manual captions -## v1.0.21 +### v1.0.21 -* Added an <input type="range"> for seeking to improve experience (and support dragging) (fixes #40, #42) -* Icons for restart and captions improved (and some IDs changed) (fixes #49) +- Added an <input type="range"> for seeking to improve experience (and support dragging) (fixes #40, #42) +- Icons for restart and captions improved (and some IDs changed) (fixes #49) -## v1.0.20 +### v1.0.20 -* Default controls included (Fixes #45) -* Volume changes on `input` as well as `change` (fixes #43) -* Fix for undefined Play text -* License changed to MIT +- Default controls included (Fixes #45) +- Volume changes on `input` as well as `change` (fixes #43) +- Fix for undefined Play text +- License changed to MIT -## v1.0.19 +### v1.0.19 -* Fixed firefox fullscreen issue (fixes #38) +- Fixed firefox fullscreen issue (fixes #38) -## v1.0.18 +### v1.0.18 -* Added CDN references +- Added CDN references -## v1.0.17 +### v1.0.17 -* SASS support added (thanks to @brunowego) -* Docs completely separated to avoid any confusion -* New gulp tasks (will add more documentation for this) +- SASS support added (thanks to @brunowego) +- Docs completely separated to avoid any confusion +- New gulp tasks (will add more documentation for this) -## v1.0.16 +### v1.0.16 -* Aria label is now dynamic +- Aria label is now dynamic -## v1.0.15 +### v1.0.15 -* Fix for seek time display in controls -* More documentation for controls html +- Fix for seek time display in controls +- More documentation for controls html -## v1.0.14 +### v1.0.14 -* Minor change for bootstrap compatibility +- Minor change for bootstrap compatibility -## v1.0.13 +### v1.0.13 -* Minor tweaks +- Minor tweaks -## v1.0.12 +### v1.0.12 -* Handle native events (issue #34) +- Handle native events (issue #34) -## v1.0.11 +### v1.0.11 -* Bug fixes for fullscreen mode +- Bug fixes for fullscreen mode -## v1.0.10 +### v1.0.10 -* Bower includes src files now -* Folder re-arrangement +- Bower includes src files now +- Folder re-arrangement -## v1.0.9 +### v1.0.9 -* Added buffer progress bar -* Fixed Safari 8 caption track (it needs to be removed from the DOM like in Safari 7) -* Added validation (it works or it doesn't basically) of the `html` option passed +- Added buffer progress bar +- Fixed Safari 8 caption track (it needs to be removed from the DOM like in Safari 7) +- Added validation (it works or it doesn't basically) of the `html` option passed -## v1.0.8 +### v1.0.8 -* Bug fix +- Bug fix -## v1.0.7 +### v1.0.7 -* Storing user selected volume in local storage +- Storing user selected volume in local storage -## v1.0.6 +### v1.0.6 -* Fullscreen fallback for older browsers to use "full window" +- Fullscreen fallback for older browsers to use "full window" -## v1.0.5 +### v1.0.5 -* More minor bug fixes and improvements +- More minor bug fixes and improvements -## v1.0.4 +### v1.0.4 -* Fixed caption legibility issues +- Fixed caption legibility issues -## v1.0.3 +### v1.0.3 -* Minor bug fixes +- Minor bug fixes -## v1.0.2 +### v1.0.2 -* Added OGG to <audio> example for Firefox -* Fixed IE11 fullscreen issues +- Added OGG to <audio> example for Firefox +- Fixed IE11 fullscreen issues -## v1.0.1 +### v1.0.1 -* Bug fixes for IE (as per usual) -* Added CSS hooks for media type -* Return instances of Plyr to the element +- Bug fixes for IE (as per usual) +- Added CSS hooks for media type +- Return instances of Plyr to the element -## v1.0.0 +# v1.0.0 -* Initial release +- Initial release diff --git a/contributing.md b/contributing.md new file mode 100644 index 00000000..5759fb04 --- /dev/null +++ b/contributing.md @@ -0,0 +1,40 @@ +# Contributing + +We welcome bug reports, feature requests and pull requests. If you want to help us out, please follow these guidelines, in order to avoid redundant work. + +## Support + +Before asking questions, read our [documentation](https://github.com/sampotts/plyr) and [FAQ](https://github.com/sampotts/plyr/wiki/FAQ). + +If these doesn't answer your question +* Use [Stack Overflow](https://stackoverflow.com/) for questions that doesn't directly involve Plyr. This includes for example how to use Javascript, CSS or HTML5 media in general, and how to use other frameworks, libraries and technology. +* Use [our Slack](https://bit.ly/plyr-chat) if you need help using Plyr or have questions about Plyr. + +## Commenting +When commenting, keep a civil tone and stay on topic. Don't ask for [support](#support), or post "+1" or "I agree" type of comments. Use the emojis instead. + +Asking for the status on issues is discouraged. Unless someone has explicitly said in an issue that it's work in progress, most likely that means no one is working on it. We have a lot to do, and it may not be a top priority for us. + +We *may* moderate discussions. We do this to avoid threads being "hijacked", to avoid confusion in case the content is misleading or outdated, and to avoid bothering people with github notifications. + +## Creating issues + +Please follow the instructions in our issue templates. Don't use github issues to ask for [support](#support). + +## Contributing features and documentation + +* If you want to add a feature or make critical changes, you may want to ensure that this is something we also want (so you don't waste your time). Ask us about this in the corresponding issue if there is one, or on [our Slack](https://bit.ly/plyr-chat) otherwise. + +* Fork Plyr, and create a new branch in your fork, based on the **develop** branch + +* To test locally, you can use the demo. First make sure you have installed the dependencies with `npm install` or `yarn`. Run `gulp` to build while you are working, and run a local server from the repository root directory. If you have Python installed, this command should work: `python -m SimpleHTTPServer 8080`. Then go to `http://localhost:8080/demo/` + +* Develop and test your modifications. + +* Preferably commit your changes as independent logical chunks, with meaningful messages. Make sure you do not commit unnecessary files or changes, such as the build output, or logging and breakpoints you added for testing. + +* If your modifications changes the documented behavior or add new features, document these changes in readme.md. + +* When finished, push the changes to your GitHub repository and send a pull request to **develop**. Describe what your PR does. + +* If the Travis build fails, or if you get a code review with change requests, you can fix these by pushing new or rebased commits to the branch. diff --git a/controls.md b/controls.md index d8adc089..b7b08c58 100644 --- a/controls.md +++ b/controls.md @@ -2,9 +2,11 @@ This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs. You can pass the following to the `controls` option: -* `Array` of options (this builds the default controls based on your choices) -* `String` containing the desired HTML -* `Function` that will be executed and should return one of the above +- `Array` of options (this builds the default controls based on your choices) +- `Element` with the controls +- `String` containing the desired HTML +- `false` (or empty string or array) to disable all controls +- `Function` that will be executed and should return one of the above ## Using default controls @@ -26,6 +28,7 @@ controls: [ 'settings', // Settings menu 'pip', // Picture-in-picture (currently Safari only) 'airplay', // Airplay (currently Safari only) + 'download', // Show a download button with a link to either the current source or a custom URL you specify in your options 'fullscreen', // Toggle fullscreen ]; ``` @@ -81,14 +84,14 @@ The classes and data attributes used in your template should match the `selector You need to add several placeholders to your HTML template that are replaced when rendering: -* `{id}` - the dynamically generated ID for the player (for form controls) -* `{seektime}` - the seek time specified in options for fast forward and rewind -* `{title}` - the title of your media, if specified +- `{id}` - the dynamically generated ID for the player (for form controls) +- `{seektime}` - the seek time specified in options for fast forward and rewind +- `{title}` - the title of your media, if specified ### Limitations -* Currently the settings menus are not supported with custom controls HTML -* AirPlay and PiP buttons can be added but you will have to manage feature detection +- Currently the settings menus are not supported with custom controls HTML +- AirPlay and PiP buttons can be added but you will have to manage feature detection ### Example @@ -105,7 +108,7 @@ const controls = ` <svg role="presentation"><use xlink:href="#plyr-rewind"></use></svg> <span class="plyr__tooltip" role="tooltip">Rewind {seektime} secs</span> </button> - <button type="button" class="plyr__control" aria-pressed="false" aria-label="Play, {title}" data-plyr="play"> + <button type="button" class="plyr__control" aria-label="Play, {title}" data-plyr="play"> <svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-pause"></use></svg> <svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-play"></use></svg> <span class="label--pressed plyr__tooltip" role="tooltip">Pause</span> @@ -116,30 +119,28 @@ const controls = ` <span class="plyr__tooltip" role="tooltip">Forward {seektime} secs</span> </button> <div class="plyr__progress"> - <label for="plyr-seek-{id}" class="plyr__sr-only">Seek</label> - <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="0" id="plyr-seek-{id}"> - <progress class="plyr__progress--buffer" min="0" max="100" value="0">% buffered</progress> + <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="0" aria-label="Seek"> + <progress class="plyr__progress__buffer" min="0" max="100" value="0">% buffered</progress> <span role="tooltip" class="plyr__tooltip">00:00</span> </div> <div class="plyr__time plyr__time--current" aria-label="Current time">00:00</div> <div class="plyr__time plyr__time--duration" aria-label="Duration">00:00</div> - <button type="button" class="plyr__control" aria-pressed="false" aria-label="Mute" data-plyr="mute"> + <button type="button" class="plyr__control" aria-label="Mute" data-plyr="mute"> <svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-muted"></use></svg> <svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-volume"></use></svg> <span class="label--pressed plyr__tooltip" role="tooltip">Unmute</span> <span class="label--not-pressed plyr__tooltip" role="tooltip">Mute</span> </button> <div class="plyr__volume"> - <label for="plyr-volume-{id}" class="plyr__sr-only">Volume</label> - <input data-plyr="volume" type="range" min="0" max="1" step="0.05" value="1" autocomplete="off" id="plyr-volume-{id}"> + <input data-plyr="volume" type="range" min="0" max="1" step="0.05" value="1" autocomplete="off" aria-label="Volume"> </div> - <button type="button" class="plyr__control" aria-pressed="true" aria-label="Enable captions" data-plyr="captions"> + <button type="button" class="plyr__control" data-plyr="captions"> <svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-captions-on"></use></svg> <svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-captions-off"></use></svg> <span class="label--pressed plyr__tooltip" role="tooltip">Disable captions</span> <span class="label--not-pressed plyr__tooltip" role="tooltip">Enable captions</span> </button> - <button type="button" class="plyr__control" aria-pressed="false" aria-label="Enter fullscreen" data-plyr="fullscreen"> + <button type="button" class="plyr__control" data-plyr="fullscreen"> <svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-exit-fullscreen"></use></svg> <svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-enter-fullscreen"></use></svg> <span class="label--pressed plyr__tooltip" role="tooltip">Exit fullscreen</span> diff --git a/demo/dist/demo.css b/demo/dist/demo.css index d8e05728..4ef903f9 100644 --- a/demo/dist/demo.css +++ b/demo/dist/demo.css @@ -1 +1 @@ -@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:300;src:url(https://cdn.plyr.io/static/fonts/gordita-light.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-light.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:400;src:url(https://cdn.plyr.io/static/fonts/gordita-regular.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:500;src:url(https://cdn.plyr.io/static/fonts/gordita-medium.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-medium.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:600;src:url(https://cdn.plyr.io/static/fonts/gordita-bold.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:900;src:url(https://cdn.plyr.io/static/fonts/gordita-black.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-black.woff) format("woff")}@keyframes fadein{0%{opacity:0}100%{opacity:1}}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a,button.faux-link{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}*,::after,::before{box-sizing:border-box}body,html{display:flex;width:100%}html{background:linear-gradient(to left top,#4dc1ff,#0074b3);background-attachment:fixed;height:100%}body{align-items:center;display:flex;flex-direction:column;min-height:100%}.grid{flex:1;overflow:auto}main{margin:auto;padding-bottom:1px;text-align:center}aside{align-items:center;background:#fff;color:#55646b;display:flex;flex-shrink:0;justify-content:center;padding:15px;position:relative;text-align:center;text-shadow:none;width:100%}aside .icon{fill:#4baaf4;margin-right:10px}aside p{margin:0}aside a,aside button.faux-link{color:#4baaf4}aside a.tab-focus,aside button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(75,170,244,.35);outline:0}.grid{margin:0 auto;padding:20px}@media only screen and (min-width:768px){.grid{align-items:center;display:flex;max-width:1280px;width:100%}.grid>*{flex:1}}html{font-size:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:15px;font-size:.9375rem;color:#fff;font-family:Gordita,Avenir,"Helvetica Neue",sans-serif;font-weight:500;line-height:1.75;text-shadow:0 1px 1px rgba(0,0,0,.15)}button,input,select,textarea{font:inherit}p,small{margin:0 0 20px}small{font-size:13px;font-size:.8125rem;display:block}h1{font-size:64px;font-size:4rem;font-weight:600;letter-spacing:-.025em;line-height:1.2;margin:0 0 20px}.button,.button__count{align-items:center;background:#fff;border:0;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.1);color:#55646b;display:inline-flex;padding:15px;position:relative;text-shadow:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}.button{font-weight:600;padding-left:20px;padding-right:20px;transition:all .2s ease}.button:focus,.button:hover{color:#343f4a}.button:focus::after,.button:hover::after{display:none}.button:hover{box-shadow:0 2px 2px rgba(0,0,0,.1);transform:translateY(-1px)}.button:focus{outline:0}.button.tab-focus{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}.button:active{transform:translateY(1px)}.button--with-count{display:inline-flex}.button--with-count .button .icon{flex-shrink:0}.button__count{animation:fadein .2s ease;margin-left:10px}.button__count::before{border:5px solid transparent;border-left-width:0;border-right-color:#fff;content:'';height:0;position:absolute;right:100%;top:50%;transform:translateY(-50%);width:0}header{padding-bottom:20px;text-align:center}header .call-to-action{margin-top:30px}@media only screen and (min-width:768px){header{margin-right:60px;max-width:360px;padding-bottom:40px;text-align:left}}.icon{fill:currentColor;height:16px;vertical-align:-3px;width:16px}a svg,button svg,button.faux-link svg,label svg{pointer-events:none}.btn .icon,a .icon,button.faux-link .icon{margin-right:6px}button.faux-link{background:0 0;border:0;border-radius:0;cursor:pointer;font:inherit;line-height:1.75;margin:0;padding:0;position:relative;text-align:inherit;text-shadow:inherit;-moz-user-select:text;vertical-align:baseline;width:auto}a,button.faux-link{border-bottom:1px dotted currentColor;color:#fff;font-weight:600;position:relative;text-decoration:none;transition:all .2s ease}a::after,button.faux-link::after{background:currentColor;content:'';height:1px;left:50%;position:absolute;top:100%;transform:translateX(-50%);transition:width .2s ease;width:0}a:focus,a:hover,button.faux-link:focus,button.faux-link:hover{border-bottom-color:transparent;outline:0}a:focus::after,a:hover::after,button.faux-link:focus::after,button.faux-link:hover::after{width:100%}a.tab-focus,button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}a.no-border::after,button.no-border.faux-link::after{display:none}li,ul{list-style:none;margin:0;padding:0}audio,img,video{max-width:100%;vertical-align:middle}nav{display:flex;justify-content:center;margin-bottom:20px}video{max-width:100%;vertical-align:middle}.plyr{border-radius:4px;box-shadow:0 2px 5px rgba(0,0,0,.2);margin:20px auto}.plyr.plyr--audio{max-width:480px}.plyr__video-wrapper::after{border:1px solid rgba(0,0,0,.15);border-radius:inherit;bottom:0;content:'';left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:3}.plyr__cite{display:none;margin-top:20px}.plyr__cite .icon{margin-right:4px}.plyr--audio~ul .plyr__cite--audio,.plyr--video:not(.plyr--youtube):not(.plyr--vimeo)~ul .plyr__cite--video,.plyr--vimeo~ul .plyr__cite--vimeo,.plyr--youtube~ul .plyr__cite--youtube{display:block}@keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-family:inherit;font-variant-numeric:tabular-nums;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui button.faux-link,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:#fff;font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:12px;left:0;padding:10px;position:absolute;text-align:center;transform:translateY(-40px);transition:transform .4s ease-in-out;width:100%}.plyr__captions span{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions span div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:13px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr--hide-controls .plyr__captions{transform:translateY(-15px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__control[aria-pressed=false] .icon--pressed,.plyr__control[aria-pressed=false] .label--pressed,.plyr__control[aria-pressed=true] .icon--not-pressed,.plyr__control[aria-pressed=true] .label--not-pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{height:20px;left:2px;position:relative;width:20px}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu:first-child,.plyr__controls .plyr__menu:first-child+[data-plyr=pause],.plyr__controls .plyr__progress:first-child,.plyr__controls .plyr__progress:first-child+[data-plyr=pause],.plyr__controls .plyr__time:first-child,.plyr__controls .plyr__time:first-child+[data-plyr=pause],.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0}.plyr__controls .plyr__volume{margin-left:5px}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:10px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:5px}}.plyr--video .plyr__controls{background:linear-gradient(transparent,rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:35px 10px 10px;position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:2}.plyr--video .plyr__controls .plyr__control svg{-webkit-filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15));filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__controls .plyr__control.plyr__tab-focus,.plyr--video .plyr__controls .plyr__control:hover,.plyr--video .plyr__controls .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%;position:relative}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr--full-ui .plyr__video-embed iframe{pointer-events:none}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:13px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container ul{list-style:none;margin:0;overflow:hidden;padding:7px}.plyr__menu__container ul li{margin-top:2px}.plyr__menu__container ul li:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4f5b5f;display:flex;font-size:13px;padding:4px 14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container label.plyr__control{padding-left:7px}.plyr__menu__container label.plyr__control input[type=radio]+span{background:rgba(0,0,0,.1);border-radius:100%;display:block;flex-shrink:0;height:16px;margin-right:10px;position:relative;transition:all .3s ease;width:16px}.plyr__menu__container label.plyr__control input[type=radio]+span::after{background:#fff;border-radius:100%;content:'';height:6px;left:5px;opacity:0;position:absolute;top:5px;transform:scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container label.plyr__control input[type=radio]:checked+span{background:#1aafff}.plyr__menu__container label.plyr__control input[type=radio]:checked+span::after{opacity:1;transform:scale(1)}.plyr__menu__container label.plyr__control input[type=radio]:focus+span{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__menu__container label.plyr__control.plyr__tab-focus input[type=radio]+span,.plyr__menu__container label.plyr__control:hover input[type=radio]+span{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:-7px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr__progress{display:flex;flex:1;position:relative}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:11px;left:0}.plyr__progress--buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:6px;left:0;margin:-3px 0 0;padding:0;position:absolute;top:50%;width:100%}.plyr__progress--buffer::-webkit-progress-bar{background:0 0;transition:width .2s ease}.plyr__progress--buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:6px}.plyr__progress--buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:6px;transition:width .2s ease}.plyr__progress--buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress--buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress--buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress--buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress--buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress--buffer{background-color:rgba(183,197,205,.66)}.plyr__poster{background-color:#000;background-position:50% 50%;background-repeat:no-repeat;background-size:100% 100%;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr--stopped .plyr__poster{opacity:1}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:28px;color:#1aafff;display:block;height:20px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-webkit-user-select:none;user-select:none;background-image:linear-gradient(to right,currentColor var(--value,0),transparent var(--value,0))}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:3px;height:6px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr__time{font-size:11px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:12px;font-weight:500;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;white-space:nowrap;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translate(0,10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{right:0;transform:translate(0,10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0,0) scale(1)}.plyr--video{overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__volume{flex:1;position:relative}.plyr__volume input[type=range]{position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:50px}}@media (min-width:768px){.plyr__volume{max-width:80px}}.plyr--is-ios .plyr__volume{display:none!important}.plyr--is-ios.plyr--vimeo [data-plyr=mute]{display:none!important}.plyr--has-error{pointer-events:none}.plyr--has-error::after{align-items:center;background:#000;color:#fff;content:attr(data-plyr-error);display:flex;font-size:13px;height:100%;justify-content:center;left:0;position:absolute;text-align:center;text-shadow:0 1px 1px #000;top:0;width:100%;z-index:10}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:fullscreen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback .plyr__video-embed{overflow:visible}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads::after{background:rgba(47,52,61,.8);border-radius:2px;bottom:10px;color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;z-index:3}.plyr__ads::after:empty{display:none}.plyr__cues{background:currentColor;display:block;height:6px;left:0;margin:-3px 0 0;opacity:.8;position:absolute;top:50%;width:3px;z-index:3}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}.no-border{border:0}[hidden]{display:none}.sr-only{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;opacity:.001;overflow:hidden;padding:0;position:absolute;width:1px}
\ No newline at end of file +@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:300;src:url(https://cdn.plyr.io/static/fonts/gordita-light.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-light.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:400;src:url(https://cdn.plyr.io/static/fonts/gordita-regular.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:500;src:url(https://cdn.plyr.io/static/fonts/gordita-medium.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-medium.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:600;src:url(https://cdn.plyr.io/static/fonts/gordita-bold.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:900;src:url(https://cdn.plyr.io/static/fonts/gordita-black.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-black.woff) format("woff")}@keyframes fadein{0%{opacity:0}100%{opacity:1}}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a,button.faux-link{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}*,::after,::before{box-sizing:border-box}body,html{display:flex;width:100%}html{background:linear-gradient(to left top,#4dc1ff,#0074b3);background-attachment:fixed;height:100%}body{align-items:center;display:flex;flex-direction:column;min-height:100%}.grid{flex:1;overflow:auto}main{margin:auto;padding-bottom:1px;text-align:center}aside{align-items:center;background:#fff;color:#55646b;display:flex;flex-shrink:0;justify-content:center;padding:15px;position:relative;text-align:center;text-shadow:none;width:100%}aside .icon{fill:#4baaf4;margin-right:10px}aside p{margin:0}aside a,aside button.faux-link{color:#4baaf4}aside a.tab-focus,aside button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(75,170,244,.35);outline:0}.grid{margin:0 auto;padding:20px}@media only screen and (min-width:768px){.grid{align-items:center;display:flex;max-width:1260px;width:100%}.grid>*{flex:1}}html{font-size:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:15px;font-size:.9375rem;color:#fff;font-family:Gordita,Avenir,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-weight:500;line-height:1.75;text-shadow:0 1px 1px rgba(0,0,0,.15)}button,input,select,textarea{font:inherit}p,small{margin:0 0 20px}small{font-size:13px;font-size:.8125rem;display:block}h1{font-size:64px;font-size:4rem;font-weight:600;letter-spacing:-.025em;line-height:1.2;margin:0 0 20px}.button,.button__count{align-items:center;background:#fff;border:0;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.1);color:#55646b;display:inline-flex;padding:15px;position:relative;text-shadow:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}.button{font-weight:600;padding-left:20px;padding-right:20px;transition:all .2s ease}.button:focus,.button:hover{color:#343f4a}.button:focus::after,.button:hover::after{display:none}.button:hover{box-shadow:0 2px 2px rgba(0,0,0,.1);transform:translateY(-1px)}.button:focus{outline:0}.button.tab-focus{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}.button:active{transform:translateY(1px)}.button--with-count{display:inline-flex}.button--with-count .button .icon{flex-shrink:0}.button__count{animation:fadein .2s ease;margin-left:10px}.button__count::before{border:5px solid transparent;border-left-width:0;border-right-color:#fff;content:'';height:0;position:absolute;right:100%;top:50%;transform:translateY(-50%);width:0}header{padding-bottom:20px;text-align:center}header .call-to-action{margin-top:30px}@media only screen and (min-width:768px){header{margin-right:60px;max-width:360px;padding-bottom:40px;text-align:left}}.icon{fill:currentColor;height:16px;vertical-align:-3px;width:16px}a svg,button svg,button.faux-link svg,label svg{pointer-events:none}.btn .icon,a .icon,button.faux-link .icon{margin-right:6px}button.faux-link{background:0 0;border:0;border-radius:0;cursor:pointer;font:inherit;line-height:1.75;margin:0;padding:0;position:relative;text-align:inherit;text-shadow:inherit;-moz-user-select:text;vertical-align:baseline;width:auto}a,button.faux-link{border-bottom:1px dotted currentColor;color:#fff;font-weight:600;position:relative;text-decoration:none;transition:all .2s ease}a::after,button.faux-link::after{background:currentColor;content:'';height:1px;left:50%;position:absolute;top:100%;transform:translateX(-50%);transition:width .2s ease;width:0}a:focus,a:hover,button.faux-link:focus,button.faux-link:hover{border-bottom-color:transparent;outline:0}a:focus::after,a:hover::after,button.faux-link:focus::after,button.faux-link:hover::after{width:100%}a.tab-focus,button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}a.no-border::after,button.no-border.faux-link::after{display:none}li,ul{list-style:none;margin:0;padding:0}audio,img,video{max-width:100%;vertical-align:middle}nav{display:flex;justify-content:center;margin-bottom:20px}video{max-width:100%;vertical-align:middle}.plyr{border-radius:4px;box-shadow:0 2px 5px rgba(0,0,0,.2);margin:20px auto}.plyr.plyr--audio{max-width:480px}.plyr__video-wrapper::after{border:1px solid rgba(0,0,0,.15);border-radius:inherit;bottom:0;content:'';left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:3}.plyr__cite{display:none;margin-top:20px}.plyr__cite .icon{margin-right:4px}.plyr--audio~ul .plyr__cite--audio,.plyr--video:not(.plyr--youtube):not(.plyr--vimeo)~ul .plyr__cite--video,.plyr--vimeo~ul .plyr__cite--vimeo,.plyr--youtube~ul .plyr__cite--youtube{display:block}@keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-family:inherit;font-variant-numeric:tabular-nums;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui button.faux-link,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:#fff;font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:12px;left:0;padding:10px;position:absolute;text-align:center;transition:transform .4s ease-in-out;width:100%}.plyr__captions .plyr__caption{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions .plyr__caption div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:13px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty)~.plyr__captions{transform:translateY(-40px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}a.plyr__control,button.plyr__control.faux-link{text-decoration:none}a.plyr__control::after,a.plyr__control::before,button.plyr__control.faux-link::after,button.plyr__control.faux-link::before{display:none}.plyr__control.plyr__control--pressed .icon--not-pressed,.plyr__control.plyr__control--pressed .label--not-pressed,.plyr__control:not(.plyr__control--pressed) .icon--pressed,.plyr__control:not(.plyr__control--pressed) .label--pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--video .plyr__control svg{filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__control.plyr__tab-focus,.plyr--video .plyr__control:hover,.plyr--video .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{left:2px;position:relative}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;justify-content:flex-end;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls .plyr__volume,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls .plyr__progress+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:2px}.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0;margin-right:auto}.plyr__controls:empty{display:none}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls .plyr__volume,.plyr__controls>.plyr__control{margin-left:10px}}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video .plyr__controls{background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:20px 5px 5px;position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:3}@media (min-width:480px){.plyr--video .plyr__controls{padding:35px 10px 10px}}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%;position:relative}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:13px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container [role=menu]{padding:7px}.plyr__menu__container [role=menuitem],.plyr__menu__container [role=menuitemradio]{margin-top:2px}.plyr__menu__container [role=menuitem]:first-child,.plyr__menu__container [role=menuitemradio]:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4f5b5f;display:flex;font-size:13px;padding:4px 11px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control>span{align-items:inherit;display:flex;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container .plyr__control[role=menuitemradio]{padding-left:7px}.plyr__menu__container .plyr__control[role=menuitemradio]::after,.plyr__menu__container .plyr__control[role=menuitemradio]::before{border-radius:100%}.plyr__menu__container .plyr__control[role=menuitemradio]::before{background:rgba(0,0,0,.1);content:'';display:block;flex-shrink:0;height:16px;margin-right:10px;transition:all .3s ease;width:16px}.plyr__menu__container .plyr__control[role=menuitemradio]::after{background:#fff;border:0;height:6px;left:12px;opacity:0;top:50%;transform:translateY(-50%) scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before{background:#1aafff}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::after{opacity:1;transform:translateY(-50%) scale(1)}.plyr__menu__container .plyr__control[role=menuitemradio].plyr__tab-focus::before,.plyr__menu__container .plyr__control[role=menuitemradio]:hover::before{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:-5px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:26px;color:#1aafff;display:block;height:19px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-webkit-user-select:none;user-select:none;background-image:linear-gradient(to right,currentColor var(--value,0),transparent var(--value,0))}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:2.5px;height:5px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr__poster{background-color:#000;background-position:50% 50%;background-repeat:no-repeat;background-size:contain;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .2s ease;width:100%;z-index:1}.plyr--stopped.plyr__poster-enabled .plyr__poster{opacity:1}.plyr__time{font-size:11px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:12px;font-weight:500;left:50%;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;white-space:nowrap;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translate(0,10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{left:auto;right:0;transform:translate(0,10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0,0) scale(1)}.plyr--video{background:#000;overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__progress{flex:1;left:6.5px;margin-right:13px;position:relative}.plyr__progress input[type=range],.plyr__progress__buffer{margin-left:-6.5px;margin-right:-6.5px;width:calc(100% + 13px)}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:11px;left:0}.plyr__progress__buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:5px;left:0;margin-top:-2.5px;padding:0;position:absolute;top:50%}.plyr__progress__buffer::-webkit-progress-bar{background:0 0}.plyr__progress__buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:5px;transition:width .2s ease}.plyr__progress__buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:5px;transition:width .2s ease}.plyr__progress__buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress__buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress__buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress__buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress__buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress__buffer{background-color:rgba(183,197,205,.66)}.plyr__volume{align-items:center;display:flex;flex:1;position:relative}.plyr__volume input[type=range]{margin-left:5px;position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:90px}}@media (min-width:768px){.plyr__volume{max-width:110px}}.plyr--is-ios .plyr__volume{display:none!important}.plyr--is-ios.plyr--vimeo [data-plyr=mute]{display:none!important}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads::after{background:rgba(47,52,61,.8);border-radius:2px;bottom:10px;color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;z-index:3}.plyr__ads::after:empty{display:none}.plyr__cues{background:currentColor;display:block;height:5px;left:0;margin:-2.5px 0 0;opacity:.8;position:absolute;top:50%;width:3px;z-index:3}.plyr__preview-thumb{background-color:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);margin-bottom:10px;opacity:0;padding:3px;pointer-events:none;position:absolute;transform:translate(0,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;z-index:2}.plyr__preview-thumb--is-shown{opacity:1;transform:translate(0,0) scale(1)}.plyr__preview-thumb::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr__preview-thumb__image-container{background:#b7c5cd;border-radius:2px;overflow:hidden;position:relative;z-index:0}.plyr__preview-thumb__image-container img{height:100%;left:0;max-height:none;max-width:none;position:absolute;top:0;width:100%}.plyr__preview-thumb__time-container{bottom:6px;left:0;position:absolute;right:0;white-space:nowrap;z-index:3}.plyr__preview-thumb__time-container span{background-color:rgba(0,0,0,.55);border-radius:2px;color:#fff;font-size:11px;padding:3px 6px}.plyr__preview-scrubbing{bottom:0;filter:blur(1px);height:100%;left:0;margin:auto;opacity:0;overflow:hidden;position:absolute;right:0;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr__preview-scrubbing--is-shown{opacity:1}.plyr__preview-scrubbing img{height:100%;left:0;max-height:none;max-width:none;-o-object-fit:contain;object-fit:contain;position:absolute;top:0;width:100%}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}.plyr [hidden]{display:none!important}.no-border{border:0}[hidden]{display:none}.sr-only{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;opacity:.001;overflow:hidden;padding:0;position:absolute;width:1px}
\ No newline at end of file diff --git a/demo/dist/demo.js b/demo/dist/demo.js index aebe368c..4790e762 100644 --- a/demo/dist/demo.js +++ b/demo/dist/demo.js @@ -1,4190 +1,12918 @@ -(function () { -'use strict'; - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var stringify_1 = createCommonjsModule(function (module, exports) { -/* - json-stringify-safe - Like JSON.stringify, but doesn't throw on circular references. - - Originally forked from https://github.com/isaacs/json-stringify-safe - version 5.0.1 on 3/8/2017 and modified to handle Errors serialization - and IE8 compatibility. Tests for this are in test/vendor. - - ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE -*/ - -exports = module.exports = stringify; -exports.getSerialize = serializer; - -function indexOf(haystack, needle) { - for (var i = 0; i < haystack.length; ++i) { - if (haystack[i] === needle) return i; - } - return -1; -} - -function stringify(obj, replacer, spaces, cycleReplacer) { - return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces); -} - -// https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106 -function stringifyError(value) { - var err = { - // These properties are implemented as magical getters and don't show up in for in - stack: value.stack, - message: value.message, - name: value.name - }; - - for (var i in value) { - if (Object.prototype.hasOwnProperty.call(value, i)) { - err[i] = value[i]; - } - } - - return err; -} - -function serializer(replacer, cycleReplacer) { - var stack = []; - var keys = []; - - if (cycleReplacer == null) { - cycleReplacer = function(key, value) { - if (stack[0] === value) { - return '[Circular ~]'; - } - return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']'; - }; - } - - return function(key, value) { - if (stack.length > 0) { - var thisPos = indexOf(stack, this); - ~thisPos ? stack.splice(thisPos + 1) : stack.push(this); - ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key); - - if (~indexOf(stack, value)) { - value = cycleReplacer.call(this, key, value); - } - } else { - stack.push(value); - } - - return replacer == null - ? value instanceof Error ? stringifyError(value) : value - : replacer.call(this, key, value); - }; -} -}); -var stringify_2 = stringify_1.getSerialize; - -var _window = - typeof window !== 'undefined' - ? window - : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; - -function isObject(what) { - return typeof what === 'object' && what !== null; -} - -// Yanked from https://git.io/vS8DV re-used under CC0 -// with some tiny modifications -function isError(value) { - switch ({}.toString.call(value)) { - case '[object Error]': - return true; - case '[object Exception]': - return true; - case '[object DOMException]': - return true; - default: - return value instanceof Error; - } -} - -function isErrorEvent(value) { - return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]'; -} - -function isUndefined(what) { - return what === void 0; -} - -function isFunction(what) { - return typeof what === 'function'; -} - -function isPlainObject(what) { - return Object.prototype.toString.call(what) === '[object Object]'; -} - -function isString(what) { - return Object.prototype.toString.call(what) === '[object String]'; -} - -function isArray(what) { - return Object.prototype.toString.call(what) === '[object Array]'; -} - -function isEmptyObject(what) { - if (!isPlainObject(what)) return false; - - for (var _ in what) { - if (what.hasOwnProperty(_)) { - return false; - } - } - return true; -} - -function supportsErrorEvent() { - try { - new ErrorEvent(''); // eslint-disable-line no-new - return true; - } catch (e) { - return false; - } -} - -function supportsFetch() { - if (!('fetch' in _window)) return false; - - try { - new Headers(); // eslint-disable-line no-new - new Request(''); // eslint-disable-line no-new - new Response(); // eslint-disable-line no-new - return true; - } catch (e) { - return false; - } -} - -// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default -// https://caniuse.com/#feat=referrer-policy -// It doesn't. And it throw exception instead of ignoring this parameter... -// REF: https://github.com/getsentry/raven-js/issues/1233 -function supportsReferrerPolicy() { - if (!supportsFetch()) return false; - - try { - // eslint-disable-next-line no-new - new Request('pickleRick', { - referrerPolicy: 'origin' - }); - return true; - } catch (e) { - return false; - } -} - -function supportsPromiseRejectionEvent() { - return typeof PromiseRejectionEvent === 'function'; -} - -function wrappedCallback(callback) { - function dataCallback(data, original) { - var normalizedData = callback(data) || data; - if (original) { - return original(normalizedData) || normalizedData; - } - return normalizedData; - } - - return dataCallback; -} - -function each(obj, callback) { - var i, j; - - if (isUndefined(obj.length)) { - for (i in obj) { - if (hasKey(obj, i)) { - callback.call(null, i, obj[i]); - } - } - } else { - j = obj.length; - if (j) { - for (i = 0; i < j; i++) { - callback.call(null, i, obj[i]); - } - } - } -} - -function objectMerge(obj1, obj2) { - if (!obj2) { - return obj1; - } - each(obj2, function(key, value) { - obj1[key] = value; - }); - return obj1; -} - -/** - * This function is only used for react-native. - * react-native freezes object that have already been sent over the - * js bridge. We need this function in order to check if the object is frozen. - * So it's ok that objectFrozen returns false if Object.isFrozen is not - * supported because it's not relevant for other "platforms". See related issue: - * https://github.com/getsentry/react-native-sentry/issues/57 - */ -function objectFrozen(obj) { - if (!Object.isFrozen) { - return false; - } - return Object.isFrozen(obj); -} - -function truncate(str, max) { - if (typeof max !== 'number') { - throw new Error('2nd argument to `truncate` function should be a number'); - } - if (typeof str !== 'string' || max === 0) { - return str; - } - return str.length <= max ? str : str.substr(0, max) + '\u2026'; -} - -/** - * hasKey, a better form of hasOwnProperty - * Example: hasKey(MainHostObject, property) === true/false - * - * @param {Object} host object to check property - * @param {string} key to check - */ -function hasKey(object, key) { - return Object.prototype.hasOwnProperty.call(object, key); -} - -function joinRegExp(patterns) { - // Combine an array of regular expressions and strings into one large regexp - // Be mad. - var sources = [], - i = 0, - len = patterns.length, - pattern; - - for (; i < len; i++) { - pattern = patterns[i]; - if (isString(pattern)) { - // If it's a string, we need to escape it - // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions - sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')); - } else if (pattern && pattern.source) { - // If it's a regexp already, we want to extract the source - sources.push(pattern.source); - } - // Intentionally skip other cases - } - return new RegExp(sources.join('|'), 'i'); -} - -function urlencode(o) { - var pairs = []; - each(o, function(key, value) { - pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - }); - return pairs.join('&'); -} - -// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B -// intentionally using regex and not <a/> href parsing trick because React Native and other -// environments where DOM might not be available -function parseUrl(url) { - if (typeof url !== 'string') return {}; - var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/); - - // coerce to undefined values to empty string so we don't get 'undefined' - var query = match[6] || ''; - var fragment = match[8] || ''; - return { - protocol: match[2], - host: match[4], - path: match[5], - relative: match[5] + query + fragment // everything minus origin - }; -} -function uuid4() { - var crypto = _window.crypto || _window.msCrypto; - - if (!isUndefined(crypto) && crypto.getRandomValues) { - // Use window.crypto API if available - // eslint-disable-next-line no-undef - var arr = new Uint16Array(8); - crypto.getRandomValues(arr); - - // set 4 in byte 7 - arr[3] = (arr[3] & 0xfff) | 0x4000; - // set 2 most significant bits of byte 9 to '10' - arr[4] = (arr[4] & 0x3fff) | 0x8000; - - var pad = function(num) { - var v = num.toString(16); - while (v.length < 4) { - v = '0' + v; - } - return v; - }; - - return ( - pad(arr[0]) + - pad(arr[1]) + - pad(arr[2]) + - pad(arr[3]) + - pad(arr[4]) + - pad(arr[5]) + - pad(arr[6]) + - pad(arr[7]) - ); - } else { - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 - return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (Math.random() * 16) | 0, - v = c === 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); - } -} - -/** - * Given a child DOM element, returns a query-selector statement describing that - * and its ancestors - * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz] - * @param elem - * @returns {string} - */ -function htmlTreeAsString(elem) { - /* eslint no-extra-parens:0*/ - var MAX_TRAVERSE_HEIGHT = 5, - MAX_OUTPUT_LEN = 80, - out = [], - height = 0, - len = 0, - separator = ' > ', - sepLength = separator.length, - nextStr; - - while (elem && height++ < MAX_TRAVERSE_HEIGHT) { - nextStr = htmlElementAsString(elem); - // bail out if - // - nextStr is the 'html' element - // - the length of the string that would be created exceeds MAX_OUTPUT_LEN - // (ignore this limit if we are on the first iteration) - if ( - nextStr === 'html' || - (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) - ) { - break; - } - - out.push(nextStr); - - len += nextStr.length; - elem = elem.parentNode; - } - - return out.reverse().join(separator); -} - -/** - * Returns a simple, query-selector representation of a DOM element - * e.g. [HTMLElement] => input#foo.btn[name=baz] - * @param HTMLElement - * @returns {string} - */ -function htmlElementAsString(elem) { - var out = [], - className, - classes, - key, - attr, - i; - - if (!elem || !elem.tagName) { - return ''; - } - - out.push(elem.tagName.toLowerCase()); - if (elem.id) { - out.push('#' + elem.id); - } - - className = elem.className; - if (className && isString(className)) { - classes = className.split(/\s+/); - for (i = 0; i < classes.length; i++) { - out.push('.' + classes[i]); - } - } - var attrWhitelist = ['type', 'name', 'title', 'alt']; - for (i = 0; i < attrWhitelist.length; i++) { - key = attrWhitelist[i]; - attr = elem.getAttribute(key); - if (attr) { - out.push('[' + key + '="' + attr + '"]'); - } - } - return out.join(''); -} - -/** - * Returns true if either a OR b is truthy, but not both - */ -function isOnlyOneTruthy(a, b) { - return !!(!!a ^ !!b); -} - -/** - * Returns true if both parameters are undefined - */ -function isBothUndefined(a, b) { - return isUndefined(a) && isUndefined(b); -} - -/** - * Returns true if the two input exception interfaces have the same content - */ -function isSameException(ex1, ex2) { - if (isOnlyOneTruthy(ex1, ex2)) return false; - - ex1 = ex1.values[0]; - ex2 = ex2.values[0]; - - if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; - - // in case both stacktraces are undefined, we can't decide so default to false - if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false; - - return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); -} - -/** - * Returns true if the two input stack trace interfaces have the same content - */ -function isSameStacktrace(stack1, stack2) { - if (isOnlyOneTruthy(stack1, stack2)) return false; - - var frames1 = stack1.frames; - var frames2 = stack2.frames; - - // Exit early if frame count differs - if (frames1.length !== frames2.length) return false; - - // Iterate through every frame; bail out if anything differs - var a, b; - for (var i = 0; i < frames1.length; i++) { - a = frames1[i]; - b = frames2[i]; - if ( - a.filename !== b.filename || - a.lineno !== b.lineno || - a.colno !== b.colno || - a['function'] !== b['function'] - ) - return false; - } - return true; -} - -/** - * Polyfill a method - * @param obj object e.g. `document` - * @param name method name present on object e.g. `addEventListener` - * @param replacement replacement function - * @param track {optional} record instrumentation to an array - */ -function fill(obj, name, replacement, track) { - if (obj == null) return; - var orig = obj[name]; - obj[name] = replacement(orig); - obj[name].__raven__ = true; - obj[name].__orig__ = orig; - if (track) { - track.push([obj, name, orig]); - } -} - -/** - * Join values in array - * @param input array of values to be joined together - * @param delimiter string to be placed in-between values - * @returns {string} - */ -function safeJoin(input, delimiter) { - if (!isArray(input)) return ''; - - var output = []; - - for (var i = 0; i < input.length; i++) { - try { - output.push(String(input[i])); - } catch (e) { - output.push('[value cannot be serialized]'); - } - } - - return output.join(delimiter); -} - -// Default Node.js REPL depth -var MAX_SERIALIZE_EXCEPTION_DEPTH = 3; -// 50kB, as 100kB is max payload size, so half sounds reasonable -var MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024; -var MAX_SERIALIZE_KEYS_LENGTH = 40; - -function utf8Length(value) { - return ~-encodeURI(value).split(/%..|./).length; -} - -function jsonSize(value) { - return utf8Length(JSON.stringify(value)); -} - -function serializeValue(value) { - if (typeof value === 'string') { - var maxLength = 40; - return truncate(value, maxLength); - } else if ( - typeof value === 'number' || - typeof value === 'boolean' || - typeof value === 'undefined' - ) { - return value; - } - - var type = Object.prototype.toString.call(value); - - // Node.js REPL notation - if (type === '[object Object]') return '[Object]'; - if (type === '[object Array]') return '[Array]'; - if (type === '[object Function]') - return value.name ? '[Function: ' + value.name + ']' : '[Function]'; - - return value; -} - -function serializeObject(value, depth) { - if (depth === 0) return serializeValue(value); - - if (isPlainObject(value)) { - return Object.keys(value).reduce(function(acc, key) { - acc[key] = serializeObject(value[key], depth - 1); - return acc; - }, {}); - } else if (Array.isArray(value)) { - return value.map(function(val) { - return serializeObject(val, depth - 1); - }); - } - - return serializeValue(value); -} - -function serializeException(ex, depth, maxSize) { - if (!isPlainObject(ex)) return ex; - - depth = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_DEPTH : depth; - maxSize = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_SIZE : maxSize; - - var serialized = serializeObject(ex, depth); - - if (jsonSize(stringify_1(serialized)) > maxSize) { - return serializeException(ex, depth - 1); - } - - return serialized; -} - -function serializeKeysForMessage(keys, maxLength) { - if (typeof keys === 'number' || typeof keys === 'string') return keys.toString(); - if (!Array.isArray(keys)) return ''; - - keys = keys.filter(function(key) { - return typeof key === 'string'; - }); - if (keys.length === 0) return '[object has no keys]'; - - maxLength = typeof maxLength !== 'number' ? MAX_SERIALIZE_KEYS_LENGTH : maxLength; - if (keys[0].length >= maxLength) return keys[0]; - - for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) { - var serialized = keys.slice(0, usedKeys).join(', '); - if (serialized.length > maxLength) continue; - if (usedKeys === keys.length) return serialized; - return serialized + '\u2026'; - } - - return ''; -} - -function sanitize(input, sanitizeKeys) { - if (!isArray(sanitizeKeys) || (isArray(sanitizeKeys) && sanitizeKeys.length === 0)) - return input; - - var sanitizeRegExp = joinRegExp(sanitizeKeys); - var sanitizeMask = '********'; - var safeInput; - - try { - safeInput = JSON.parse(stringify_1(input)); - } catch (o_O) { - return input; - } - - function sanitizeWorker(workerInput) { - if (isArray(workerInput)) { - return workerInput.map(function(val) { - return sanitizeWorker(val); - }); - } - - if (isPlainObject(workerInput)) { - return Object.keys(workerInput).reduce(function(acc, k) { - if (sanitizeRegExp.test(k)) { - acc[k] = sanitizeMask; - } else { - acc[k] = sanitizeWorker(workerInput[k]); - } - return acc; - }, {}); - } - - return workerInput; - } - - return sanitizeWorker(safeInput); -} - -var utils = { - isObject: isObject, - isError: isError, - isErrorEvent: isErrorEvent, - isUndefined: isUndefined, - isFunction: isFunction, - isPlainObject: isPlainObject, - isString: isString, - isArray: isArray, - isEmptyObject: isEmptyObject, - supportsErrorEvent: supportsErrorEvent, - supportsFetch: supportsFetch, - supportsReferrerPolicy: supportsReferrerPolicy, - supportsPromiseRejectionEvent: supportsPromiseRejectionEvent, - wrappedCallback: wrappedCallback, - each: each, - objectMerge: objectMerge, - truncate: truncate, - objectFrozen: objectFrozen, - hasKey: hasKey, - joinRegExp: joinRegExp, - urlencode: urlencode, - uuid4: uuid4, - htmlTreeAsString: htmlTreeAsString, - htmlElementAsString: htmlElementAsString, - isSameException: isSameException, - isSameStacktrace: isSameStacktrace, - parseUrl: parseUrl, - fill: fill, - safeJoin: safeJoin, - serializeException: serializeException, - serializeKeysForMessage: serializeKeysForMessage, - sanitize: sanitize -}; - -/* - TraceKit - Cross brower stack traces - - This was originally forked from github.com/occ/TraceKit, but has since been - largely re-written and is now maintained as part of raven-js. Tests for - this are in test/vendor. - - MIT license -*/ - -var TraceKit = { - collectWindowErrors: true, - debug: false -}; - -// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) -var _window$1 = - typeof window !== 'undefined' - ? window - : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; - -// global reference to slice -var _slice = [].slice; -var UNKNOWN_FUNCTION = '?'; - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types -var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/; - -function getLocationHref() { - if (typeof document === 'undefined' || document.location == null) return ''; - - return document.location.href; -} - -/** - * TraceKit.report: cross-browser processing of unhandled exceptions - * - * Syntax: - * TraceKit.report.subscribe(function(stackInfo) { ... }) - * TraceKit.report.unsubscribe(function(stackInfo) { ... }) - * TraceKit.report(exception) - * try { ...code... } catch(ex) { TraceKit.report(ex); } - * - * Supports: - * - Firefox: full stack trace with line numbers, plus column number - * on top frame; column number is not guaranteed - * - Opera: full stack trace with line and column numbers - * - Chrome: full stack trace with line and column numbers - * - Safari: line and column number for the top frame only; some frames - * may be missing, and column number is not guaranteed - * - IE: line and column number for the top frame only; some frames - * may be missing, and column number is not guaranteed - * - * In theory, TraceKit should work on all of the following versions: - * - IE5.5+ (only 8.0 tested) - * - Firefox 0.9+ (only 3.5+ tested) - * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require - * Exceptions Have Stacktrace to be enabled in opera:config) - * - Safari 3+ (only 4+ tested) - * - Chrome 1+ (only 5+ tested) - * - Konqueror 3.5+ (untested) - * - * Requires TraceKit.computeStackTrace. - * - * Tries to catch all unhandled exceptions and report them to the - * subscribed handlers. Please note that TraceKit.report will rethrow the - * exception. This is REQUIRED in order to get a useful stack trace in IE. - * If the exception does not reach the top of the browser, you will only - * get a stack trace from the point where TraceKit.report was called. - * - * Handlers receive a stackInfo object as described in the - * TraceKit.computeStackTrace docs. - */ -TraceKit.report = (function reportModuleWrapper() { - var handlers = [], - lastArgs = null, - lastException = null, - lastExceptionStack = null; - - /** - * Add a crash handler. - * @param {Function} handler - */ - function subscribe(handler) { - installGlobalHandler(); - handlers.push(handler); - } - - /** - * Remove a crash handler. - * @param {Function} handler - */ - function unsubscribe(handler) { - for (var i = handlers.length - 1; i >= 0; --i) { - if (handlers[i] === handler) { - handlers.splice(i, 1); - } - } - } - - /** - * Remove all crash handlers. - */ - function unsubscribeAll() { - uninstallGlobalHandler(); - handlers = []; - } - - /** - * Dispatch stack information to all handlers. - * @param {Object.<string, *>} stack - */ - function notifyHandlers(stack, isWindowError) { - var exception = null; - if (isWindowError && !TraceKit.collectWindowErrors) { - return; - } - for (var i in handlers) { - if (handlers.hasOwnProperty(i)) { - try { - handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2))); - } catch (inner) { - exception = inner; - } - } - } - - if (exception) { - throw exception; - } - } - - var _oldOnerrorHandler, _onErrorHandlerInstalled; - - /** - * Ensures all global unhandled exceptions are recorded. - * Supported by Gecko and IE. - * @param {string} msg Error message. - * @param {string} url URL of script that generated the exception. - * @param {(number|string)} lineNo The line number at which the error - * occurred. - * @param {?(number|string)} colNo The column number at which the error - * occurred. - * @param {?Error} ex The actual Error object. - */ - function traceKitWindowOnError(msg, url, lineNo, colNo, ex) { - var stack = null; - // If 'ex' is ErrorEvent, get real Error from inside - var exception = utils.isErrorEvent(ex) ? ex.error : ex; - // If 'msg' is ErrorEvent, get real message from inside - var message = utils.isErrorEvent(msg) ? msg.message : msg; - - if (lastExceptionStack) { - TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( - lastExceptionStack, - url, - lineNo, - message - ); - processLastException(); - } else if (exception && utils.isError(exception)) { - // non-string `exception` arg; attempt to extract stack trace - - // New chrome and blink send along a real error object - // Let's just report that like a normal error. - // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror - stack = TraceKit.computeStackTrace(exception); - notifyHandlers(stack, true); - } else { - var location = { - url: url, - line: lineNo, - column: colNo - }; - - var name = undefined; - var groups; - - if ({}.toString.call(message) === '[object String]') { - var groups = message.match(ERROR_TYPES_RE); - if (groups) { - name = groups[1]; - message = groups[2]; - } - } - - location.func = UNKNOWN_FUNCTION; - - stack = { - name: name, - message: message, - url: getLocationHref(), - stack: [location] - }; - notifyHandlers(stack, true); - } - - if (_oldOnerrorHandler) { - return _oldOnerrorHandler.apply(this, arguments); - } - - return false; - } - - function installGlobalHandler() { - if (_onErrorHandlerInstalled) { - return; - } - _oldOnerrorHandler = _window$1.onerror; - _window$1.onerror = traceKitWindowOnError; - _onErrorHandlerInstalled = true; - } - - function uninstallGlobalHandler() { - if (!_onErrorHandlerInstalled) { - return; - } - _window$1.onerror = _oldOnerrorHandler; - _onErrorHandlerInstalled = false; - _oldOnerrorHandler = undefined; - } - - function processLastException() { - var _lastExceptionStack = lastExceptionStack, - _lastArgs = lastArgs; - lastArgs = null; - lastExceptionStack = null; - lastException = null; - notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs)); - } - - /** - * Reports an unhandled Error to TraceKit. - * @param {Error} ex - * @param {?boolean} rethrow If false, do not re-throw the exception. - * Only used for window.onerror to not cause an infinite loop of - * rethrowing. - */ - function report(ex, rethrow) { - var args = _slice.call(arguments, 1); - if (lastExceptionStack) { - if (lastException === ex) { - return; // already caught by an inner catch block, ignore - } else { - processLastException(); - } - } - - var stack = TraceKit.computeStackTrace(ex); - lastExceptionStack = stack; - lastException = ex; - lastArgs = args; - - // If the stack trace is incomplete, wait for 2 seconds for - // slow slow IE to see if onerror occurs or not before reporting - // this exception; otherwise, we will end up with an incomplete - // stack trace - setTimeout(function() { - if (lastException === ex) { - processLastException(); - } - }, stack.incomplete ? 2000 : 0); - - if (rethrow !== false) { - throw ex; // re-throw to propagate to the top level (and cause window.onerror) - } - } - - report.subscribe = subscribe; - report.unsubscribe = unsubscribe; - report.uninstall = unsubscribeAll; - return report; -})(); - -/** - * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript - * - * Syntax: - * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below) - * Returns: - * s.name - exception name - * s.message - exception message - * s.stack[i].url - JavaScript or HTML file URL - * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work) - * s.stack[i].args - arguments passed to the function, if known - * s.stack[i].line - line number, if known - * s.stack[i].column - column number, if known - * - * Supports: - * - Firefox: full stack trace with line numbers and unreliable column - * number on top frame - * - Opera 10: full stack trace with line and column numbers - * - Opera 9-: full stack trace with line numbers - * - Chrome: full stack trace with line and column numbers - * - Safari: line and column number for the topmost stacktrace element - * only - * - IE: no line numbers whatsoever - * - * Tries to guess names of anonymous functions by looking for assignments - * in the source code. In IE and Safari, we have to guess source file names - * by searching for function bodies inside all page scripts. This will not - * work for scripts that are loaded cross-domain. - * Here be dragons: some function names may be guessed incorrectly, and - * duplicate functions may be mismatched. - * - * TraceKit.computeStackTrace should only be used for tracing purposes. - * Logging of unhandled exceptions should be done with TraceKit.report, - * which builds on top of TraceKit.computeStackTrace and provides better - * IE support by utilizing the window.onerror event to retrieve information - * about the top of the stack. - * - * Note: In IE and Safari, no stack trace is recorded on the Error object, - * so computeStackTrace instead walks its *own* chain of callers. - * This means that: - * * in Safari, some methods may be missing from the stack trace; - * * in IE, the topmost function in the stack trace will always be the - * caller of computeStackTrace. - * - * This is okay for tracing (because you are likely to be calling - * computeStackTrace from the function you want to be the topmost element - * of the stack trace anyway), but not okay for logging unhandled - * exceptions (because your catch block will likely be far away from the - * inner function that actually caused the exception). - * - */ -TraceKit.computeStackTrace = (function computeStackTraceWrapper() { - // Contents of Exception in various browsers. - // - // SAFARI: - // ex.message = Can't find variable: qq - // ex.line = 59 - // ex.sourceId = 580238192 - // ex.sourceURL = http://... - // ex.expressionBeginOffset = 96 - // ex.expressionCaretOffset = 98 - // ex.expressionEndOffset = 98 - // ex.name = ReferenceError - // - // FIREFOX: - // ex.message = qq is not defined - // ex.fileName = http://... - // ex.lineNumber = 59 - // ex.columnNumber = 69 - // ex.stack = ...stack trace... (see the example below) - // ex.name = ReferenceError - // - // CHROME: - // ex.message = qq is not defined - // ex.name = ReferenceError - // ex.type = not_defined - // ex.arguments = ['aa'] - // ex.stack = ...stack trace... - // - // INTERNET EXPLORER: - // ex.message = ... - // ex.name = ReferenceError - // - // OPERA: - // ex.message = ...message... (see the example below) - // ex.name = ReferenceError - // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message) - // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace' - - /** - * Computes stack trace information from the stack property. - * Chrome and Gecko use this property. - * @param {Error} ex - * @return {?Object.<string, *>} Stack trace information. - */ - function computeStackTraceFromStackProp(ex) { - if (typeof ex.stack === 'undefined' || !ex.stack) return; - - var chrome = /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; - var winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; - // NOTE: blob urls are now supposed to always have an origin, therefore it's format - // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well - var gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; - // Used to additionally parse URL/line/column from eval frames - var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i; - var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/; - var lines = ex.stack.split('\n'); - var stack = []; - var submatch; - var parts; - var element; - var reference = /^(.*) is undefined$/.exec(ex.message); - - for (var i = 0, j = lines.length; i < j; ++i) { - if ((parts = chrome.exec(lines[i]))) { - var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line - var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line - if (isEval && (submatch = chromeEval.exec(parts[2]))) { - // throw out eval line/column and use top-most line/column number - parts[2] = submatch[1]; // url - parts[3] = submatch[2]; // line - parts[4] = submatch[3]; // column - } - element = { - url: !isNative ? parts[2] : null, - func: parts[1] || UNKNOWN_FUNCTION, - args: isNative ? [parts[2]] : [], - line: parts[3] ? +parts[3] : null, - column: parts[4] ? +parts[4] : null - }; - } else if ((parts = winjs.exec(lines[i]))) { - element = { - url: parts[2], - func: parts[1] || UNKNOWN_FUNCTION, - args: [], - line: +parts[3], - column: parts[4] ? +parts[4] : null - }; - } else if ((parts = gecko.exec(lines[i]))) { - var isEval = parts[3] && parts[3].indexOf(' > eval') > -1; - if (isEval && (submatch = geckoEval.exec(parts[3]))) { - // throw out eval line/column and use top-most line number - parts[3] = submatch[1]; - parts[4] = submatch[2]; - parts[5] = null; // no column when eval - } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') { - // FireFox uses this awesome columnNumber property for its top frame - // Also note, Firefox's column number is 0-based and everything else expects 1-based, - // so adding 1 - // NOTE: this hack doesn't work if top-most frame is eval - stack[0].column = ex.columnNumber + 1; - } - element = { - url: parts[3], - func: parts[1] || UNKNOWN_FUNCTION, - args: parts[2] ? parts[2].split(',') : [], - line: parts[4] ? +parts[4] : null, - column: parts[5] ? +parts[5] : null - }; - } else { - continue; - } - - if (!element.func && element.line) { - element.func = UNKNOWN_FUNCTION; - } - - stack.push(element); - } - - if (!stack.length) { - return null; - } - - return { - name: ex.name, - message: ex.message, - url: getLocationHref(), - stack: stack - }; - } - - /** - * Adds information about the first frame to incomplete stack traces. - * Safari and IE require this to get complete data on the first frame. - * @param {Object.<string, *>} stackInfo Stack trace information from - * one of the compute* methods. - * @param {string} url The URL of the script that caused an error. - * @param {(number|string)} lineNo The line number of the script that - * caused an error. - * @param {string=} message The error generated by the browser, which - * hopefully contains the name of the object that caused the error. - * @return {boolean} Whether or not the stack information was - * augmented. - */ - function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) { - var initial = { - url: url, - line: lineNo - }; - - if (initial.url && initial.line) { - stackInfo.incomplete = false; - - if (!initial.func) { - initial.func = UNKNOWN_FUNCTION; - } - - if (stackInfo.stack.length > 0) { - if (stackInfo.stack[0].url === initial.url) { - if (stackInfo.stack[0].line === initial.line) { - return false; // already in stack trace - } else if ( - !stackInfo.stack[0].line && - stackInfo.stack[0].func === initial.func - ) { - stackInfo.stack[0].line = initial.line; - return false; - } - } - } - - stackInfo.stack.unshift(initial); - stackInfo.partial = true; - return true; - } else { - stackInfo.incomplete = true; - } - - return false; - } - - /** - * Computes stack trace information by walking the arguments.caller - * chain at the time the exception occurred. This will cause earlier - * frames to be missed but is the only way to get any stack trace in - * Safari and IE. The top frame is restored by - * {@link augmentStackTraceWithInitialElement}. - * @param {Error} ex - * @return {?Object.<string, *>} Stack trace information. - */ - function computeStackTraceByWalkingCallerChain(ex, depth) { - var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i, - stack = [], - funcs = {}, - recursion = false, - parts, - item; - - for ( - var curr = computeStackTraceByWalkingCallerChain.caller; - curr && !recursion; - curr = curr.caller - ) { - if (curr === computeStackTrace || curr === TraceKit.report) { - // console.log('skipping internal function'); - continue; - } - - item = { - url: null, - func: UNKNOWN_FUNCTION, - line: null, - column: null - }; - - if (curr.name) { - item.func = curr.name; - } else if ((parts = functionName.exec(curr.toString()))) { - item.func = parts[1]; - } - - if (typeof item.func === 'undefined') { - try { - item.func = parts.input.substring(0, parts.input.indexOf('{')); - } catch (e) {} - } - - if (funcs['' + curr]) { - recursion = true; - } else { - funcs['' + curr] = true; - } - - stack.push(item); - } - - if (depth) { - // console.log('depth is ' + depth); - // console.log('stack is ' + stack.length); - stack.splice(0, depth); - } - - var result = { - name: ex.name, - message: ex.message, - url: getLocationHref(), - stack: stack - }; - augmentStackTraceWithInitialElement( - result, - ex.sourceURL || ex.fileName, - ex.line || ex.lineNumber, - ex.message || ex.description - ); - return result; - } - - /** - * Computes a stack trace for an exception. - * @param {Error} ex - * @param {(string|number)=} depth - */ - function computeStackTrace(ex, depth) { - var stack = null; - depth = depth == null ? 0 : +depth; - - try { - stack = computeStackTraceFromStackProp(ex); - if (stack) { - return stack; - } - } catch (e) { - if (TraceKit.debug) { - throw e; - } - } - - try { - stack = computeStackTraceByWalkingCallerChain(ex, depth + 1); - if (stack) { - return stack; - } - } catch (e) { - if (TraceKit.debug) { - throw e; - } - } - return { - name: ex.name, - message: ex.message, - url: getLocationHref() - }; - } - - computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; - computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp; - - return computeStackTrace; -})(); - -var tracekit = TraceKit; - -/* - * JavaScript MD5 - * https://github.com/blueimp/JavaScript-MD5 - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -/* -* Add integers, wrapping at 2^32. This uses 16-bit operations internally -* to work around bugs in some JS interpreters. -*/ -function safeAdd(x, y) { - var lsw = (x & 0xffff) + (y & 0xffff); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xffff); -} - -/* -* Bitwise rotate a 32-bit number to the left. -*/ -function bitRotateLeft(num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); -} - -/* -* These functions implement the four basic operations the algorithm uses. -*/ -function md5cmn(q, a, b, x, s, t) { - return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); -} -function md5ff(a, b, c, d, x, s, t) { - return md5cmn((b & c) | (~b & d), a, b, x, s, t); -} -function md5gg(a, b, c, d, x, s, t) { - return md5cmn((b & d) | (c & ~d), a, b, x, s, t); -} -function md5hh(a, b, c, d, x, s, t) { - return md5cmn(b ^ c ^ d, a, b, x, s, t); -} -function md5ii(a, b, c, d, x, s, t) { - return md5cmn(c ^ (b | ~d), a, b, x, s, t); -} - -/* -* Calculate the MD5 of an array of little-endian words, and a bit length. -*/ -function binlMD5(x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << (len % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var i; - var olda; - var oldb; - var oldc; - var oldd; - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - - for (i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - - a = md5ff(a, b, c, d, x[i], 7, -680876936); - d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); - c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); - b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); - a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); - d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); - c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); - b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); - a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); - d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); - c = md5ff(c, d, a, b, x[i + 10], 17, -42063); - b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); - a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); - d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); - c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); - b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); - - a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); - d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); - c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); - b = md5gg(b, c, d, a, x[i], 20, -373897302); - a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); - d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); - c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); - b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); - a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); - d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); - c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); - b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); - a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); - d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); - c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); - b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); - - a = md5hh(a, b, c, d, x[i + 5], 4, -378558); - d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); - c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); - b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); - a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); - d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); - c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); - b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); - a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); - d = md5hh(d, a, b, c, x[i], 11, -358537222); - c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); - b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); - a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); - d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); - c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); - b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); - - a = md5ii(a, b, c, d, x[i], 6, -198630844); - d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); - c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); - b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); - a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); - d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); - c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); - b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); - a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); - d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); - c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); - b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); - a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); - d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); - c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); - b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); - - a = safeAdd(a, olda); - b = safeAdd(b, oldb); - c = safeAdd(c, oldc); - d = safeAdd(d, oldd); - } - return [a, b, c, d]; -} - -/* -* Convert an array of little-endian words to a string -*/ -function binl2rstr(input) { - var i; - var output = ''; - var length32 = input.length * 32; - for (i = 0; i < length32; i += 8) { - output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff); - } - return output; -} - -/* -* Convert a raw string to an array of little-endian words -* Characters >255 have their high-byte silently ignored. -*/ -function rstr2binl(input) { - var i; - var output = []; - output[(input.length >> 2) - 1] = undefined; - for (i = 0; i < output.length; i += 1) { - output[i] = 0; - } - var length8 = input.length * 8; - for (i = 0; i < length8; i += 8) { - output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32); - } - return output; -} - -/* -* Calculate the MD5 of a raw string -*/ -function rstrMD5(s) { - return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)); -} - -/* -* Calculate the HMAC-MD5, of a key and some data (raw strings) -*/ -function rstrHMACMD5(key, data) { - var i; - var bkey = rstr2binl(key); - var ipad = []; - var opad = []; - var hash; - ipad[15] = opad[15] = undefined; - if (bkey.length > 16) { - bkey = binlMD5(bkey, key.length * 8); - } - for (i = 0; i < 16; i += 1) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5c5c5c5c; - } - hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); - return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)); -} - -/* -* Convert a raw string to a hex string -*/ -function rstr2hex(input) { - var hexTab = '0123456789abcdef'; - var output = ''; - var x; - var i; - for (i = 0; i < input.length; i += 1) { - x = input.charCodeAt(i); - output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f); - } - return output; -} - -/* -* Encode a string as utf-8 -*/ -function str2rstrUTF8(input) { - return unescape(encodeURIComponent(input)); -} - -/* -* Take string arguments and return either raw or hex encoded strings -*/ -function rawMD5(s) { - return rstrMD5(str2rstrUTF8(s)); -} -function hexMD5(s) { - return rstr2hex(rawMD5(s)); -} -function rawHMACMD5(k, d) { - return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)); -} -function hexHMACMD5(k, d) { - return rstr2hex(rawHMACMD5(k, d)); -} - -function md5(string, key, raw) { - if (!key) { - if (!raw) { - return hexMD5(string); - } - return rawMD5(string); - } - if (!raw) { - return hexHMACMD5(key, string); - } - return rawHMACMD5(key, string); -} - -var md5_1 = md5; - -function RavenConfigError(message) { - this.name = 'RavenConfigError'; - this.message = message; -} -RavenConfigError.prototype = new Error(); -RavenConfigError.prototype.constructor = RavenConfigError; - -var configError = RavenConfigError; - -var wrapMethod = function(console, level, callback) { - var originalConsoleLevel = console[level]; - var originalConsole = console; - - if (!(level in console)) { - return; - } - - var sentryLevel = level === 'warn' ? 'warning' : level; - - console[level] = function() { - var args = [].slice.call(arguments); - - var msg = utils.safeJoin(args, ' '); - var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}}; - - if (level === 'assert') { - if (args[0] === false) { - // Default browsers message - msg = - 'Assertion failed: ' + (utils.safeJoin(args.slice(1), ' ') || 'console.assert'); - data.extra.arguments = args.slice(1); - callback && callback(msg, data); - } - } else { - callback && callback(msg, data); - } - - // this fails for some browsers. :( - if (originalConsoleLevel) { - // IE9 doesn't allow calling apply on console functions directly - // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193 - Function.prototype.apply.call(originalConsoleLevel, originalConsole, args); - } - }; -}; - -var console$1 = { - wrapMethod: wrapMethod -}; - -/*global XDomainRequest:false */ - - - - - - - -var isError$1 = utils.isError; -var isObject$1 = utils.isObject; -var isPlainObject$1 = utils.isPlainObject; -var isErrorEvent$1 = utils.isErrorEvent; -var isUndefined$1 = utils.isUndefined; -var isFunction$1 = utils.isFunction; -var isString$1 = utils.isString; -var isArray$1 = utils.isArray; -var isEmptyObject$1 = utils.isEmptyObject; -var each$1 = utils.each; -var objectMerge$1 = utils.objectMerge; -var truncate$1 = utils.truncate; -var objectFrozen$1 = utils.objectFrozen; -var hasKey$1 = utils.hasKey; -var joinRegExp$1 = utils.joinRegExp; -var urlencode$1 = utils.urlencode; -var uuid4$1 = utils.uuid4; -var htmlTreeAsString$1 = utils.htmlTreeAsString; -var isSameException$1 = utils.isSameException; -var isSameStacktrace$1 = utils.isSameStacktrace; -var parseUrl$1 = utils.parseUrl; -var fill$1 = utils.fill; -var supportsFetch$1 = utils.supportsFetch; -var supportsReferrerPolicy$1 = utils.supportsReferrerPolicy; -var serializeKeysForMessage$1 = utils.serializeKeysForMessage; -var serializeException$1 = utils.serializeException; -var sanitize$1 = utils.sanitize; - -var wrapConsoleMethod = console$1.wrapMethod; - -var dsnKeys = 'source protocol user pass host port path'.split(' '), - dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/; - -function now() { - return +new Date(); -} - -// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) -var _window$2 = - typeof window !== 'undefined' - ? window - : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; -var _document = _window$2.document; -var _navigator = _window$2.navigator; - -function keepOriginalCallback(original, callback) { - return isFunction$1(callback) - ? function(data) { - return callback(data, original); - } - : callback; -} - -// First, check for JSON support -// If there is no JSON, we no-op the core features of Raven -// since JSON is required to encode the payload -function Raven() { - this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify); - // Raven can run in contexts where there's no document (react-native) - this._hasDocument = !isUndefined$1(_document); - this._hasNavigator = !isUndefined$1(_navigator); - this._lastCapturedException = null; - this._lastData = null; - this._lastEventId = null; - this._globalServer = null; - this._globalKey = null; - this._globalProject = null; - this._globalContext = {}; - this._globalOptions = { - // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin - release: _window$2.SENTRY_RELEASE && _window$2.SENTRY_RELEASE.id, - logger: 'javascript', - ignoreErrors: [], - ignoreUrls: [], - whitelistUrls: [], - includePaths: [], - headers: null, - collectWindowErrors: true, - captureUnhandledRejections: true, - maxMessageLength: 0, - // By default, truncates URL values to 250 chars - maxUrlLength: 250, - stackTraceLimit: 50, - autoBreadcrumbs: true, - instrument: true, - sampleRate: 1, - sanitizeKeys: [] - }; - this._fetchDefaults = { - method: 'POST', - keepalive: true, - // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default - // https://caniuse.com/#feat=referrer-policy - // It doesn't. And it throw exception instead of ignoring this parameter... - // REF: https://github.com/getsentry/raven-js/issues/1233 - referrerPolicy: supportsReferrerPolicy$1() ? 'origin' : '' - }; - this._ignoreOnError = 0; - this._isRavenInstalled = false; - this._originalErrorStackTraceLimit = Error.stackTraceLimit; - // capture references to window.console *and* all its methods first - // before the console plugin has a chance to monkey patch - this._originalConsole = _window$2.console || {}; - this._originalConsoleMethods = {}; - this._plugins = []; - this._startTime = now(); - this._wrappedBuiltIns = []; - this._breadcrumbs = []; - this._lastCapturedEvent = null; - this._keypressTimeout; - this._location = _window$2.location; - this._lastHref = this._location && this._location.href; - this._resetBackoff(); - - // eslint-disable-next-line guard-for-in - for (var method in this._originalConsole) { - this._originalConsoleMethods[method] = this._originalConsole[method]; - } -} - -/* - * The core Raven singleton - * - * @this {Raven} - */ - -Raven.prototype = { - // Hardcode version string so that raven source can be loaded directly via - // webpack (using a build step causes webpack #1617). Grunt verifies that - // this value matches package.json during build. - // See: https://github.com/getsentry/raven-js/issues/465 - VERSION: '3.24.2', - - debug: false, - - TraceKit: tracekit, // alias to TraceKit - - /* - * Configure Raven with a DSN and extra options - * - * @param {string} dsn The public Sentry DSN - * @param {object} options Set of global options [optional] - * @return {Raven} - */ - config: function(dsn, options) { - var self = this; - - if (self._globalServer) { - this._logDebug('error', 'Error: Raven has already been configured'); - return self; - } - if (!dsn) return self; - - var globalOptions = self._globalOptions; - - // merge in options - if (options) { - each$1(options, function(key, value) { - // tags and extra are special and need to be put into context - if (key === 'tags' || key === 'extra' || key === 'user') { - self._globalContext[key] = value; - } else { - globalOptions[key] = value; - } - }); - } - - self.setDSN(dsn); - - // "Script error." is hard coded into browsers for errors that it can't read. - // this is the result of a script being pulled in from an external domain and CORS. - globalOptions.ignoreErrors.push(/^Script error\.?$/); - globalOptions.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/); - - // join regexp rules into one big rule - globalOptions.ignoreErrors = joinRegExp$1(globalOptions.ignoreErrors); - globalOptions.ignoreUrls = globalOptions.ignoreUrls.length - ? joinRegExp$1(globalOptions.ignoreUrls) - : false; - globalOptions.whitelistUrls = globalOptions.whitelistUrls.length - ? joinRegExp$1(globalOptions.whitelistUrls) - : false; - globalOptions.includePaths = joinRegExp$1(globalOptions.includePaths); - globalOptions.maxBreadcrumbs = Math.max( - 0, - Math.min(globalOptions.maxBreadcrumbs || 100, 100) - ); // default and hard limit is 100 - - var autoBreadcrumbDefaults = { - xhr: true, - console: true, - dom: true, - location: true, - sentry: true - }; - - var autoBreadcrumbs = globalOptions.autoBreadcrumbs; - if ({}.toString.call(autoBreadcrumbs) === '[object Object]') { - autoBreadcrumbs = objectMerge$1(autoBreadcrumbDefaults, autoBreadcrumbs); - } else if (autoBreadcrumbs !== false) { - autoBreadcrumbs = autoBreadcrumbDefaults; - } - globalOptions.autoBreadcrumbs = autoBreadcrumbs; - - var instrumentDefaults = { - tryCatch: true - }; - - var instrument = globalOptions.instrument; - if ({}.toString.call(instrument) === '[object Object]') { - instrument = objectMerge$1(instrumentDefaults, instrument); - } else if (instrument !== false) { - instrument = instrumentDefaults; - } - globalOptions.instrument = instrument; - - tracekit.collectWindowErrors = !!globalOptions.collectWindowErrors; - - // return for chaining - return self; - }, - - /* - * Installs a global window.onerror error handler - * to capture and report uncaught exceptions. - * At this point, install() is required to be called due - * to the way TraceKit is set up. - * - * @return {Raven} - */ - install: function() { - var self = this; - if (self.isSetup() && !self._isRavenInstalled) { - tracekit.report.subscribe(function() { - self._handleOnErrorStackInfo.apply(self, arguments); - }); - - if (self._globalOptions.captureUnhandledRejections) { - self._attachPromiseRejectionHandler(); - } - - self._patchFunctionToString(); - - if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) { - self._instrumentTryCatch(); - } - - if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs(); - - // Install all of the plugins - self._drainPlugins(); - - self._isRavenInstalled = true; - } - - Error.stackTraceLimit = self._globalOptions.stackTraceLimit; - return this; - }, - - /* - * Set the DSN (can be called multiple time unlike config) - * - * @param {string} dsn The public Sentry DSN - */ - setDSN: function(dsn) { - var self = this, - uri = self._parseDSN(dsn), - lastSlash = uri.path.lastIndexOf('/'), - path = uri.path.substr(1, lastSlash); - - self._dsn = dsn; - self._globalKey = uri.user; - self._globalSecret = uri.pass && uri.pass.substr(1); - self._globalProject = uri.path.substr(lastSlash + 1); - - self._globalServer = self._getGlobalServer(uri); - - self._globalEndpoint = - self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/'; - - // Reset backoff state since we may be pointing at a - // new project/server - this._resetBackoff(); - }, - - /* - * Wrap code within a context so Raven can capture errors - * reliably across domains that is executed immediately. - * - * @param {object} options A specific set of options for this context [optional] - * @param {function} func The callback to be immediately executed within the context - * @param {array} args An array of arguments to be called with the callback [optional] - */ - context: function(options, func, args) { - if (isFunction$1(options)) { - args = func || []; - func = options; - options = undefined; - } - - return this.wrap(options, func).apply(this, args); - }, - - /* - * Wrap code within a context and returns back a new function to be executed - * - * @param {object} options A specific set of options for this context [optional] - * @param {function} func The function to be wrapped in a new context - * @param {function} func A function to call before the try/catch wrapper [optional, private] - * @return {function} The newly wrapped functions with a context - */ - wrap: function(options, func, _before) { - var self = this; - // 1 argument has been passed, and it's not a function - // so just return it - if (isUndefined$1(func) && !isFunction$1(options)) { - return options; - } - - // options is optional - if (isFunction$1(options)) { - func = options; - options = undefined; - } - - // At this point, we've passed along 2 arguments, and the second one - // is not a function either, so we'll just return the second argument. - if (!isFunction$1(func)) { - return func; - } - - // We don't wanna wrap it twice! - try { - if (func.__raven__) { - return func; - } - - // If this has already been wrapped in the past, return that - if (func.__raven_wrapper__) { - return func.__raven_wrapper__; - } - } catch (e) { - // Just accessing custom props in some Selenium environments - // can cause a "Permission denied" exception (see raven-js#495). - // Bail on wrapping and return the function as-is (defers to window.onerror). - return func; - } - - function wrapped() { - var args = [], - i = arguments.length, - deep = !options || (options && options.deep !== false); - - if (_before && isFunction$1(_before)) { - _before.apply(this, arguments); - } - - // Recursively wrap all of a function's arguments that are - // functions themselves. - while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i]; - - try { - // Attempt to invoke user-land function - // NOTE: If you are a Sentry user, and you are seeing this stack frame, it - // means Raven caught an error invoking your application code. This is - // expected behavior and NOT indicative of a bug with Raven.js. - return func.apply(this, args); - } catch (e) { - self._ignoreNextOnError(); - self.captureException(e, options); - throw e; - } - } - - // copy over properties of the old function - for (var property in func) { - if (hasKey$1(func, property)) { - wrapped[property] = func[property]; - } - } - wrapped.prototype = func.prototype; - - func.__raven_wrapper__ = wrapped; - // Signal that this function has been wrapped/filled already - // for both debugging and to prevent it to being wrapped/filled twice - wrapped.__raven__ = true; - wrapped.__orig__ = func; - - return wrapped; - }, - - /** - * Uninstalls the global error handler. - * - * @return {Raven} - */ - uninstall: function() { - tracekit.report.uninstall(); - - this._detachPromiseRejectionHandler(); - this._unpatchFunctionToString(); - this._restoreBuiltIns(); - this._restoreConsole(); - - Error.stackTraceLimit = this._originalErrorStackTraceLimit; - this._isRavenInstalled = false; - - return this; - }, - - /** - * Callback used for `unhandledrejection` event - * - * @param {PromiseRejectionEvent} event An object containing - * promise: the Promise that was rejected - * reason: the value with which the Promise was rejected - * @return void - */ - _promiseRejectionHandler: function(event) { - this._logDebug('debug', 'Raven caught unhandled promise rejection:', event); - this.captureException(event.reason, { - extra: { - unhandledPromiseRejection: true - } - }); - }, - - /** - * Installs the global promise rejection handler. - * - * @return {raven} - */ - _attachPromiseRejectionHandler: function() { - this._promiseRejectionHandler = this._promiseRejectionHandler.bind(this); - _window$2.addEventListener && - _window$2.addEventListener('unhandledrejection', this._promiseRejectionHandler); - return this; - }, - - /** - * Uninstalls the global promise rejection handler. - * - * @return {raven} - */ - _detachPromiseRejectionHandler: function() { - _window$2.removeEventListener && - _window$2.removeEventListener('unhandledrejection', this._promiseRejectionHandler); - return this; - }, - - /** - * Manually capture an exception and send it over to Sentry - * - * @param {error} ex An exception to be logged - * @param {object} options A specific set of options for this error [optional] - * @return {Raven} - */ - captureException: function(ex, options) { - options = objectMerge$1({trimHeadFrames: 0}, options ? options : {}); - - if (isErrorEvent$1(ex) && ex.error) { - // If it is an ErrorEvent with `error` property, extract it to get actual Error - ex = ex.error; - } else if (isError$1(ex)) { - // we have a real Error object - ex = ex; - } else if (isPlainObject$1(ex)) { - // If it is plain Object, serialize it manually and extract options - // This will allow us to group events based on top-level keys - // which is much better than creating new group when any key/value change - options = this._getCaptureExceptionOptionsFromPlainObject(options, ex); - ex = new Error(options.message); - } else { - // If none of previous checks were valid, then it means that - // it's not a plain Object - // it's not a valid ErrorEvent (one with an error property) - // it's not an Error - // So bail out and capture it as a simple message: - return this.captureMessage( - ex, - objectMerge$1(options, { - stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace - trimHeadFrames: options.trimHeadFrames + 1 - }) - ); - } - - // Store the raw exception object for potential debugging and introspection - this._lastCapturedException = ex; - - // TraceKit.report will re-raise any exception passed to it, - // which means you have to wrap it in try/catch. Instead, we - // can wrap it here and only re-raise if TraceKit.report - // raises an exception different from the one we asked to - // report on. - try { - var stack = tracekit.computeStackTrace(ex); - this._handleStackInfo(stack, options); - } catch (ex1) { - if (ex !== ex1) { - throw ex1; - } - } - - return this; - }, - - _getCaptureExceptionOptionsFromPlainObject: function(currentOptions, ex) { - var exKeys = Object.keys(ex).sort(); - var options = objectMerge$1(currentOptions, { - message: - 'Non-Error exception captured with keys: ' + serializeKeysForMessage$1(exKeys), - fingerprint: [md5_1(exKeys)], - extra: currentOptions.extra || {} - }); - options.extra.__serialized__ = serializeException$1(ex); - - return options; - }, - - /* - * Manually send a message to Sentry - * - * @param {string} msg A plain message to be captured in Sentry - * @param {object} options A specific set of options for this message [optional] - * @return {Raven} - */ - captureMessage: function(msg, options) { - // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an - // early call; we'll error on the side of logging anything called before configuration since it's - // probably something you should see: - if ( - !!this._globalOptions.ignoreErrors.test && - this._globalOptions.ignoreErrors.test(msg) - ) { - return; - } - - options = options || {}; - msg = msg + ''; // Make sure it's actually a string - - var data = objectMerge$1( - { - message: msg - }, - options - ); - - var ex; - // Generate a "synthetic" stack trace from this point. - // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative - // of a bug with Raven.js. Sentry generates synthetic traces either by configuration, - // or if it catches a thrown object without a "stack" property. - try { - throw new Error(msg); - } catch (ex1) { - ex = ex1; - } - - // null exception name so `Error` isn't prefixed to msg - ex.name = null; - var stack = tracekit.computeStackTrace(ex); - - // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1] - var initialCall = isArray$1(stack.stack) && stack.stack[1]; - - // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call - // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd - // initialCall => captureException(string) => captureMessage(string) - if (initialCall && initialCall.func === 'Raven.captureException') { - initialCall = stack.stack[2]; - } - - var fileurl = (initialCall && initialCall.url) || ''; - - if ( - !!this._globalOptions.ignoreUrls.test && - this._globalOptions.ignoreUrls.test(fileurl) - ) { - return; - } - - if ( - !!this._globalOptions.whitelistUrls.test && - !this._globalOptions.whitelistUrls.test(fileurl) - ) { - return; - } - - if (this._globalOptions.stacktrace || (options && options.stacktrace)) { - // fingerprint on msg, not stack trace (legacy behavior, could be revisited) - data.fingerprint = data.fingerprint == null ? msg : data.fingerprint; - - options = objectMerge$1( - { - trimHeadFrames: 0 - }, - options - ); - // Since we know this is a synthetic trace, the top frame (this function call) - // MUST be from Raven.js, so mark it for trimming - // We add to the trim counter so that callers can choose to trim extra frames, such - // as utility functions. - options.trimHeadFrames += 1; - - var frames = this._prepareFrames(stack, options); - data.stacktrace = { - // Sentry expects frames oldest to newest - frames: frames.reverse() - }; - } - - // Make sure that fingerprint is always wrapped in an array - if (data.fingerprint) { - data.fingerprint = isArray$1(data.fingerprint) - ? data.fingerprint - : [data.fingerprint]; - } - - // Fire away! - this._send(data); - - return this; - }, - - captureBreadcrumb: function(obj) { - var crumb = objectMerge$1( - { - timestamp: now() / 1000 - }, - obj - ); - - if (isFunction$1(this._globalOptions.breadcrumbCallback)) { - var result = this._globalOptions.breadcrumbCallback(crumb); - - if (isObject$1(result) && !isEmptyObject$1(result)) { - crumb = result; - } else if (result === false) { - return this; - } - } - - this._breadcrumbs.push(crumb); - if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) { - this._breadcrumbs.shift(); - } - return this; - }, - - addPlugin: function(plugin /*arg1, arg2, ... argN*/) { - var pluginArgs = [].slice.call(arguments, 1); - - this._plugins.push([plugin, pluginArgs]); - if (this._isRavenInstalled) { - this._drainPlugins(); - } - - return this; - }, - - /* - * Set/clear a user to be sent along with the payload. - * - * @param {object} user An object representing user data [optional] - * @return {Raven} - */ - setUserContext: function(user) { - // Intentionally do not merge here since that's an unexpected behavior. - this._globalContext.user = user; - - return this; - }, - - /* - * Merge extra attributes to be sent along with the payload. - * - * @param {object} extra An object representing extra data [optional] - * @return {Raven} - */ - setExtraContext: function(extra) { - this._mergeContext('extra', extra); - - return this; - }, - - /* - * Merge tags to be sent along with the payload. - * - * @param {object} tags An object representing tags [optional] - * @return {Raven} - */ - setTagsContext: function(tags) { - this._mergeContext('tags', tags); - - return this; - }, - - /* - * Clear all of the context. - * - * @return {Raven} - */ - clearContext: function() { - this._globalContext = {}; - - return this; - }, - - /* - * Get a copy of the current context. This cannot be mutated. - * - * @return {object} copy of context - */ - getContext: function() { - // lol javascript - return JSON.parse(stringify_1(this._globalContext)); - }, - - /* - * Set environment of application - * - * @param {string} environment Typically something like 'production'. - * @return {Raven} - */ - setEnvironment: function(environment) { - this._globalOptions.environment = environment; - - return this; - }, - - /* - * Set release version of application - * - * @param {string} release Typically something like a git SHA to identify version - * @return {Raven} - */ - setRelease: function(release) { - this._globalOptions.release = release; - - return this; - }, - - /* - * Set the dataCallback option - * - * @param {function} callback The callback to run which allows the - * data blob to be mutated before sending - * @return {Raven} - */ - setDataCallback: function(callback) { - var original = this._globalOptions.dataCallback; - this._globalOptions.dataCallback = keepOriginalCallback(original, callback); - return this; - }, - - /* - * Set the breadcrumbCallback option - * - * @param {function} callback The callback to run which allows filtering - * or mutating breadcrumbs - * @return {Raven} - */ - setBreadcrumbCallback: function(callback) { - var original = this._globalOptions.breadcrumbCallback; - this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback); - return this; - }, - - /* - * Set the shouldSendCallback option - * - * @param {function} callback The callback to run which allows - * introspecting the blob before sending - * @return {Raven} - */ - setShouldSendCallback: function(callback) { - var original = this._globalOptions.shouldSendCallback; - this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback); - return this; - }, - - /** - * Override the default HTTP transport mechanism that transmits data - * to the Sentry server. - * - * @param {function} transport Function invoked instead of the default - * `makeRequest` handler. - * - * @return {Raven} - */ - setTransport: function(transport) { - this._globalOptions.transport = transport; - - return this; - }, - - /* - * Get the latest raw exception that was captured by Raven. - * - * @return {error} - */ - lastException: function() { - return this._lastCapturedException; - }, - - /* - * Get the last event id - * - * @return {string} - */ - lastEventId: function() { - return this._lastEventId; - }, - - /* - * Determine if Raven is setup and ready to go. - * - * @return {boolean} - */ - isSetup: function() { - if (!this._hasJSON) return false; // needs JSON support - if (!this._globalServer) { - if (!this.ravenNotConfiguredError) { - this.ravenNotConfiguredError = true; - this._logDebug('error', 'Error: Raven has not been configured.'); - } - return false; - } - return true; - }, - - afterLoad: function() { - // TODO: remove window dependence? - - // Attempt to initialize Raven on load - var RavenConfig = _window$2.RavenConfig; - if (RavenConfig) { - this.config(RavenConfig.dsn, RavenConfig.config).install(); - } - }, - - showReportDialog: function(options) { - if ( - !_document // doesn't work without a document (React native) - ) - return; - - options = options || {}; - - var lastEventId = options.eventId || this.lastEventId(); - if (!lastEventId) { - throw new configError('Missing eventId'); - } - - var dsn = options.dsn || this._dsn; - if (!dsn) { - throw new configError('Missing DSN'); - } - - var encode = encodeURIComponent; - var qs = ''; - qs += '?eventId=' + encode(lastEventId); - qs += '&dsn=' + encode(dsn); - - var user = options.user || this._globalContext.user; - if (user) { - if (user.name) qs += '&name=' + encode(user.name); - if (user.email) qs += '&email=' + encode(user.email); - } - - var globalServer = this._getGlobalServer(this._parseDSN(dsn)); - - var script = _document.createElement('script'); - script.async = true; - script.src = globalServer + '/api/embed/error-page/' + qs; - (_document.head || _document.body).appendChild(script); - }, - - /**** Private functions ****/ - _ignoreNextOnError: function() { - var self = this; - this._ignoreOnError += 1; - setTimeout(function() { - // onerror should trigger before setTimeout - self._ignoreOnError -= 1; - }); - }, - - _triggerEvent: function(eventType, options) { - // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it - var evt, key; - - if (!this._hasDocument) return; - - options = options || {}; - - eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1); - - if (_document.createEvent) { - evt = _document.createEvent('HTMLEvents'); - evt.initEvent(eventType, true, true); - } else { - evt = _document.createEventObject(); - evt.eventType = eventType; - } - - for (key in options) - if (hasKey$1(options, key)) { - evt[key] = options[key]; - } - - if (_document.createEvent) { - // IE9 if standards - _document.dispatchEvent(evt); - } else { - // IE8 regardless of Quirks or Standards - // IE9 if quirks - try { - _document.fireEvent('on' + evt.eventType.toLowerCase(), evt); - } catch (e) { - // Do nothing - } - } - }, - - /** - * Wraps addEventListener to capture UI breadcrumbs - * @param evtName the event name (e.g. "click") - * @returns {Function} - * @private - */ - _breadcrumbEventHandler: function(evtName) { - var self = this; - return function(evt) { - // reset keypress timeout; e.g. triggering a 'click' after - // a 'keypress' will reset the keypress debounce so that a new - // set of keypresses can be recorded - self._keypressTimeout = null; - - // It's possible this handler might trigger multiple times for the same - // event (e.g. event propagation through node ancestors). Ignore if we've - // already captured the event. - if (self._lastCapturedEvent === evt) return; - - self._lastCapturedEvent = evt; - - // try/catch both: - // - accessing evt.target (see getsentry/raven-js#838, #768) - // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly - // can throw an exception in some circumstances. - var target; - try { - target = htmlTreeAsString$1(evt.target); - } catch (e) { - target = '<unknown>'; - } - - self.captureBreadcrumb({ - category: 'ui.' + evtName, // e.g. ui.click, ui.input - message: target - }); - }; - }, - - /** - * Wraps addEventListener to capture keypress UI events - * @returns {Function} - * @private - */ - _keypressEventHandler: function() { - var self = this, - debounceDuration = 1000; // milliseconds - - // TODO: if somehow user switches keypress target before - // debounce timeout is triggered, we will only capture - // a single breadcrumb from the FIRST target (acceptable?) - return function(evt) { - var target; - try { - target = evt.target; - } catch (e) { - // just accessing event properties can throw an exception in some rare circumstances - // see: https://github.com/getsentry/raven-js/issues/838 - return; - } - var tagName = target && target.tagName; - - // only consider keypress events on actual input elements - // this will disregard keypresses targeting body (e.g. tabbing - // through elements, hotkeys, etc) - if ( - !tagName || - (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable) - ) - return; - - // record first keypress in a series, but ignore subsequent - // keypresses until debounce clears - var timeout = self._keypressTimeout; - if (!timeout) { - self._breadcrumbEventHandler('input')(evt); - } - clearTimeout(timeout); - self._keypressTimeout = setTimeout(function() { - self._keypressTimeout = null; - }, debounceDuration); - }; - }, - - /** - * Captures a breadcrumb of type "navigation", normalizing input URLs - * @param to the originating URL - * @param from the target URL - * @private - */ - _captureUrlChange: function(from, to) { - var parsedLoc = parseUrl$1(this._location.href); - var parsedTo = parseUrl$1(to); - var parsedFrom = parseUrl$1(from); - - // because onpopstate only tells you the "new" (to) value of location.href, and - // not the previous (from) value, we need to track the value of the current URL - // state ourselves - this._lastHref = to; - - // Use only the path component of the URL if the URL matches the current - // document (almost all the time when using pushState) - if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) - to = parsedTo.relative; - if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) - from = parsedFrom.relative; - - this.captureBreadcrumb({ - category: 'navigation', - data: { - to: to, - from: from - } - }); - }, - - _patchFunctionToString: function() { - var self = this; - self._originalFunctionToString = Function.prototype.toString; - // eslint-disable-next-line no-extend-native - Function.prototype.toString = function() { - if (typeof this === 'function' && this.__raven__) { - return self._originalFunctionToString.apply(this.__orig__, arguments); - } - return self._originalFunctionToString.apply(this, arguments); - }; - }, - - _unpatchFunctionToString: function() { - if (this._originalFunctionToString) { - // eslint-disable-next-line no-extend-native - Function.prototype.toString = this._originalFunctionToString; - } - }, - - /** - * Wrap timer functions and event targets to catch errors and provide - * better metadata. - */ - _instrumentTryCatch: function() { - var self = this; - - var wrappedBuiltIns = self._wrappedBuiltIns; - - function wrapTimeFn(orig) { - return function(fn, t) { - // preserve arity - // Make a copy of the arguments to prevent deoptimization - // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) { - args[i] = arguments[i]; - } - var originalCallback = args[0]; - if (isFunction$1(originalCallback)) { - args[0] = self.wrap(originalCallback); - } - - // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it - // also supports only two arguments and doesn't care what this is, so we - // can just call the original function directly. - if (orig.apply) { - return orig.apply(this, args); - } else { - return orig(args[0], args[1]); - } - }; - } - - var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; - - function wrapEventTarget(global) { - var proto = _window$2[global] && _window$2[global].prototype; - if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) { - fill$1( - proto, - 'addEventListener', - function(orig) { - return function(evtName, fn, capture, secure) { - // preserve arity - try { - if (fn && fn.handleEvent) { - fn.handleEvent = self.wrap(fn.handleEvent); - } - } catch (err) { - // can sometimes get 'Permission denied to access property "handle Event' - } - - // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs` - // so that we don't have more than one wrapper function - var before, clickHandler, keypressHandler; - - if ( - autoBreadcrumbs && - autoBreadcrumbs.dom && - (global === 'EventTarget' || global === 'Node') - ) { - // NOTE: generating multiple handlers per addEventListener invocation, should - // revisit and verify we can just use one (almost certainly) - clickHandler = self._breadcrumbEventHandler('click'); - keypressHandler = self._keypressEventHandler(); - before = function(evt) { - // need to intercept every DOM event in `before` argument, in case that - // same wrapped method is re-used for different events (e.g. mousemove THEN click) - // see #724 - if (!evt) return; - - var eventType; - try { - eventType = evt.type; - } catch (e) { - // just accessing event properties can throw an exception in some rare circumstances - // see: https://github.com/getsentry/raven-js/issues/838 - return; - } - if (eventType === 'click') return clickHandler(evt); - else if (eventType === 'keypress') return keypressHandler(evt); - }; - } - return orig.call( - this, - evtName, - self.wrap(fn, undefined, before), - capture, - secure - ); - }; - }, - wrappedBuiltIns - ); - fill$1( - proto, - 'removeEventListener', - function(orig) { - return function(evt, fn, capture, secure) { - try { - fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn); - } catch (e) { - // ignore, accessing __raven_wrapper__ will throw in some Selenium environments - } - return orig.call(this, evt, fn, capture, secure); - }; - }, - wrappedBuiltIns - ); - } - } - - fill$1(_window$2, 'setTimeout', wrapTimeFn, wrappedBuiltIns); - fill$1(_window$2, 'setInterval', wrapTimeFn, wrappedBuiltIns); - if (_window$2.requestAnimationFrame) { - fill$1( - _window$2, - 'requestAnimationFrame', - function(orig) { - return function(cb) { - return orig(self.wrap(cb)); - }; - }, - wrappedBuiltIns - ); - } - - // event targets borrowed from bugsnag-js: - // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666 - var eventTargets = [ - 'EventTarget', - 'Window', - 'Node', - 'ApplicationCache', - 'AudioTrackList', - 'ChannelMergerNode', - 'CryptoOperation', - 'EventSource', - 'FileReader', - 'HTMLUnknownElement', - 'IDBDatabase', - 'IDBRequest', - 'IDBTransaction', - 'KeyOperation', - 'MediaController', - 'MessagePort', - 'ModalWindow', - 'Notification', - 'SVGElementInstance', - 'Screen', - 'TextTrack', - 'TextTrackCue', - 'TextTrackList', - 'WebSocket', - 'WebSocketWorker', - 'Worker', - 'XMLHttpRequest', - 'XMLHttpRequestEventTarget', - 'XMLHttpRequestUpload' - ]; - for (var i = 0; i < eventTargets.length; i++) { - wrapEventTarget(eventTargets[i]); - } - }, - - /** - * Instrument browser built-ins w/ breadcrumb capturing - * - XMLHttpRequests - * - DOM interactions (click/typing) - * - window.location changes - * - console - * - * Can be disabled or individually configured via the `autoBreadcrumbs` config option - */ - _instrumentBreadcrumbs: function() { - var self = this; - var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; - - var wrappedBuiltIns = self._wrappedBuiltIns; - - function wrapProp(prop, xhr) { - if (prop in xhr && isFunction$1(xhr[prop])) { - fill$1(xhr, prop, function(orig) { - return self.wrap(orig); - }); // intentionally don't track filled methods on XHR instances - } - } - - if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window$2) { - var xhrproto = _window$2.XMLHttpRequest && _window$2.XMLHttpRequest.prototype; - fill$1( - xhrproto, - 'open', - function(origOpen) { - return function(method, url) { - // preserve arity - - // if Sentry key appears in URL, don't capture - if (isString$1(url) && url.indexOf(self._globalKey) === -1) { - this.__raven_xhr = { - method: method, - url: url, - status_code: null - }; - } - - return origOpen.apply(this, arguments); - }; - }, - wrappedBuiltIns - ); - - fill$1( - xhrproto, - 'send', - function(origSend) { - return function() { - // preserve arity - var xhr = this; - - function onreadystatechangeHandler() { - if (xhr.__raven_xhr && xhr.readyState === 4) { - try { - // touching statusCode in some platforms throws - // an exception - xhr.__raven_xhr.status_code = xhr.status; - } catch (e) { - /* do nothing */ - } - - self.captureBreadcrumb({ - type: 'http', - category: 'xhr', - data: xhr.__raven_xhr - }); - } - } - - var props = ['onload', 'onerror', 'onprogress']; - for (var j = 0; j < props.length; j++) { - wrapProp(props[j], xhr); - } - - if ('onreadystatechange' in xhr && isFunction$1(xhr.onreadystatechange)) { - fill$1( - xhr, - 'onreadystatechange', - function(orig) { - return self.wrap(orig, undefined, onreadystatechangeHandler); - } /* intentionally don't track this instrumentation */ - ); - } else { - // if onreadystatechange wasn't actually set by the page on this xhr, we - // are free to set our own and capture the breadcrumb - xhr.onreadystatechange = onreadystatechangeHandler; - } - - return origSend.apply(this, arguments); - }; - }, - wrappedBuiltIns - ); - } - - if (autoBreadcrumbs.xhr && supportsFetch$1()) { - fill$1( - _window$2, - 'fetch', - function(origFetch) { - return function() { - // preserve arity - // Make a copy of the arguments to prevent deoptimization - // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) { - args[i] = arguments[i]; - } - - var fetchInput = args[0]; - var method = 'GET'; - var url; - - if (typeof fetchInput === 'string') { - url = fetchInput; - } else if ('Request' in _window$2 && fetchInput instanceof _window$2.Request) { - url = fetchInput.url; - if (fetchInput.method) { - method = fetchInput.method; - } - } else { - url = '' + fetchInput; - } - - // if Sentry key appears in URL, don't capture, as it's our own request - if (url.indexOf(self._globalKey) !== -1) { - return origFetch.apply(this, args); - } - - if (args[1] && args[1].method) { - method = args[1].method; - } - - var fetchData = { - method: method, - url: url, - status_code: null - }; - - return origFetch - .apply(this, args) - .then(function(response) { - fetchData.status_code = response.status; - - self.captureBreadcrumb({ - type: 'http', - category: 'fetch', - data: fetchData - }); - - return response; - }) - ['catch'](function(err) { - // if there is an error performing the request - self.captureBreadcrumb({ - type: 'http', - category: 'fetch', - data: fetchData, - level: 'error' - }); - - throw err; - }); - }; - }, - wrappedBuiltIns - ); - } - - // Capture breadcrumbs from any click that is unhandled / bubbled up all the way - // to the document. Do this before we instrument addEventListener. - if (autoBreadcrumbs.dom && this._hasDocument) { - if (_document.addEventListener) { - _document.addEventListener('click', self._breadcrumbEventHandler('click'), false); - _document.addEventListener('keypress', self._keypressEventHandler(), false); - } else if (_document.attachEvent) { - // IE8 Compatibility - _document.attachEvent('onclick', self._breadcrumbEventHandler('click')); - _document.attachEvent('onkeypress', self._keypressEventHandler()); - } - } - - // record navigation (URL) changes - // NOTE: in Chrome App environment, touching history.pushState, *even inside - // a try/catch block*, will cause Chrome to output an error to console.error - // borrowed from: https://github.com/angular/angular.js/pull/13945/files - var chrome = _window$2.chrome; - var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime; - var hasPushAndReplaceState = - !isChromePackagedApp && - _window$2.history && - history.pushState && - history.replaceState; - if (autoBreadcrumbs.location && hasPushAndReplaceState) { - // TODO: remove onpopstate handler on uninstall() - var oldOnPopState = _window$2.onpopstate; - _window$2.onpopstate = function() { - var currentHref = self._location.href; - self._captureUrlChange(self._lastHref, currentHref); - - if (oldOnPopState) { - return oldOnPopState.apply(this, arguments); - } - }; - - var historyReplacementFunction = function(origHistFunction) { - // note history.pushState.length is 0; intentionally not declaring - // params to preserve 0 arity - return function(/* state, title, url */) { - var url = arguments.length > 2 ? arguments[2] : undefined; - - // url argument is optional - if (url) { - // coerce to string (this is what pushState does) - self._captureUrlChange(self._lastHref, url + ''); - } - - return origHistFunction.apply(this, arguments); - }; - }; - - fill$1(history, 'pushState', historyReplacementFunction, wrappedBuiltIns); - fill$1(history, 'replaceState', historyReplacementFunction, wrappedBuiltIns); - } - - if (autoBreadcrumbs.console && 'console' in _window$2 && console.log) { - // console - var consoleMethodCallback = function(msg, data) { - self.captureBreadcrumb({ - message: msg, - level: data.level, - category: 'console' - }); - }; - - each$1(['debug', 'info', 'warn', 'error', 'log'], function(_, level) { - wrapConsoleMethod(console, level, consoleMethodCallback); - }); - } - }, - - _restoreBuiltIns: function() { - // restore any wrapped builtins - var builtin; - while (this._wrappedBuiltIns.length) { - builtin = this._wrappedBuiltIns.shift(); - - var obj = builtin[0], - name = builtin[1], - orig = builtin[2]; - - obj[name] = orig; - } - }, - - _restoreConsole: function() { - // eslint-disable-next-line guard-for-in - for (var method in this._originalConsoleMethods) { - this._originalConsole[method] = this._originalConsoleMethods[method]; - } - }, - - _drainPlugins: function() { - var self = this; - - // FIX ME TODO - each$1(this._plugins, function(_, plugin) { - var installer = plugin[0]; - var args = plugin[1]; - installer.apply(self, [self].concat(args)); - }); - }, - - _parseDSN: function(str) { - var m = dsnPattern.exec(str), - dsn = {}, - i = 7; - - try { - while (i--) dsn[dsnKeys[i]] = m[i] || ''; - } catch (e) { - throw new configError('Invalid DSN: ' + str); - } - - if (dsn.pass && !this._globalOptions.allowSecretKey) { - throw new configError( - 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key' - ); - } - - return dsn; - }, - - _getGlobalServer: function(uri) { - // assemble the endpoint from the uri pieces - var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : ''); - - if (uri.protocol) { - globalServer = uri.protocol + ':' + globalServer; - } - return globalServer; - }, - - _handleOnErrorStackInfo: function() { - // if we are intentionally ignoring errors via onerror, bail out - if (!this._ignoreOnError) { - this._handleStackInfo.apply(this, arguments); - } - }, - - _handleStackInfo: function(stackInfo, options) { - var frames = this._prepareFrames(stackInfo, options); - - this._triggerEvent('handle', { - stackInfo: stackInfo, - options: options - }); - - this._processException( - stackInfo.name, - stackInfo.message, - stackInfo.url, - stackInfo.lineno, - frames, - options - ); - }, - - _prepareFrames: function(stackInfo, options) { - var self = this; - var frames = []; - if (stackInfo.stack && stackInfo.stack.length) { - each$1(stackInfo.stack, function(i, stack) { - var frame = self._normalizeFrame(stack, stackInfo.url); - if (frame) { - frames.push(frame); - } - }); - - // e.g. frames captured via captureMessage throw - if (options && options.trimHeadFrames) { - for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) { - frames[j].in_app = false; - } - } - } - frames = frames.slice(0, this._globalOptions.stackTraceLimit); - return frames; - }, - - _normalizeFrame: function(frame, stackInfoUrl) { - // normalize the frames data - var normalized = { - filename: frame.url, - lineno: frame.line, - colno: frame.column, - function: frame.func || '?' - }; - - // Case when we don't have any information about the error - // E.g. throwing a string or raw object, instead of an `Error` in Firefox - // Generating synthetic error doesn't add any value here - // - // We should probably somehow let a user know that they should fix their code - if (!frame.url) { - normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler - } - - normalized.in_app = !// determine if an exception came from outside of our app - // first we check the global includePaths list. - ( - (!!this._globalOptions.includePaths.test && - !this._globalOptions.includePaths.test(normalized.filename)) || - // Now we check for fun, if the function name is Raven or TraceKit - /(Raven|TraceKit)\./.test(normalized['function']) || - // finally, we do a last ditch effort and check for raven.min.js - /raven\.(min\.)?js$/.test(normalized.filename) - ); - - return normalized; - }, - - _processException: function(type, message, fileurl, lineno, frames, options) { - var prefixedMessage = (type ? type + ': ' : '') + (message || ''); - if ( - !!this._globalOptions.ignoreErrors.test && - (this._globalOptions.ignoreErrors.test(message) || - this._globalOptions.ignoreErrors.test(prefixedMessage)) - ) { - return; - } - - var stacktrace; - - if (frames && frames.length) { - fileurl = frames[0].filename || fileurl; - // Sentry expects frames oldest to newest - // and JS sends them as newest to oldest - frames.reverse(); - stacktrace = {frames: frames}; - } else if (fileurl) { - stacktrace = { - frames: [ - { - filename: fileurl, - lineno: lineno, - in_app: true - } - ] - }; - } - - if ( - !!this._globalOptions.ignoreUrls.test && - this._globalOptions.ignoreUrls.test(fileurl) - ) { - return; - } - - if ( - !!this._globalOptions.whitelistUrls.test && - !this._globalOptions.whitelistUrls.test(fileurl) - ) { - return; - } - - var data = objectMerge$1( - { - // sentry.interfaces.Exception - exception: { - values: [ - { - type: type, - value: message, - stacktrace: stacktrace - } - ] - }, - culprit: fileurl - }, - options - ); - - // Fire away! - this._send(data); - }, - - _trimPacket: function(data) { - // For now, we only want to truncate the two different messages - // but this could/should be expanded to just trim everything - var max = this._globalOptions.maxMessageLength; - if (data.message) { - data.message = truncate$1(data.message, max); - } - if (data.exception) { - var exception = data.exception.values[0]; - exception.value = truncate$1(exception.value, max); - } - - var request = data.request; - if (request) { - if (request.url) { - request.url = truncate$1(request.url, this._globalOptions.maxUrlLength); - } - if (request.Referer) { - request.Referer = truncate$1(request.Referer, this._globalOptions.maxUrlLength); - } - } - - if (data.breadcrumbs && data.breadcrumbs.values) - this._trimBreadcrumbs(data.breadcrumbs); - - return data; - }, - - /** - * Truncate breadcrumb values (right now just URLs) - */ - _trimBreadcrumbs: function(breadcrumbs) { - // known breadcrumb properties with urls - // TODO: also consider arbitrary prop values that start with (https?)?:// - var urlProps = ['to', 'from', 'url'], - urlProp, - crumb, - data; - - for (var i = 0; i < breadcrumbs.values.length; ++i) { - crumb = breadcrumbs.values[i]; - if ( - !crumb.hasOwnProperty('data') || - !isObject$1(crumb.data) || - objectFrozen$1(crumb.data) - ) - continue; - - data = objectMerge$1({}, crumb.data); - for (var j = 0; j < urlProps.length; ++j) { - urlProp = urlProps[j]; - if (data.hasOwnProperty(urlProp) && data[urlProp]) { - data[urlProp] = truncate$1(data[urlProp], this._globalOptions.maxUrlLength); - } - } - breadcrumbs.values[i].data = data; - } - }, - - _getHttpData: function() { - if (!this._hasNavigator && !this._hasDocument) return; - var httpData = {}; - - if (this._hasNavigator && _navigator.userAgent) { - httpData.headers = { - 'User-Agent': navigator.userAgent - }; - } - - // Check in `window` instead of `document`, as we may be in ServiceWorker environment - if (_window$2.location && _window$2.location.href) { - httpData.url = _window$2.location.href; - } - - if (this._hasDocument && _document.referrer) { - if (!httpData.headers) httpData.headers = {}; - httpData.headers.Referer = _document.referrer; - } - - return httpData; - }, - - _resetBackoff: function() { - this._backoffDuration = 0; - this._backoffStart = null; - }, - - _shouldBackoff: function() { - return this._backoffDuration && now() - this._backoffStart < this._backoffDuration; - }, - - /** - * Returns true if the in-process data payload matches the signature - * of the previously-sent data - * - * NOTE: This has to be done at this level because TraceKit can generate - * data from window.onerror WITHOUT an exception object (IE8, IE9, - * other old browsers). This can take the form of an "exception" - * data object with a single frame (derived from the onerror args). - */ - _isRepeatData: function(current) { - var last = this._lastData; - - if ( - !last || - current.message !== last.message || // defined for captureMessage - current.culprit !== last.culprit // defined for captureException/onerror - ) - return false; - - // Stacktrace interface (i.e. from captureMessage) - if (current.stacktrace || last.stacktrace) { - return isSameStacktrace$1(current.stacktrace, last.stacktrace); - } else if (current.exception || last.exception) { - // Exception interface (i.e. from captureException/onerror) - return isSameException$1(current.exception, last.exception); - } - - return true; - }, - - _setBackoffState: function(request) { - // If we are already in a backoff state, don't change anything - if (this._shouldBackoff()) { - return; - } - - var status = request.status; - - // 400 - project_id doesn't exist or some other fatal - // 401 - invalid/revoked dsn - // 429 - too many requests - if (!(status === 400 || status === 401 || status === 429)) return; - - var retry; - try { - // If Retry-After is not in Access-Control-Expose-Headers, most - // browsers will throw an exception trying to access it - if (supportsFetch$1()) { - retry = request.headers.get('Retry-After'); - } else { - retry = request.getResponseHeader('Retry-After'); - } - - // Retry-After is returned in seconds - retry = parseInt(retry, 10) * 1000; - } catch (e) { - /* eslint no-empty:0 */ - } - - this._backoffDuration = retry - ? // If Sentry server returned a Retry-After value, use it - retry - : // Otherwise, double the last backoff duration (starts at 1 sec) - this._backoffDuration * 2 || 1000; - - this._backoffStart = now(); - }, - - _send: function(data) { - var globalOptions = this._globalOptions; - - var baseData = { - project: this._globalProject, - logger: globalOptions.logger, - platform: 'javascript' - }, - httpData = this._getHttpData(); - - if (httpData) { - baseData.request = httpData; - } - - // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload - if (data.trimHeadFrames) delete data.trimHeadFrames; - - data = objectMerge$1(baseData, data); - - // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge - data.tags = objectMerge$1(objectMerge$1({}, this._globalContext.tags), data.tags); - data.extra = objectMerge$1(objectMerge$1({}, this._globalContext.extra), data.extra); - - // Send along our own collected metadata with extra - data.extra['session:duration'] = now() - this._startTime; - - if (this._breadcrumbs && this._breadcrumbs.length > 0) { - // intentionally make shallow copy so that additions - // to breadcrumbs aren't accidentally sent in this request - data.breadcrumbs = { - values: [].slice.call(this._breadcrumbs, 0) - }; - } - - if (this._globalContext.user) { - // sentry.interfaces.User - data.user = this._globalContext.user; - } - - // Include the environment if it's defined in globalOptions - if (globalOptions.environment) data.environment = globalOptions.environment; - - // Include the release if it's defined in globalOptions - if (globalOptions.release) data.release = globalOptions.release; - - // Include server_name if it's defined in globalOptions - if (globalOptions.serverName) data.server_name = globalOptions.serverName; - - data = this._sanitizeData(data); - - // Cleanup empty properties before sending them to the server - Object.keys(data).forEach(function(key) { - if (data[key] == null || data[key] === '' || isEmptyObject$1(data[key])) { - delete data[key]; - } - }); - - if (isFunction$1(globalOptions.dataCallback)) { - data = globalOptions.dataCallback(data) || data; - } - - // Why?????????? - if (!data || isEmptyObject$1(data)) { - return; - } - - // Check if the request should be filtered or not - if ( - isFunction$1(globalOptions.shouldSendCallback) && - !globalOptions.shouldSendCallback(data) - ) { - return; - } - - // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests), - // so drop requests until "cool-off" period has elapsed. - if (this._shouldBackoff()) { - this._logDebug('warn', 'Raven dropped error due to backoff: ', data); - return; - } - - if (typeof globalOptions.sampleRate === 'number') { - if (Math.random() < globalOptions.sampleRate) { - this._sendProcessedPayload(data); - } - } else { - this._sendProcessedPayload(data); - } - }, - - _sanitizeData: function(data) { - return sanitize$1(data, this._globalOptions.sanitizeKeys); - }, - - _getUuid: function() { - return uuid4$1(); - }, - - _sendProcessedPayload: function(data, callback) { - var self = this; - var globalOptions = this._globalOptions; - - if (!this.isSetup()) return; - - // Try and clean up the packet before sending by truncating long values - data = this._trimPacket(data); - - // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback, - // but this would require copying an un-truncated copy of the data packet, which can be - // arbitrarily deep (extra_data) -- could be worthwhile? will revisit - if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) { - this._logDebug('warn', 'Raven dropped repeat event: ', data); - return; - } - - // Send along an event_id if not explicitly passed. - // This event_id can be used to reference the error within Sentry itself. - // Set lastEventId after we know the error should actually be sent - this._lastEventId = data.event_id || (data.event_id = this._getUuid()); - - // Store outbound payload after trim - this._lastData = data; - - this._logDebug('debug', 'Raven about to send:', data); - - var auth = { - sentry_version: '7', - sentry_client: 'raven-js/' + this.VERSION, - sentry_key: this._globalKey - }; - - if (this._globalSecret) { - auth.sentry_secret = this._globalSecret; - } - - var exception = data.exception && data.exception.values[0]; - - // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy - if ( - this._globalOptions.autoBreadcrumbs && - this._globalOptions.autoBreadcrumbs.sentry - ) { - this.captureBreadcrumb({ - category: 'sentry', - message: exception - ? (exception.type ? exception.type + ': ' : '') + exception.value - : data.message, - event_id: data.event_id, - level: data.level || 'error' // presume error unless specified - }); - } - - var url = this._globalEndpoint; - (globalOptions.transport || this._makeRequest).call(this, { - url: url, - auth: auth, - data: data, - options: globalOptions, - onSuccess: function success() { - self._resetBackoff(); - - self._triggerEvent('success', { - data: data, - src: url - }); - callback && callback(); - }, - onError: function failure(error) { - self._logDebug('error', 'Raven transport failed to send: ', error); - - if (error.request) { - self._setBackoffState(error.request); - } - - self._triggerEvent('failure', { - data: data, - src: url - }); - error = error || new Error('Raven send failed (no additional details provided)'); - callback && callback(error); - } - }); - }, - - _makeRequest: function(opts) { - // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests - var url = opts.url + '?' + urlencode$1(opts.auth); - - var evaluatedHeaders = null; - var evaluatedFetchParameters = {}; - - if (opts.options.headers) { - evaluatedHeaders = this._evaluateHash(opts.options.headers); - } - - if (opts.options.fetchParameters) { - evaluatedFetchParameters = this._evaluateHash(opts.options.fetchParameters); - } - - if (supportsFetch$1()) { - evaluatedFetchParameters.body = stringify_1(opts.data); - - var defaultFetchOptions = objectMerge$1({}, this._fetchDefaults); - var fetchOptions = objectMerge$1(defaultFetchOptions, evaluatedFetchParameters); - - if (evaluatedHeaders) { - fetchOptions.headers = evaluatedHeaders; - } - - return _window$2 - .fetch(url, fetchOptions) - .then(function(response) { - if (response.ok) { - opts.onSuccess && opts.onSuccess(); - } else { - var error = new Error('Sentry error code: ' + response.status); - // It's called request only to keep compatibility with XHR interface - // and not add more redundant checks in setBackoffState method - error.request = response; - opts.onError && opts.onError(error); - } - }) - ['catch'](function() { - opts.onError && - opts.onError(new Error('Sentry error code: network unavailable')); - }); - } - - var request = _window$2.XMLHttpRequest && new _window$2.XMLHttpRequest(); - if (!request) return; - - // if browser doesn't support CORS (e.g. IE7), we are out of luck - var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined'; - - if (!hasCORS) return; - - if ('withCredentials' in request) { - request.onreadystatechange = function() { - if (request.readyState !== 4) { - return; - } else if (request.status === 200) { - opts.onSuccess && opts.onSuccess(); - } else if (opts.onError) { - var err = new Error('Sentry error code: ' + request.status); - err.request = request; - opts.onError(err); - } - }; - } else { - request = new XDomainRequest(); - // xdomainrequest cannot go http -> https (or vice versa), - // so always use protocol relative - url = url.replace(/^https?:/, ''); - - // onreadystatechange not supported by XDomainRequest - if (opts.onSuccess) { - request.onload = opts.onSuccess; - } - if (opts.onError) { - request.onerror = function() { - var err = new Error('Sentry error code: XDomainRequest'); - err.request = request; - opts.onError(err); - }; - } - } - - request.open('POST', url); - - if (evaluatedHeaders) { - each$1(evaluatedHeaders, function(key, value) { - request.setRequestHeader(key, value); - }); - } - - request.send(stringify_1(opts.data)); - }, - - _evaluateHash: function(hash) { - var evaluated = {}; - - for (var key in hash) { - if (hash.hasOwnProperty(key)) { - var value = hash[key]; - evaluated[key] = typeof value === 'function' ? value() : value; - } - } - - return evaluated; - }, - - _logDebug: function(level) { - // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change - if ( - this._originalConsoleMethods[level] && - (this.debug || this._globalOptions.debug) - ) { - // In IE<10 console methods do not have their own 'apply' method - Function.prototype.apply.call( - this._originalConsoleMethods[level], - this._originalConsole, - [].slice.call(arguments, 1) - ); - } - }, - - _mergeContext: function(key, context) { - if (isUndefined$1(context)) { - delete this._globalContext[key]; - } else { - this._globalContext[key] = objectMerge$1(this._globalContext[key] || {}, context); - } - } -}; - -// Deprecations -Raven.prototype.setUser = Raven.prototype.setUserContext; -Raven.prototype.setReleaseContext = Raven.prototype.setRelease; - -var raven = Raven; - -/** - * Enforces a single instance of the Raven client, and the - * main entry point for Raven. If you are a consumer of the - * Raven library, you SHOULD load this file (vs raven.js). - **/ - - - -// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) -var _window$3 = - typeof window !== 'undefined' - ? window - : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; -var _Raven = _window$3.Raven; - -var Raven$1 = new raven(); - -/* - * Allow multiple versions of Raven to be installed. - * Strip Raven from the global context and returns the instance. - * - * @return {Raven} - */ -Raven$1.noConflict = function() { - _window$3.Raven = _Raven; - return Raven$1; -}; - -Raven$1.afterLoad(); - -var singleton = Raven$1; - -/** - * DISCLAIMER: - * - * Expose `Client` constructor for cases where user want to track multiple "sub-applications" in one larger app. - * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it. - * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug. - * - * It's called `Client' to be in-line with Raven Node implementation. - * - * HOWTO: - * - * import Raven from 'raven-js'; - * - * const someAppReporter = new Raven.Client(); - * const someOtherAppReporter = new Raven.Client(); - * - * someAppReporter.config('__DSN__', { - * ...config goes here - * }); - * - * someOtherAppReporter.config('__OTHER_DSN__', { - * ...config goes here - * }); - * - * someAppReporter.captureMessage(...); - * someAppReporter.captureException(...); - * someAppReporter.captureBreadcrumb(...); - * - * someOtherAppReporter.captureMessage(...); - * someOtherAppReporter.captureException(...); - * someOtherAppReporter.captureBreadcrumb(...); - * - * It should "just work". - */ -var Client = raven; -singleton.Client = Client; - -// ========================================================================== - -(function () { - var isLive = window.location.host === 'plyr.io'; - - // Raven / Sentry - // For demo site (https://plyr.io) only - if (isLive) { - singleton.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install(); - } - - document.addEventListener('DOMContentLoaded', function () { - singleton.context(function () { - if (window.shr) { - window.shr.setup({ - count: { - classname: 'button__count' - } - }); - } - - // Setup tab focus - var tabClassName = 'tab-focus'; - - // Remove class on blur - document.addEventListener('focusout', function (event) { - event.target.classList.remove(tabClassName); - }); - - // Add classname to tabbed elements - document.addEventListener('keydown', function (event) { - if (event.keyCode !== 9) { - return; - } - - // Delay the adding of classname until the focus has changed - // This event fires before the focusin event - setTimeout(function () { - document.activeElement.classList.add(tabClassName); - }, 0); - }); - - // Setup the player - var player = new Plyr('#player', { - debug: true, - title: 'View From A Blue Moon', - iconUrl: '../dist/plyr.svg', - keyboard: { - global: true - }, - tooltips: { - controls: true - }, - /* controls: [ - 'play-large', - 'restart', - 'rewind', - 'play', - 'fast-forward', - 'progress', - 'current-time', - 'duration', - 'mute', - 'volume', - 'captions', - 'settings', - 'pip', - 'airplay', - 'fullscreen', - ], */ - /* i18n: { - restart: '重新開始', - rewind: '快退{seektime}秒', - play: '播放', - pause: '暫停', - fastForward: '快進{seektime}秒', - seek: '尋求', - played: '發揮', - buffered: '緩衝的', - currentTime: '當前時間戳', - duration: '長短', - volume: '音量', - mute: '靜音', - unmute: '取消靜音', - enableCaptions: '開啟字幕', - disableCaptions: '關閉字幕', - enterFullscreen: '進入全螢幕', - exitFullscreen: '退出全螢幕', - frameTitle: '球員為{title}', - captions: '字幕', - settings: '設定', - speed: '速度', - normal: '正常', - quality: '質量', - loop: '循環', - start: 'Start', - end: 'End', - all: 'All', - reset: '重啟', - disabled: '殘', - enabled: '啟用', - advertisement: '廣告', - }, */ - captions: { - active: true - }, - keys: { - google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c' - }, - ads: { - enabled: true, - publisherId: '918848828995742' - } - }); - - // Expose for tinkering in the console - window.player = player; - - // Setup type toggle - var buttons = document.querySelectorAll('[data-source]'); - var types = { - video: 'video', - audio: 'audio', - youtube: 'youtube', - vimeo: 'vimeo' - }; - var currentType = window.location.hash.replace('#', ''); - var historySupport = window.history && window.history.pushState; - - // Toggle class on an element - function toggleClass(element, className, state) { - if (element) { - element.classList[state ? 'add' : 'remove'](className); - } - } - - // Set a new source - function newSource(type, init) { - // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video - if (!(type in types) || !init && type === currentType || !currentType.length && type === types.video) { - return; - } - - switch (type) { - case types.video: - player.source = { - type: 'video', - title: 'View From A Blue Moon', - sources: [{ - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4', - type: 'video/mp4', - size: 576 - }, { - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4', - type: 'video/mp4', - size: 720 - }, { - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4', - type: 'video/mp4', - size: 1080 - }, { - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4', - type: 'video/mp4', - size: 1440 - }], - poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', - tracks: [{ - kind: 'captions', - label: 'English', - srclang: 'en', - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', - default: true - }, { - kind: 'captions', - label: 'French', - srclang: 'fr', - src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt' - }] - }; - - break; - - case types.audio: - player.source = { - type: 'audio', - title: 'Kishi Bashi – “It All Began With A Burst”', - sources: [{ - src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3', - type: 'audio/mp3' - }, { - src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg', - type: 'audio/ogg' - }] - }; - - break; - - case types.youtube: - player.source = { - type: 'video', - sources: [{ - src: 'https://youtube.com/watch?v=bTqVqk7FSmY', - provider: 'youtube' - }] - }; - - break; - - case types.vimeo: - player.source = { - type: 'video', - sources: [{ - src: 'https://vimeo.com/76979871', - provider: 'vimeo' - }] - }; - - break; - - default: - break; - } - - // Set the current type for next time - currentType = type; - - // Remove active classes - Array.from(buttons).forEach(function (button) { - return toggleClass(button.parentElement, 'active', false); - }); - - // Set active on parent - toggleClass(document.querySelector('[data-source="' + type + '"]'), 'active', true); - - // Show cite - Array.from(document.querySelectorAll('.plyr__cite')).forEach(function (cite) { - cite.setAttribute('hidden', ''); - }); - document.querySelector('.plyr__cite--' + type).removeAttribute('hidden'); - } - - // Bind to each button - Array.from(buttons).forEach(function (button) { - button.addEventListener('click', function () { - var type = button.getAttribute('data-source'); - - newSource(type); - - if (historySupport) { - window.history.pushState({ type: type }, '', '#' + type); - } - }); - }); - - // List for backwards/forwards - window.addEventListener('popstate', function (event) { - if (event.state && 'type' in event.state) { - newSource(event.state.type); - } - }); - - // On load - if (historySupport) { - var video = !currentType.length; - - // If there's no current type set, assume video - if (video) { - currentType = types.video; - } - - // Replace current history state - if (currentType in types) { - window.history.replaceState({ - type: currentType - }, '', video ? '' : '#' + currentType); - } - - // If it's not video, load the source - if (currentType !== types.video) { - newSource(currentType, true); - } - } - }); - }); - - // Google analytics - // For demo site (https://plyr.io) only - /* eslint-disable */ - if (isLive) { - (function (i, s, o, g, r, a, m) { - i.GoogleAnalyticsObject = r; - i[r] = i[r] || function () { - (i[r].q = i[r].q || []).push(arguments); - }; - i[r].l = 1 * new Date(); - a = s.createElement(o); - m = s.getElementsByTagName(o)[0]; - a.async = 1; - a.src = g; - m.parentNode.insertBefore(a, m); - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - window.ga('create', 'UA-40881672-11', 'auto'); - window.ga('send', 'pageview'); - } - /* eslint-enable */ -})(); +typeof navigator === "object" && (function () { + 'use strict'; + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var stringify_1 = createCommonjsModule(function (module, exports) { + /* + json-stringify-safe + Like JSON.stringify, but doesn't throw on circular references. + + Originally forked from https://github.com/isaacs/json-stringify-safe + version 5.0.1 on 3/8/2017 and modified to handle Errors serialization + and IE8 compatibility. Tests for this are in test/vendor. + + ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE + */ + + exports = module.exports = stringify; + exports.getSerialize = serializer; + + function indexOf(haystack, needle) { + for (var i = 0; i < haystack.length; ++i) { + if (haystack[i] === needle) return i; + } + return -1; + } + + function stringify(obj, replacer, spaces, cycleReplacer) { + return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces); + } + + // https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106 + function stringifyError(value) { + var err = { + // These properties are implemented as magical getters and don't show up in for in + stack: value.stack, + message: value.message, + name: value.name + }; + + for (var i in value) { + if (Object.prototype.hasOwnProperty.call(value, i)) { + err[i] = value[i]; + } + } + + return err; + } + + function serializer(replacer, cycleReplacer) { + var stack = []; + var keys = []; + + if (cycleReplacer == null) { + cycleReplacer = function(key, value) { + if (stack[0] === value) { + return '[Circular ~]'; + } + return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']'; + }; + } + + return function(key, value) { + if (stack.length > 0) { + var thisPos = indexOf(stack, this); + ~thisPos ? stack.splice(thisPos + 1) : stack.push(this); + ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key); + + if (~indexOf(stack, value)) { + value = cycleReplacer.call(this, key, value); + } + } else { + stack.push(value); + } + + return replacer == null + ? value instanceof Error ? stringifyError(value) : value + : replacer.call(this, key, value); + }; + } + }); + var stringify_2 = stringify_1.getSerialize; + + var _window = + typeof window !== 'undefined' + ? window + : typeof commonjsGlobal !== 'undefined' + ? commonjsGlobal + : typeof self !== 'undefined' + ? self + : {}; + + function isObject(what) { + return typeof what === 'object' && what !== null; + } + + // Yanked from https://git.io/vS8DV re-used under CC0 + // with some tiny modifications + function isError(value) { + switch (Object.prototype.toString.call(value)) { + case '[object Error]': + return true; + case '[object Exception]': + return true; + case '[object DOMException]': + return true; + default: + return value instanceof Error; + } + } + + function isErrorEvent(value) { + return Object.prototype.toString.call(value) === '[object ErrorEvent]'; + } + + function isDOMError(value) { + return Object.prototype.toString.call(value) === '[object DOMError]'; + } + + function isDOMException(value) { + return Object.prototype.toString.call(value) === '[object DOMException]'; + } + + function isUndefined(what) { + return what === void 0; + } + + function isFunction(what) { + return typeof what === 'function'; + } + + function isPlainObject(what) { + return Object.prototype.toString.call(what) === '[object Object]'; + } + + function isString(what) { + return Object.prototype.toString.call(what) === '[object String]'; + } + + function isArray(what) { + return Object.prototype.toString.call(what) === '[object Array]'; + } + + function isEmptyObject(what) { + if (!isPlainObject(what)) return false; + + for (var _ in what) { + if (what.hasOwnProperty(_)) { + return false; + } + } + return true; + } + + function supportsErrorEvent() { + try { + new ErrorEvent(''); // eslint-disable-line no-new + return true; + } catch (e) { + return false; + } + } + + function supportsDOMError() { + try { + new DOMError(''); // eslint-disable-line no-new + return true; + } catch (e) { + return false; + } + } + + function supportsDOMException() { + try { + new DOMException(''); // eslint-disable-line no-new + return true; + } catch (e) { + return false; + } + } + + function supportsFetch() { + if (!('fetch' in _window)) return false; + + try { + new Headers(); // eslint-disable-line no-new + new Request(''); // eslint-disable-line no-new + new Response(); // eslint-disable-line no-new + return true; + } catch (e) { + return false; + } + } + + // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default + // https://caniuse.com/#feat=referrer-policy + // It doesn't. And it throw exception instead of ignoring this parameter... + // REF: https://github.com/getsentry/raven-js/issues/1233 + function supportsReferrerPolicy() { + if (!supportsFetch()) return false; + + try { + // eslint-disable-next-line no-new + new Request('pickleRick', { + referrerPolicy: 'origin' + }); + return true; + } catch (e) { + return false; + } + } + + function supportsPromiseRejectionEvent() { + return typeof PromiseRejectionEvent === 'function'; + } + + function wrappedCallback(callback) { + function dataCallback(data, original) { + var normalizedData = callback(data) || data; + if (original) { + return original(normalizedData) || normalizedData; + } + return normalizedData; + } + + return dataCallback; + } + + function each(obj, callback) { + var i, j; + + if (isUndefined(obj.length)) { + for (i in obj) { + if (hasKey(obj, i)) { + callback.call(null, i, obj[i]); + } + } + } else { + j = obj.length; + if (j) { + for (i = 0; i < j; i++) { + callback.call(null, i, obj[i]); + } + } + } + } + + function objectMerge(obj1, obj2) { + if (!obj2) { + return obj1; + } + each(obj2, function(key, value) { + obj1[key] = value; + }); + return obj1; + } + + /** + * This function is only used for react-native. + * react-native freezes object that have already been sent over the + * js bridge. We need this function in order to check if the object is frozen. + * So it's ok that objectFrozen returns false if Object.isFrozen is not + * supported because it's not relevant for other "platforms". See related issue: + * https://github.com/getsentry/react-native-sentry/issues/57 + */ + function objectFrozen(obj) { + if (!Object.isFrozen) { + return false; + } + return Object.isFrozen(obj); + } + + function truncate(str, max) { + if (typeof max !== 'number') { + throw new Error('2nd argument to `truncate` function should be a number'); + } + if (typeof str !== 'string' || max === 0) { + return str; + } + return str.length <= max ? str : str.substr(0, max) + '\u2026'; + } + + /** + * hasKey, a better form of hasOwnProperty + * Example: hasKey(MainHostObject, property) === true/false + * + * @param {Object} host object to check property + * @param {string} key to check + */ + function hasKey(object, key) { + return Object.prototype.hasOwnProperty.call(object, key); + } + + function joinRegExp(patterns) { + // Combine an array of regular expressions and strings into one large regexp + // Be mad. + var sources = [], + i = 0, + len = patterns.length, + pattern; + + for (; i < len; i++) { + pattern = patterns[i]; + if (isString(pattern)) { + // If it's a string, we need to escape it + // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions + sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')); + } else if (pattern && pattern.source) { + // If it's a regexp already, we want to extract the source + sources.push(pattern.source); + } + // Intentionally skip other cases + } + return new RegExp(sources.join('|'), 'i'); + } + + function urlencode(o) { + var pairs = []; + each(o, function(key, value) { + pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + }); + return pairs.join('&'); + } + + // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B + // intentionally using regex and not <a/> href parsing trick because React Native and other + // environments where DOM might not be available + function parseUrl(url) { + if (typeof url !== 'string') return {}; + var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/); + + // coerce to undefined values to empty string so we don't get 'undefined' + var query = match[6] || ''; + var fragment = match[8] || ''; + return { + protocol: match[2], + host: match[4], + path: match[5], + relative: match[5] + query + fragment // everything minus origin + }; + } + function uuid4() { + var crypto = _window.crypto || _window.msCrypto; + + if (!isUndefined(crypto) && crypto.getRandomValues) { + // Use window.crypto API if available + // eslint-disable-next-line no-undef + var arr = new Uint16Array(8); + crypto.getRandomValues(arr); + + // set 4 in byte 7 + arr[3] = (arr[3] & 0xfff) | 0x4000; + // set 2 most significant bits of byte 9 to '10' + arr[4] = (arr[4] & 0x3fff) | 0x8000; + + var pad = function(num) { + var v = num.toString(16); + while (v.length < 4) { + v = '0' + v; + } + return v; + }; + + return ( + pad(arr[0]) + + pad(arr[1]) + + pad(arr[2]) + + pad(arr[3]) + + pad(arr[4]) + + pad(arr[5]) + + pad(arr[6]) + + pad(arr[7]) + ); + } else { + // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 + return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (Math.random() * 16) | 0, + v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + } + } + + /** + * Given a child DOM element, returns a query-selector statement describing that + * and its ancestors + * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz] + * @param elem + * @returns {string} + */ + function htmlTreeAsString(elem) { + /* eslint no-extra-parens:0*/ + var MAX_TRAVERSE_HEIGHT = 5, + MAX_OUTPUT_LEN = 80, + out = [], + height = 0, + len = 0, + separator = ' > ', + sepLength = separator.length, + nextStr; + + while (elem && height++ < MAX_TRAVERSE_HEIGHT) { + nextStr = htmlElementAsString(elem); + // bail out if + // - nextStr is the 'html' element + // - the length of the string that would be created exceeds MAX_OUTPUT_LEN + // (ignore this limit if we are on the first iteration) + if ( + nextStr === 'html' || + (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) + ) { + break; + } + + out.push(nextStr); + + len += nextStr.length; + elem = elem.parentNode; + } + + return out.reverse().join(separator); + } + + /** + * Returns a simple, query-selector representation of a DOM element + * e.g. [HTMLElement] => input#foo.btn[name=baz] + * @param HTMLElement + * @returns {string} + */ + function htmlElementAsString(elem) { + var out = [], + className, + classes, + key, + attr, + i; + + if (!elem || !elem.tagName) { + return ''; + } + + out.push(elem.tagName.toLowerCase()); + if (elem.id) { + out.push('#' + elem.id); + } + + className = elem.className; + if (className && isString(className)) { + classes = className.split(/\s+/); + for (i = 0; i < classes.length; i++) { + out.push('.' + classes[i]); + } + } + var attrWhitelist = ['type', 'name', 'title', 'alt']; + for (i = 0; i < attrWhitelist.length; i++) { + key = attrWhitelist[i]; + attr = elem.getAttribute(key); + if (attr) { + out.push('[' + key + '="' + attr + '"]'); + } + } + return out.join(''); + } + + /** + * Returns true if either a OR b is truthy, but not both + */ + function isOnlyOneTruthy(a, b) { + return !!(!!a ^ !!b); + } + + /** + * Returns true if both parameters are undefined + */ + function isBothUndefined(a, b) { + return isUndefined(a) && isUndefined(b); + } + + /** + * Returns true if the two input exception interfaces have the same content + */ + function isSameException(ex1, ex2) { + if (isOnlyOneTruthy(ex1, ex2)) return false; + + ex1 = ex1.values[0]; + ex2 = ex2.values[0]; + + if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; + + // in case both stacktraces are undefined, we can't decide so default to false + if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false; + + return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); + } + + /** + * Returns true if the two input stack trace interfaces have the same content + */ + function isSameStacktrace(stack1, stack2) { + if (isOnlyOneTruthy(stack1, stack2)) return false; + + var frames1 = stack1.frames; + var frames2 = stack2.frames; + + // Exit early if stacktrace is malformed + if (frames1 === undefined || frames2 === undefined) return false; + + // Exit early if frame count differs + if (frames1.length !== frames2.length) return false; + + // Iterate through every frame; bail out if anything differs + var a, b; + for (var i = 0; i < frames1.length; i++) { + a = frames1[i]; + b = frames2[i]; + if ( + a.filename !== b.filename || + a.lineno !== b.lineno || + a.colno !== b.colno || + a['function'] !== b['function'] + ) + return false; + } + return true; + } + + /** + * Polyfill a method + * @param obj object e.g. `document` + * @param name method name present on object e.g. `addEventListener` + * @param replacement replacement function + * @param track {optional} record instrumentation to an array + */ + function fill(obj, name, replacement, track) { + if (obj == null) return; + var orig = obj[name]; + obj[name] = replacement(orig); + obj[name].__raven__ = true; + obj[name].__orig__ = orig; + if (track) { + track.push([obj, name, orig]); + } + } + + /** + * Join values in array + * @param input array of values to be joined together + * @param delimiter string to be placed in-between values + * @returns {string} + */ + function safeJoin(input, delimiter) { + if (!isArray(input)) return ''; + + var output = []; + + for (var i = 0; i < input.length; i++) { + try { + output.push(String(input[i])); + } catch (e) { + output.push('[value cannot be serialized]'); + } + } + + return output.join(delimiter); + } + + // Default Node.js REPL depth + var MAX_SERIALIZE_EXCEPTION_DEPTH = 3; + // 50kB, as 100kB is max payload size, so half sounds reasonable + var MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024; + var MAX_SERIALIZE_KEYS_LENGTH = 40; + + function utf8Length(value) { + return ~-encodeURI(value).split(/%..|./).length; + } + + function jsonSize(value) { + return utf8Length(JSON.stringify(value)); + } + + function serializeValue(value) { + if (typeof value === 'string') { + var maxLength = 40; + return truncate(value, maxLength); + } else if ( + typeof value === 'number' || + typeof value === 'boolean' || + typeof value === 'undefined' + ) { + return value; + } + + var type = Object.prototype.toString.call(value); + + // Node.js REPL notation + if (type === '[object Object]') return '[Object]'; + if (type === '[object Array]') return '[Array]'; + if (type === '[object Function]') + return value.name ? '[Function: ' + value.name + ']' : '[Function]'; + + return value; + } + + function serializeObject(value, depth) { + if (depth === 0) return serializeValue(value); + + if (isPlainObject(value)) { + return Object.keys(value).reduce(function(acc, key) { + acc[key] = serializeObject(value[key], depth - 1); + return acc; + }, {}); + } else if (Array.isArray(value)) { + return value.map(function(val) { + return serializeObject(val, depth - 1); + }); + } + + return serializeValue(value); + } + + function serializeException(ex, depth, maxSize) { + if (!isPlainObject(ex)) return ex; + + depth = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_DEPTH : depth; + maxSize = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_SIZE : maxSize; + + var serialized = serializeObject(ex, depth); + + if (jsonSize(stringify_1(serialized)) > maxSize) { + return serializeException(ex, depth - 1); + } + + return serialized; + } + + function serializeKeysForMessage(keys, maxLength) { + if (typeof keys === 'number' || typeof keys === 'string') return keys.toString(); + if (!Array.isArray(keys)) return ''; + + keys = keys.filter(function(key) { + return typeof key === 'string'; + }); + if (keys.length === 0) return '[object has no keys]'; + + maxLength = typeof maxLength !== 'number' ? MAX_SERIALIZE_KEYS_LENGTH : maxLength; + if (keys[0].length >= maxLength) return keys[0]; + + for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) { + var serialized = keys.slice(0, usedKeys).join(', '); + if (serialized.length > maxLength) continue; + if (usedKeys === keys.length) return serialized; + return serialized + '\u2026'; + } + + return ''; + } + + function sanitize(input, sanitizeKeys) { + if (!isArray(sanitizeKeys) || (isArray(sanitizeKeys) && sanitizeKeys.length === 0)) + return input; + + var sanitizeRegExp = joinRegExp(sanitizeKeys); + var sanitizeMask = '********'; + var safeInput; + + try { + safeInput = JSON.parse(stringify_1(input)); + } catch (o_O) { + return input; + } + + function sanitizeWorker(workerInput) { + if (isArray(workerInput)) { + return workerInput.map(function(val) { + return sanitizeWorker(val); + }); + } + + if (isPlainObject(workerInput)) { + return Object.keys(workerInput).reduce(function(acc, k) { + if (sanitizeRegExp.test(k)) { + acc[k] = sanitizeMask; + } else { + acc[k] = sanitizeWorker(workerInput[k]); + } + return acc; + }, {}); + } + + return workerInput; + } + + return sanitizeWorker(safeInput); + } + + var utils = { + isObject: isObject, + isError: isError, + isErrorEvent: isErrorEvent, + isDOMError: isDOMError, + isDOMException: isDOMException, + isUndefined: isUndefined, + isFunction: isFunction, + isPlainObject: isPlainObject, + isString: isString, + isArray: isArray, + isEmptyObject: isEmptyObject, + supportsErrorEvent: supportsErrorEvent, + supportsDOMError: supportsDOMError, + supportsDOMException: supportsDOMException, + supportsFetch: supportsFetch, + supportsReferrerPolicy: supportsReferrerPolicy, + supportsPromiseRejectionEvent: supportsPromiseRejectionEvent, + wrappedCallback: wrappedCallback, + each: each, + objectMerge: objectMerge, + truncate: truncate, + objectFrozen: objectFrozen, + hasKey: hasKey, + joinRegExp: joinRegExp, + urlencode: urlencode, + uuid4: uuid4, + htmlTreeAsString: htmlTreeAsString, + htmlElementAsString: htmlElementAsString, + isSameException: isSameException, + isSameStacktrace: isSameStacktrace, + parseUrl: parseUrl, + fill: fill, + safeJoin: safeJoin, + serializeException: serializeException, + serializeKeysForMessage: serializeKeysForMessage, + sanitize: sanitize + }; + + /* + TraceKit - Cross brower stack traces + + This was originally forked from github.com/occ/TraceKit, but has since been + largely re-written and is now maintained as part of raven-js. Tests for + this are in test/vendor. + + MIT license + */ + + var TraceKit = { + collectWindowErrors: true, + debug: false + }; + + // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) + var _window$1 = + typeof window !== 'undefined' + ? window + : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; + + // global reference to slice + var _slice = [].slice; + var UNKNOWN_FUNCTION = '?'; + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types + var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/; + + function getLocationHref() { + if (typeof document === 'undefined' || document.location == null) return ''; + return document.location.href; + } + + function getLocationOrigin() { + if (typeof document === 'undefined' || document.location == null) return ''; + + // Oh dear IE10... + if (!document.location.origin) { + return ( + document.location.protocol + + '//' + + document.location.hostname + + (document.location.port ? ':' + document.location.port : '') + ); + } + + return document.location.origin; + } + + /** + * TraceKit.report: cross-browser processing of unhandled exceptions + * + * Syntax: + * TraceKit.report.subscribe(function(stackInfo) { ... }) + * TraceKit.report.unsubscribe(function(stackInfo) { ... }) + * TraceKit.report(exception) + * try { ...code... } catch(ex) { TraceKit.report(ex); } + * + * Supports: + * - Firefox: full stack trace with line numbers, plus column number + * on top frame; column number is not guaranteed + * - Opera: full stack trace with line and column numbers + * - Chrome: full stack trace with line and column numbers + * - Safari: line and column number for the top frame only; some frames + * may be missing, and column number is not guaranteed + * - IE: line and column number for the top frame only; some frames + * may be missing, and column number is not guaranteed + * + * In theory, TraceKit should work on all of the following versions: + * - IE5.5+ (only 8.0 tested) + * - Firefox 0.9+ (only 3.5+ tested) + * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require + * Exceptions Have Stacktrace to be enabled in opera:config) + * - Safari 3+ (only 4+ tested) + * - Chrome 1+ (only 5+ tested) + * - Konqueror 3.5+ (untested) + * + * Requires TraceKit.computeStackTrace. + * + * Tries to catch all unhandled exceptions and report them to the + * subscribed handlers. Please note that TraceKit.report will rethrow the + * exception. This is REQUIRED in order to get a useful stack trace in IE. + * If the exception does not reach the top of the browser, you will only + * get a stack trace from the point where TraceKit.report was called. + * + * Handlers receive a stackInfo object as described in the + * TraceKit.computeStackTrace docs. + */ + TraceKit.report = (function reportModuleWrapper() { + var handlers = [], + lastArgs = null, + lastException = null, + lastExceptionStack = null; + + /** + * Add a crash handler. + * @param {Function} handler + */ + function subscribe(handler) { + installGlobalHandler(); + handlers.push(handler); + } + + /** + * Remove a crash handler. + * @param {Function} handler + */ + function unsubscribe(handler) { + for (var i = handlers.length - 1; i >= 0; --i) { + if (handlers[i] === handler) { + handlers.splice(i, 1); + } + } + } + + /** + * Remove all crash handlers. + */ + function unsubscribeAll() { + uninstallGlobalHandler(); + handlers = []; + } + + /** + * Dispatch stack information to all handlers. + * @param {Object.<string, *>} stack + */ + function notifyHandlers(stack, isWindowError) { + var exception = null; + if (isWindowError && !TraceKit.collectWindowErrors) { + return; + } + for (var i in handlers) { + if (handlers.hasOwnProperty(i)) { + try { + handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2))); + } catch (inner) { + exception = inner; + } + } + } + + if (exception) { + throw exception; + } + } + + var _oldOnerrorHandler, _onErrorHandlerInstalled; + + /** + * Ensures all global unhandled exceptions are recorded. + * Supported by Gecko and IE. + * @param {string} msg Error message. + * @param {string} url URL of script that generated the exception. + * @param {(number|string)} lineNo The line number at which the error + * occurred. + * @param {?(number|string)} colNo The column number at which the error + * occurred. + * @param {?Error} ex The actual Error object. + */ + function traceKitWindowOnError(msg, url, lineNo, colNo, ex) { + var stack = null; + // If 'ex' is ErrorEvent, get real Error from inside + var exception = utils.isErrorEvent(ex) ? ex.error : ex; + // If 'msg' is ErrorEvent, get real message from inside + var message = utils.isErrorEvent(msg) ? msg.message : msg; + + if (lastExceptionStack) { + TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( + lastExceptionStack, + url, + lineNo, + message + ); + processLastException(); + } else if (exception && utils.isError(exception)) { + // non-string `exception` arg; attempt to extract stack trace + + // New chrome and blink send along a real error object + // Let's just report that like a normal error. + // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror + stack = TraceKit.computeStackTrace(exception); + notifyHandlers(stack, true); + } else { + var location = { + url: url, + line: lineNo, + column: colNo + }; + + var name = undefined; + var groups; + + if ({}.toString.call(message) === '[object String]') { + var groups = message.match(ERROR_TYPES_RE); + if (groups) { + name = groups[1]; + message = groups[2]; + } + } + + location.func = UNKNOWN_FUNCTION; + + stack = { + name: name, + message: message, + url: getLocationHref(), + stack: [location] + }; + notifyHandlers(stack, true); + } + + if (_oldOnerrorHandler) { + return _oldOnerrorHandler.apply(this, arguments); + } + + return false; + } + + function installGlobalHandler() { + if (_onErrorHandlerInstalled) { + return; + } + _oldOnerrorHandler = _window$1.onerror; + _window$1.onerror = traceKitWindowOnError; + _onErrorHandlerInstalled = true; + } + + function uninstallGlobalHandler() { + if (!_onErrorHandlerInstalled) { + return; + } + _window$1.onerror = _oldOnerrorHandler; + _onErrorHandlerInstalled = false; + _oldOnerrorHandler = undefined; + } + + function processLastException() { + var _lastExceptionStack = lastExceptionStack, + _lastArgs = lastArgs; + lastArgs = null; + lastExceptionStack = null; + lastException = null; + notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs)); + } + + /** + * Reports an unhandled Error to TraceKit. + * @param {Error} ex + * @param {?boolean} rethrow If false, do not re-throw the exception. + * Only used for window.onerror to not cause an infinite loop of + * rethrowing. + */ + function report(ex, rethrow) { + var args = _slice.call(arguments, 1); + if (lastExceptionStack) { + if (lastException === ex) { + return; // already caught by an inner catch block, ignore + } else { + processLastException(); + } + } + + var stack = TraceKit.computeStackTrace(ex); + lastExceptionStack = stack; + lastException = ex; + lastArgs = args; + + // If the stack trace is incomplete, wait for 2 seconds for + // slow slow IE to see if onerror occurs or not before reporting + // this exception; otherwise, we will end up with an incomplete + // stack trace + setTimeout(function() { + if (lastException === ex) { + processLastException(); + } + }, stack.incomplete ? 2000 : 0); + + if (rethrow !== false) { + throw ex; // re-throw to propagate to the top level (and cause window.onerror) + } + } + + report.subscribe = subscribe; + report.unsubscribe = unsubscribe; + report.uninstall = unsubscribeAll; + return report; + })(); + + /** + * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript + * + * Syntax: + * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below) + * Returns: + * s.name - exception name + * s.message - exception message + * s.stack[i].url - JavaScript or HTML file URL + * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work) + * s.stack[i].args - arguments passed to the function, if known + * s.stack[i].line - line number, if known + * s.stack[i].column - column number, if known + * + * Supports: + * - Firefox: full stack trace with line numbers and unreliable column + * number on top frame + * - Opera 10: full stack trace with line and column numbers + * - Opera 9-: full stack trace with line numbers + * - Chrome: full stack trace with line and column numbers + * - Safari: line and column number for the topmost stacktrace element + * only + * - IE: no line numbers whatsoever + * + * Tries to guess names of anonymous functions by looking for assignments + * in the source code. In IE and Safari, we have to guess source file names + * by searching for function bodies inside all page scripts. This will not + * work for scripts that are loaded cross-domain. + * Here be dragons: some function names may be guessed incorrectly, and + * duplicate functions may be mismatched. + * + * TraceKit.computeStackTrace should only be used for tracing purposes. + * Logging of unhandled exceptions should be done with TraceKit.report, + * which builds on top of TraceKit.computeStackTrace and provides better + * IE support by utilizing the window.onerror event to retrieve information + * about the top of the stack. + * + * Note: In IE and Safari, no stack trace is recorded on the Error object, + * so computeStackTrace instead walks its *own* chain of callers. + * This means that: + * * in Safari, some methods may be missing from the stack trace; + * * in IE, the topmost function in the stack trace will always be the + * caller of computeStackTrace. + * + * This is okay for tracing (because you are likely to be calling + * computeStackTrace from the function you want to be the topmost element + * of the stack trace anyway), but not okay for logging unhandled + * exceptions (because your catch block will likely be far away from the + * inner function that actually caused the exception). + * + */ + TraceKit.computeStackTrace = (function computeStackTraceWrapper() { + // Contents of Exception in various browsers. + // + // SAFARI: + // ex.message = Can't find variable: qq + // ex.line = 59 + // ex.sourceId = 580238192 + // ex.sourceURL = http://... + // ex.expressionBeginOffset = 96 + // ex.expressionCaretOffset = 98 + // ex.expressionEndOffset = 98 + // ex.name = ReferenceError + // + // FIREFOX: + // ex.message = qq is not defined + // ex.fileName = http://... + // ex.lineNumber = 59 + // ex.columnNumber = 69 + // ex.stack = ...stack trace... (see the example below) + // ex.name = ReferenceError + // + // CHROME: + // ex.message = qq is not defined + // ex.name = ReferenceError + // ex.type = not_defined + // ex.arguments = ['aa'] + // ex.stack = ...stack trace... + // + // INTERNET EXPLORER: + // ex.message = ... + // ex.name = ReferenceError + // + // OPERA: + // ex.message = ...message... (see the example below) + // ex.name = ReferenceError + // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message) + // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace' + + /** + * Computes stack trace information from the stack property. + * Chrome and Gecko use this property. + * @param {Error} ex + * @return {?Object.<string, *>} Stack trace information. + */ + function computeStackTraceFromStackProp(ex) { + if (typeof ex.stack === 'undefined' || !ex.stack) return; + + var chrome = /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; + var winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; + // NOTE: blob urls are now supposed to always have an origin, therefore it's format + // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well + var gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; + // Used to additionally parse URL/line/column from eval frames + var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i; + var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/; + var lines = ex.stack.split('\n'); + var stack = []; + var submatch; + var parts; + var element; + var reference = /^(.*) is undefined$/.exec(ex.message); + + for (var i = 0, j = lines.length; i < j; ++i) { + if ((parts = chrome.exec(lines[i]))) { + var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line + var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line + if (isEval && (submatch = chromeEval.exec(parts[2]))) { + // throw out eval line/column and use top-most line/column number + parts[2] = submatch[1]; // url + parts[3] = submatch[2]; // line + parts[4] = submatch[3]; // column + } + element = { + url: !isNative ? parts[2] : null, + func: parts[1] || UNKNOWN_FUNCTION, + args: isNative ? [parts[2]] : [], + line: parts[3] ? +parts[3] : null, + column: parts[4] ? +parts[4] : null + }; + } else if ((parts = winjs.exec(lines[i]))) { + element = { + url: parts[2], + func: parts[1] || UNKNOWN_FUNCTION, + args: [], + line: +parts[3], + column: parts[4] ? +parts[4] : null + }; + } else if ((parts = gecko.exec(lines[i]))) { + var isEval = parts[3] && parts[3].indexOf(' > eval') > -1; + if (isEval && (submatch = geckoEval.exec(parts[3]))) { + // throw out eval line/column and use top-most line number + parts[3] = submatch[1]; + parts[4] = submatch[2]; + parts[5] = null; // no column when eval + } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') { + // FireFox uses this awesome columnNumber property for its top frame + // Also note, Firefox's column number is 0-based and everything else expects 1-based, + // so adding 1 + // NOTE: this hack doesn't work if top-most frame is eval + stack[0].column = ex.columnNumber + 1; + } + element = { + url: parts[3], + func: parts[1] || UNKNOWN_FUNCTION, + args: parts[2] ? parts[2].split(',') : [], + line: parts[4] ? +parts[4] : null, + column: parts[5] ? +parts[5] : null + }; + } else { + continue; + } + + if (!element.func && element.line) { + element.func = UNKNOWN_FUNCTION; + } + + if (element.url && element.url.substr(0, 5) === 'blob:') { + // Special case for handling JavaScript loaded into a blob. + // We use a synchronous AJAX request here as a blob is already in + // memory - it's not making a network request. This will generate a warning + // in the browser console, but there has already been an error so that's not + // that much of an issue. + var xhr = new XMLHttpRequest(); + xhr.open('GET', element.url, false); + xhr.send(null); + + // If we failed to download the source, skip this patch + if (xhr.status === 200) { + var source = xhr.responseText || ''; + + // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file. + // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175 + source = source.slice(-300); + + // Now we dig out the source map URL + var sourceMaps = source.match(/\/\/# sourceMappingURL=(.*)$/); + + // If we don't find a source map comment or we find more than one, continue on to the next element. + if (sourceMaps) { + var sourceMapAddress = sourceMaps[1]; + + // Now we check to see if it's a relative URL. + // If it is, convert it to an absolute one. + if (sourceMapAddress.charAt(0) === '~') { + sourceMapAddress = getLocationOrigin() + sourceMapAddress.slice(1); + } + + // Now we strip the '.map' off of the end of the URL and update the + // element so that Sentry can match the map to the blob. + element.url = sourceMapAddress.slice(0, -4); + } + } + } + + stack.push(element); + } + + if (!stack.length) { + return null; + } + + return { + name: ex.name, + message: ex.message, + url: getLocationHref(), + stack: stack + }; + } + + /** + * Adds information about the first frame to incomplete stack traces. + * Safari and IE require this to get complete data on the first frame. + * @param {Object.<string, *>} stackInfo Stack trace information from + * one of the compute* methods. + * @param {string} url The URL of the script that caused an error. + * @param {(number|string)} lineNo The line number of the script that + * caused an error. + * @param {string=} message The error generated by the browser, which + * hopefully contains the name of the object that caused the error. + * @return {boolean} Whether or not the stack information was + * augmented. + */ + function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) { + var initial = { + url: url, + line: lineNo + }; + + if (initial.url && initial.line) { + stackInfo.incomplete = false; + + if (!initial.func) { + initial.func = UNKNOWN_FUNCTION; + } + + if (stackInfo.stack.length > 0) { + if (stackInfo.stack[0].url === initial.url) { + if (stackInfo.stack[0].line === initial.line) { + return false; // already in stack trace + } else if ( + !stackInfo.stack[0].line && + stackInfo.stack[0].func === initial.func + ) { + stackInfo.stack[0].line = initial.line; + return false; + } + } + } + + stackInfo.stack.unshift(initial); + stackInfo.partial = true; + return true; + } else { + stackInfo.incomplete = true; + } + + return false; + } + + /** + * Computes stack trace information by walking the arguments.caller + * chain at the time the exception occurred. This will cause earlier + * frames to be missed but is the only way to get any stack trace in + * Safari and IE. The top frame is restored by + * {@link augmentStackTraceWithInitialElement}. + * @param {Error} ex + * @return {?Object.<string, *>} Stack trace information. + */ + function computeStackTraceByWalkingCallerChain(ex, depth) { + var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i, + stack = [], + funcs = {}, + recursion = false, + parts, + item; + + for ( + var curr = computeStackTraceByWalkingCallerChain.caller; + curr && !recursion; + curr = curr.caller + ) { + if (curr === computeStackTrace || curr === TraceKit.report) { + // console.log('skipping internal function'); + continue; + } + + item = { + url: null, + func: UNKNOWN_FUNCTION, + line: null, + column: null + }; + + if (curr.name) { + item.func = curr.name; + } else if ((parts = functionName.exec(curr.toString()))) { + item.func = parts[1]; + } + + if (typeof item.func === 'undefined') { + try { + item.func = parts.input.substring(0, parts.input.indexOf('{')); + } catch (e) {} + } + + if (funcs['' + curr]) { + recursion = true; + } else { + funcs['' + curr] = true; + } + + stack.push(item); + } + + if (depth) { + // console.log('depth is ' + depth); + // console.log('stack is ' + stack.length); + stack.splice(0, depth); + } + + var result = { + name: ex.name, + message: ex.message, + url: getLocationHref(), + stack: stack + }; + augmentStackTraceWithInitialElement( + result, + ex.sourceURL || ex.fileName, + ex.line || ex.lineNumber, + ex.message || ex.description + ); + return result; + } + + /** + * Computes a stack trace for an exception. + * @param {Error} ex + * @param {(string|number)=} depth + */ + function computeStackTrace(ex, depth) { + var stack = null; + depth = depth == null ? 0 : +depth; + + try { + stack = computeStackTraceFromStackProp(ex); + if (stack) { + return stack; + } + } catch (e) { + if (TraceKit.debug) { + throw e; + } + } + + try { + stack = computeStackTraceByWalkingCallerChain(ex, depth + 1); + if (stack) { + return stack; + } + } catch (e) { + if (TraceKit.debug) { + throw e; + } + } + return { + name: ex.name, + message: ex.message, + url: getLocationHref() + }; + } + + computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; + computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp; + + return computeStackTrace; + })(); + + var tracekit = TraceKit; + + /* + * JavaScript MD5 + * https://github.com/blueimp/JavaScript-MD5 + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * https://opensource.org/licenses/MIT + * + * Based on + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + + /* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + function safeAdd(x, y) { + var lsw = (x & 0xffff) + (y & 0xffff); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xffff); + } + + /* + * Bitwise rotate a 32-bit number to the left. + */ + function bitRotateLeft(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /* + * These functions implement the four basic operations the algorithm uses. + */ + function md5cmn(q, a, b, x, s, t) { + return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); + } + function md5ff(a, b, c, d, x, s, t) { + return md5cmn((b & c) | (~b & d), a, b, x, s, t); + } + function md5gg(a, b, c, d, x, s, t) { + return md5cmn((b & d) | (c & ~d), a, b, x, s, t); + } + function md5hh(a, b, c, d, x, s, t) { + return md5cmn(b ^ c ^ d, a, b, x, s, t); + } + function md5ii(a, b, c, d, x, s, t) { + return md5cmn(c ^ (b | ~d), a, b, x, s, t); + } + + /* + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + function binlMD5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << (len % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var i; + var olda; + var oldb; + var oldc; + var oldd; + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5ff(a, b, c, d, x[i], 7, -680876936); + d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5gg(b, c, d, a, x[i], 20, -373897302); + a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5hh(d, a, b, c, x[i], 11, -358537222); + c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5ii(a, b, c, d, x[i], 6, -198630844); + d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safeAdd(a, olda); + b = safeAdd(b, oldb); + c = safeAdd(c, oldc); + d = safeAdd(d, oldd); + } + return [a, b, c, d]; + } + + /* + * Convert an array of little-endian words to a string + */ + function binl2rstr(input) { + var i; + var output = ''; + var length32 = input.length * 32; + for (i = 0; i < length32; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff); + } + return output; + } + + /* + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + function rstr2binl(input) { + var i; + var output = []; + output[(input.length >> 2) - 1] = undefined; + for (i = 0; i < output.length; i += 1) { + output[i] = 0; + } + var length8 = input.length * 8; + for (i = 0; i < length8; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32); + } + return output; + } + + /* + * Calculate the MD5 of a raw string + */ + function rstrMD5(s) { + return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)); + } + + /* + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + function rstrHMACMD5(key, data) { + var i; + var bkey = rstr2binl(key); + var ipad = []; + var opad = []; + var hash; + ipad[15] = opad[15] = undefined; + if (bkey.length > 16) { + bkey = binlMD5(bkey, key.length * 8); + } + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5c5c5c5c; + } + hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)); + } + + /* + * Convert a raw string to a hex string + */ + function rstr2hex(input) { + var hexTab = '0123456789abcdef'; + var output = ''; + var x; + var i; + for (i = 0; i < input.length; i += 1) { + x = input.charCodeAt(i); + output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f); + } + return output; + } + + /* + * Encode a string as utf-8 + */ + function str2rstrUTF8(input) { + return unescape(encodeURIComponent(input)); + } + + /* + * Take string arguments and return either raw or hex encoded strings + */ + function rawMD5(s) { + return rstrMD5(str2rstrUTF8(s)); + } + function hexMD5(s) { + return rstr2hex(rawMD5(s)); + } + function rawHMACMD5(k, d) { + return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)); + } + function hexHMACMD5(k, d) { + return rstr2hex(rawHMACMD5(k, d)); + } + + function md5(string, key, raw) { + if (!key) { + if (!raw) { + return hexMD5(string); + } + return rawMD5(string); + } + if (!raw) { + return hexHMACMD5(key, string); + } + return rawHMACMD5(key, string); + } + + var md5_1 = md5; + + function RavenConfigError(message) { + this.name = 'RavenConfigError'; + this.message = message; + } + RavenConfigError.prototype = new Error(); + RavenConfigError.prototype.constructor = RavenConfigError; + + var configError = RavenConfigError; + + var wrapMethod = function(console, level, callback) { + var originalConsoleLevel = console[level]; + var originalConsole = console; + + if (!(level in console)) { + return; + } + + var sentryLevel = level === 'warn' ? 'warning' : level; + + console[level] = function() { + var args = [].slice.call(arguments); + + var msg = utils.safeJoin(args, ' '); + var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}}; + + if (level === 'assert') { + if (args[0] === false) { + // Default browsers message + msg = + 'Assertion failed: ' + (utils.safeJoin(args.slice(1), ' ') || 'console.assert'); + data.extra.arguments = args.slice(1); + callback && callback(msg, data); + } + } else { + callback && callback(msg, data); + } + + // this fails for some browsers. :( + if (originalConsoleLevel) { + // IE9 doesn't allow calling apply on console functions directly + // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193 + Function.prototype.apply.call(originalConsoleLevel, originalConsole, args); + } + }; + }; + + var console$1 = { + wrapMethod: wrapMethod + }; + + /*global XDomainRequest:false */ + + + + + + + + var isErrorEvent$1 = utils.isErrorEvent; + var isDOMError$1 = utils.isDOMError; + var isDOMException$1 = utils.isDOMException; + var isError$1 = utils.isError; + var isObject$1 = utils.isObject; + var isPlainObject$1 = utils.isPlainObject; + var isUndefined$1 = utils.isUndefined; + var isFunction$1 = utils.isFunction; + var isString$1 = utils.isString; + var isArray$1 = utils.isArray; + var isEmptyObject$1 = utils.isEmptyObject; + var each$1 = utils.each; + var objectMerge$1 = utils.objectMerge; + var truncate$1 = utils.truncate; + var objectFrozen$1 = utils.objectFrozen; + var hasKey$1 = utils.hasKey; + var joinRegExp$1 = utils.joinRegExp; + var urlencode$1 = utils.urlencode; + var uuid4$1 = utils.uuid4; + var htmlTreeAsString$1 = utils.htmlTreeAsString; + var isSameException$1 = utils.isSameException; + var isSameStacktrace$1 = utils.isSameStacktrace; + var parseUrl$1 = utils.parseUrl; + var fill$1 = utils.fill; + var supportsFetch$1 = utils.supportsFetch; + var supportsReferrerPolicy$1 = utils.supportsReferrerPolicy; + var serializeKeysForMessage$1 = utils.serializeKeysForMessage; + var serializeException$1 = utils.serializeException; + var sanitize$1 = utils.sanitize; + + var wrapConsoleMethod = console$1.wrapMethod; + + var dsnKeys = 'source protocol user pass host port path'.split(' '), + dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/; + + function now() { + return +new Date(); + } + + // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) + var _window$2 = + typeof window !== 'undefined' + ? window + : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; + var _document = _window$2.document; + var _navigator = _window$2.navigator; + + function keepOriginalCallback(original, callback) { + return isFunction$1(callback) + ? function(data) { + return callback(data, original); + } + : callback; + } + + // First, check for JSON support + // If there is no JSON, we no-op the core features of Raven + // since JSON is required to encode the payload + function Raven() { + this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify); + // Raven can run in contexts where there's no document (react-native) + this._hasDocument = !isUndefined$1(_document); + this._hasNavigator = !isUndefined$1(_navigator); + this._lastCapturedException = null; + this._lastData = null; + this._lastEventId = null; + this._globalServer = null; + this._globalKey = null; + this._globalProject = null; + this._globalContext = {}; + this._globalOptions = { + // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin + release: _window$2.SENTRY_RELEASE && _window$2.SENTRY_RELEASE.id, + logger: 'javascript', + ignoreErrors: [], + ignoreUrls: [], + whitelistUrls: [], + includePaths: [], + headers: null, + collectWindowErrors: true, + captureUnhandledRejections: true, + maxMessageLength: 0, + // By default, truncates URL values to 250 chars + maxUrlLength: 250, + stackTraceLimit: 50, + autoBreadcrumbs: true, + instrument: true, + sampleRate: 1, + sanitizeKeys: [] + }; + this._fetchDefaults = { + method: 'POST', + // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default + // https://caniuse.com/#feat=referrer-policy + // It doesn't. And it throw exception instead of ignoring this parameter... + // REF: https://github.com/getsentry/raven-js/issues/1233 + referrerPolicy: supportsReferrerPolicy$1() ? 'origin' : '' + }; + this._ignoreOnError = 0; + this._isRavenInstalled = false; + this._originalErrorStackTraceLimit = Error.stackTraceLimit; + // capture references to window.console *and* all its methods first + // before the console plugin has a chance to monkey patch + this._originalConsole = _window$2.console || {}; + this._originalConsoleMethods = {}; + this._plugins = []; + this._startTime = now(); + this._wrappedBuiltIns = []; + this._breadcrumbs = []; + this._lastCapturedEvent = null; + this._keypressTimeout; + this._location = _window$2.location; + this._lastHref = this._location && this._location.href; + this._resetBackoff(); + + // eslint-disable-next-line guard-for-in + for (var method in this._originalConsole) { + this._originalConsoleMethods[method] = this._originalConsole[method]; + } + } + + /* + * The core Raven singleton + * + * @this {Raven} + */ + + Raven.prototype = { + // Hardcode version string so that raven source can be loaded directly via + // webpack (using a build step causes webpack #1617). Grunt verifies that + // this value matches package.json during build. + // See: https://github.com/getsentry/raven-js/issues/465 + VERSION: '3.27.0', + + debug: false, + + TraceKit: tracekit, // alias to TraceKit + + /* + * Configure Raven with a DSN and extra options + * + * @param {string} dsn The public Sentry DSN + * @param {object} options Set of global options [optional] + * @return {Raven} + */ + config: function(dsn, options) { + var self = this; + + if (self._globalServer) { + this._logDebug('error', 'Error: Raven has already been configured'); + return self; + } + if (!dsn) return self; + + var globalOptions = self._globalOptions; + + // merge in options + if (options) { + each$1(options, function(key, value) { + // tags and extra are special and need to be put into context + if (key === 'tags' || key === 'extra' || key === 'user') { + self._globalContext[key] = value; + } else { + globalOptions[key] = value; + } + }); + } + + self.setDSN(dsn); + + // "Script error." is hard coded into browsers for errors that it can't read. + // this is the result of a script being pulled in from an external domain and CORS. + globalOptions.ignoreErrors.push(/^Script error\.?$/); + globalOptions.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/); + + // join regexp rules into one big rule + globalOptions.ignoreErrors = joinRegExp$1(globalOptions.ignoreErrors); + globalOptions.ignoreUrls = globalOptions.ignoreUrls.length + ? joinRegExp$1(globalOptions.ignoreUrls) + : false; + globalOptions.whitelistUrls = globalOptions.whitelistUrls.length + ? joinRegExp$1(globalOptions.whitelistUrls) + : false; + globalOptions.includePaths = joinRegExp$1(globalOptions.includePaths); + globalOptions.maxBreadcrumbs = Math.max( + 0, + Math.min(globalOptions.maxBreadcrumbs || 100, 100) + ); // default and hard limit is 100 + + var autoBreadcrumbDefaults = { + xhr: true, + console: true, + dom: true, + location: true, + sentry: true + }; + + var autoBreadcrumbs = globalOptions.autoBreadcrumbs; + if ({}.toString.call(autoBreadcrumbs) === '[object Object]') { + autoBreadcrumbs = objectMerge$1(autoBreadcrumbDefaults, autoBreadcrumbs); + } else if (autoBreadcrumbs !== false) { + autoBreadcrumbs = autoBreadcrumbDefaults; + } + globalOptions.autoBreadcrumbs = autoBreadcrumbs; + + var instrumentDefaults = { + tryCatch: true + }; + + var instrument = globalOptions.instrument; + if ({}.toString.call(instrument) === '[object Object]') { + instrument = objectMerge$1(instrumentDefaults, instrument); + } else if (instrument !== false) { + instrument = instrumentDefaults; + } + globalOptions.instrument = instrument; + + tracekit.collectWindowErrors = !!globalOptions.collectWindowErrors; + + // return for chaining + return self; + }, + + /* + * Installs a global window.onerror error handler + * to capture and report uncaught exceptions. + * At this point, install() is required to be called due + * to the way TraceKit is set up. + * + * @return {Raven} + */ + install: function() { + var self = this; + if (self.isSetup() && !self._isRavenInstalled) { + tracekit.report.subscribe(function() { + self._handleOnErrorStackInfo.apply(self, arguments); + }); + + if (self._globalOptions.captureUnhandledRejections) { + self._attachPromiseRejectionHandler(); + } + + self._patchFunctionToString(); + + if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) { + self._instrumentTryCatch(); + } + + if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs(); + + // Install all of the plugins + self._drainPlugins(); + + self._isRavenInstalled = true; + } + + Error.stackTraceLimit = self._globalOptions.stackTraceLimit; + return this; + }, + + /* + * Set the DSN (can be called multiple time unlike config) + * + * @param {string} dsn The public Sentry DSN + */ + setDSN: function(dsn) { + var self = this, + uri = self._parseDSN(dsn), + lastSlash = uri.path.lastIndexOf('/'), + path = uri.path.substr(1, lastSlash); + + self._dsn = dsn; + self._globalKey = uri.user; + self._globalSecret = uri.pass && uri.pass.substr(1); + self._globalProject = uri.path.substr(lastSlash + 1); + + self._globalServer = self._getGlobalServer(uri); + + self._globalEndpoint = + self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/'; + + // Reset backoff state since we may be pointing at a + // new project/server + this._resetBackoff(); + }, + + /* + * Wrap code within a context so Raven can capture errors + * reliably across domains that is executed immediately. + * + * @param {object} options A specific set of options for this context [optional] + * @param {function} func The callback to be immediately executed within the context + * @param {array} args An array of arguments to be called with the callback [optional] + */ + context: function(options, func, args) { + if (isFunction$1(options)) { + args = func || []; + func = options; + options = {}; + } + + return this.wrap(options, func).apply(this, args); + }, + + /* + * Wrap code within a context and returns back a new function to be executed + * + * @param {object} options A specific set of options for this context [optional] + * @param {function} func The function to be wrapped in a new context + * @param {function} _before A function to call before the try/catch wrapper [optional, private] + * @return {function} The newly wrapped functions with a context + */ + wrap: function(options, func, _before) { + var self = this; + // 1 argument has been passed, and it's not a function + // so just return it + if (isUndefined$1(func) && !isFunction$1(options)) { + return options; + } + + // options is optional + if (isFunction$1(options)) { + func = options; + options = undefined; + } + + // At this point, we've passed along 2 arguments, and the second one + // is not a function either, so we'll just return the second argument. + if (!isFunction$1(func)) { + return func; + } + + // We don't wanna wrap it twice! + try { + if (func.__raven__) { + return func; + } + + // If this has already been wrapped in the past, return that + if (func.__raven_wrapper__) { + return func.__raven_wrapper__; + } + } catch (e) { + // Just accessing custom props in some Selenium environments + // can cause a "Permission denied" exception (see raven-js#495). + // Bail on wrapping and return the function as-is (defers to window.onerror). + return func; + } + + function wrapped() { + var args = [], + i = arguments.length, + deep = !options || (options && options.deep !== false); + + if (_before && isFunction$1(_before)) { + _before.apply(this, arguments); + } + + // Recursively wrap all of a function's arguments that are + // functions themselves. + while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i]; + + try { + // Attempt to invoke user-land function + // NOTE: If you are a Sentry user, and you are seeing this stack frame, it + // means Raven caught an error invoking your application code. This is + // expected behavior and NOT indicative of a bug with Raven.js. + return func.apply(this, args); + } catch (e) { + self._ignoreNextOnError(); + self.captureException(e, options); + throw e; + } + } + + // copy over properties of the old function + for (var property in func) { + if (hasKey$1(func, property)) { + wrapped[property] = func[property]; + } + } + wrapped.prototype = func.prototype; + + func.__raven_wrapper__ = wrapped; + // Signal that this function has been wrapped/filled already + // for both debugging and to prevent it to being wrapped/filled twice + wrapped.__raven__ = true; + wrapped.__orig__ = func; + + return wrapped; + }, + + /** + * Uninstalls the global error handler. + * + * @return {Raven} + */ + uninstall: function() { + tracekit.report.uninstall(); + + this._detachPromiseRejectionHandler(); + this._unpatchFunctionToString(); + this._restoreBuiltIns(); + this._restoreConsole(); + + Error.stackTraceLimit = this._originalErrorStackTraceLimit; + this._isRavenInstalled = false; + + return this; + }, + + /** + * Callback used for `unhandledrejection` event + * + * @param {PromiseRejectionEvent} event An object containing + * promise: the Promise that was rejected + * reason: the value with which the Promise was rejected + * @return void + */ + _promiseRejectionHandler: function(event) { + this._logDebug('debug', 'Raven caught unhandled promise rejection:', event); + this.captureException(event.reason, { + mechanism: { + type: 'onunhandledrejection', + handled: false + } + }); + }, + + /** + * Installs the global promise rejection handler. + * + * @return {raven} + */ + _attachPromiseRejectionHandler: function() { + this._promiseRejectionHandler = this._promiseRejectionHandler.bind(this); + _window$2.addEventListener && + _window$2.addEventListener('unhandledrejection', this._promiseRejectionHandler); + return this; + }, + + /** + * Uninstalls the global promise rejection handler. + * + * @return {raven} + */ + _detachPromiseRejectionHandler: function() { + _window$2.removeEventListener && + _window$2.removeEventListener('unhandledrejection', this._promiseRejectionHandler); + return this; + }, + + /** + * Manually capture an exception and send it over to Sentry + * + * @param {error} ex An exception to be logged + * @param {object} options A specific set of options for this error [optional] + * @return {Raven} + */ + captureException: function(ex, options) { + options = objectMerge$1({trimHeadFrames: 0}, options ? options : {}); + + if (isErrorEvent$1(ex) && ex.error) { + // If it is an ErrorEvent with `error` property, extract it to get actual Error + ex = ex.error; + } else if (isDOMError$1(ex) || isDOMException$1(ex)) { + // If it is a DOMError or DOMException (which are legacy APIs, but still supported in some browsers) + // then we just extract the name and message, as they don't provide anything else + // https://developer.mozilla.org/en-US/docs/Web/API/DOMError + // https://developer.mozilla.org/en-US/docs/Web/API/DOMException + var name = ex.name || (isDOMError$1(ex) ? 'DOMError' : 'DOMException'); + var message = ex.message ? name + ': ' + ex.message : name; + + return this.captureMessage( + message, + objectMerge$1(options, { + // neither DOMError or DOMException provide stack trace and we most likely wont get it this way as well + // but it's barely any overhead so we may at least try + stacktrace: true, + trimHeadFrames: options.trimHeadFrames + 1 + }) + ); + } else if (isError$1(ex)) { + // we have a real Error object + ex = ex; + } else if (isPlainObject$1(ex)) { + // If it is plain Object, serialize it manually and extract options + // This will allow us to group events based on top-level keys + // which is much better than creating new group when any key/value change + options = this._getCaptureExceptionOptionsFromPlainObject(options, ex); + ex = new Error(options.message); + } else { + // If none of previous checks were valid, then it means that + // it's not a DOMError/DOMException + // it's not a plain Object + // it's not a valid ErrorEvent (one with an error property) + // it's not an Error + // So bail out and capture it as a simple message: + return this.captureMessage( + ex, + objectMerge$1(options, { + stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace + trimHeadFrames: options.trimHeadFrames + 1 + }) + ); + } + + // Store the raw exception object for potential debugging and introspection + this._lastCapturedException = ex; + + // TraceKit.report will re-raise any exception passed to it, + // which means you have to wrap it in try/catch. Instead, we + // can wrap it here and only re-raise if TraceKit.report + // raises an exception different from the one we asked to + // report on. + try { + var stack = tracekit.computeStackTrace(ex); + this._handleStackInfo(stack, options); + } catch (ex1) { + if (ex !== ex1) { + throw ex1; + } + } + + return this; + }, + + _getCaptureExceptionOptionsFromPlainObject: function(currentOptions, ex) { + var exKeys = Object.keys(ex).sort(); + var options = objectMerge$1(currentOptions, { + message: + 'Non-Error exception captured with keys: ' + serializeKeysForMessage$1(exKeys), + fingerprint: [md5_1(exKeys)], + extra: currentOptions.extra || {} + }); + options.extra.__serialized__ = serializeException$1(ex); + + return options; + }, + + /* + * Manually send a message to Sentry + * + * @param {string} msg A plain message to be captured in Sentry + * @param {object} options A specific set of options for this message [optional] + * @return {Raven} + */ + captureMessage: function(msg, options) { + // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an + // early call; we'll error on the side of logging anything called before configuration since it's + // probably something you should see: + if ( + !!this._globalOptions.ignoreErrors.test && + this._globalOptions.ignoreErrors.test(msg) + ) { + return; + } + + options = options || {}; + msg = msg + ''; // Make sure it's actually a string + + var data = objectMerge$1( + { + message: msg + }, + options + ); + + var ex; + // Generate a "synthetic" stack trace from this point. + // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative + // of a bug with Raven.js. Sentry generates synthetic traces either by configuration, + // or if it catches a thrown object without a "stack" property. + try { + throw new Error(msg); + } catch (ex1) { + ex = ex1; + } + + // null exception name so `Error` isn't prefixed to msg + ex.name = null; + var stack = tracekit.computeStackTrace(ex); + + // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1] + var initialCall = isArray$1(stack.stack) && stack.stack[1]; + + // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call + // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd + // initialCall => captureException(string) => captureMessage(string) + if (initialCall && initialCall.func === 'Raven.captureException') { + initialCall = stack.stack[2]; + } + + var fileurl = (initialCall && initialCall.url) || ''; + + if ( + !!this._globalOptions.ignoreUrls.test && + this._globalOptions.ignoreUrls.test(fileurl) + ) { + return; + } + + if ( + !!this._globalOptions.whitelistUrls.test && + !this._globalOptions.whitelistUrls.test(fileurl) + ) { + return; + } + + // Always attempt to get stacktrace if message is empty. + // It's the only way to provide any helpful information to the user. + if (this._globalOptions.stacktrace || options.stacktrace || data.message === '') { + // fingerprint on msg, not stack trace (legacy behavior, could be revisited) + data.fingerprint = data.fingerprint == null ? msg : data.fingerprint; + + options = objectMerge$1( + { + trimHeadFrames: 0 + }, + options + ); + // Since we know this is a synthetic trace, the top frame (this function call) + // MUST be from Raven.js, so mark it for trimming + // We add to the trim counter so that callers can choose to trim extra frames, such + // as utility functions. + options.trimHeadFrames += 1; + + var frames = this._prepareFrames(stack, options); + data.stacktrace = { + // Sentry expects frames oldest to newest + frames: frames.reverse() + }; + } + + // Make sure that fingerprint is always wrapped in an array + if (data.fingerprint) { + data.fingerprint = isArray$1(data.fingerprint) + ? data.fingerprint + : [data.fingerprint]; + } + + // Fire away! + this._send(data); + + return this; + }, + + captureBreadcrumb: function(obj) { + var crumb = objectMerge$1( + { + timestamp: now() / 1000 + }, + obj + ); + + if (isFunction$1(this._globalOptions.breadcrumbCallback)) { + var result = this._globalOptions.breadcrumbCallback(crumb); + + if (isObject$1(result) && !isEmptyObject$1(result)) { + crumb = result; + } else if (result === false) { + return this; + } + } + + this._breadcrumbs.push(crumb); + if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) { + this._breadcrumbs.shift(); + } + return this; + }, + + addPlugin: function(plugin /*arg1, arg2, ... argN*/) { + var pluginArgs = [].slice.call(arguments, 1); + + this._plugins.push([plugin, pluginArgs]); + if (this._isRavenInstalled) { + this._drainPlugins(); + } + + return this; + }, + + /* + * Set/clear a user to be sent along with the payload. + * + * @param {object} user An object representing user data [optional] + * @return {Raven} + */ + setUserContext: function(user) { + // Intentionally do not merge here since that's an unexpected behavior. + this._globalContext.user = user; + + return this; + }, + + /* + * Merge extra attributes to be sent along with the payload. + * + * @param {object} extra An object representing extra data [optional] + * @return {Raven} + */ + setExtraContext: function(extra) { + this._mergeContext('extra', extra); + + return this; + }, + + /* + * Merge tags to be sent along with the payload. + * + * @param {object} tags An object representing tags [optional] + * @return {Raven} + */ + setTagsContext: function(tags) { + this._mergeContext('tags', tags); + + return this; + }, + + /* + * Clear all of the context. + * + * @return {Raven} + */ + clearContext: function() { + this._globalContext = {}; + + return this; + }, + + /* + * Get a copy of the current context. This cannot be mutated. + * + * @return {object} copy of context + */ + getContext: function() { + // lol javascript + return JSON.parse(stringify_1(this._globalContext)); + }, + + /* + * Set environment of application + * + * @param {string} environment Typically something like 'production'. + * @return {Raven} + */ + setEnvironment: function(environment) { + this._globalOptions.environment = environment; + + return this; + }, + + /* + * Set release version of application + * + * @param {string} release Typically something like a git SHA to identify version + * @return {Raven} + */ + setRelease: function(release) { + this._globalOptions.release = release; + + return this; + }, + + /* + * Set the dataCallback option + * + * @param {function} callback The callback to run which allows the + * data blob to be mutated before sending + * @return {Raven} + */ + setDataCallback: function(callback) { + var original = this._globalOptions.dataCallback; + this._globalOptions.dataCallback = keepOriginalCallback(original, callback); + return this; + }, + + /* + * Set the breadcrumbCallback option + * + * @param {function} callback The callback to run which allows filtering + * or mutating breadcrumbs + * @return {Raven} + */ + setBreadcrumbCallback: function(callback) { + var original = this._globalOptions.breadcrumbCallback; + this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback); + return this; + }, + + /* + * Set the shouldSendCallback option + * + * @param {function} callback The callback to run which allows + * introspecting the blob before sending + * @return {Raven} + */ + setShouldSendCallback: function(callback) { + var original = this._globalOptions.shouldSendCallback; + this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback); + return this; + }, + + /** + * Override the default HTTP transport mechanism that transmits data + * to the Sentry server. + * + * @param {function} transport Function invoked instead of the default + * `makeRequest` handler. + * + * @return {Raven} + */ + setTransport: function(transport) { + this._globalOptions.transport = transport; + + return this; + }, + + /* + * Get the latest raw exception that was captured by Raven. + * + * @return {error} + */ + lastException: function() { + return this._lastCapturedException; + }, + + /* + * Get the last event id + * + * @return {string} + */ + lastEventId: function() { + return this._lastEventId; + }, + + /* + * Determine if Raven is setup and ready to go. + * + * @return {boolean} + */ + isSetup: function() { + if (!this._hasJSON) return false; // needs JSON support + if (!this._globalServer) { + if (!this.ravenNotConfiguredError) { + this.ravenNotConfiguredError = true; + this._logDebug('error', 'Error: Raven has not been configured.'); + } + return false; + } + return true; + }, + + afterLoad: function() { + // TODO: remove window dependence? + + // Attempt to initialize Raven on load + var RavenConfig = _window$2.RavenConfig; + if (RavenConfig) { + this.config(RavenConfig.dsn, RavenConfig.config).install(); + } + }, + + showReportDialog: function(options) { + if ( + !_document // doesn't work without a document (React native) + ) + return; + + options = objectMerge$1( + { + eventId: this.lastEventId(), + dsn: this._dsn, + user: this._globalContext.user || {} + }, + options + ); + + if (!options.eventId) { + throw new configError('Missing eventId'); + } + + if (!options.dsn) { + throw new configError('Missing DSN'); + } + + var encode = encodeURIComponent; + var encodedOptions = []; + + for (var key in options) { + if (key === 'user') { + var user = options.user; + if (user.name) encodedOptions.push('name=' + encode(user.name)); + if (user.email) encodedOptions.push('email=' + encode(user.email)); + } else { + encodedOptions.push(encode(key) + '=' + encode(options[key])); + } + } + var globalServer = this._getGlobalServer(this._parseDSN(options.dsn)); + + var script = _document.createElement('script'); + script.async = true; + script.src = globalServer + '/api/embed/error-page/?' + encodedOptions.join('&'); + (_document.head || _document.body).appendChild(script); + }, + + /**** Private functions ****/ + _ignoreNextOnError: function() { + var self = this; + this._ignoreOnError += 1; + setTimeout(function() { + // onerror should trigger before setTimeout + self._ignoreOnError -= 1; + }); + }, + + _triggerEvent: function(eventType, options) { + // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it + var evt, key; + + if (!this._hasDocument) return; + + options = options || {}; + + eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1); + + if (_document.createEvent) { + evt = _document.createEvent('HTMLEvents'); + evt.initEvent(eventType, true, true); + } else { + evt = _document.createEventObject(); + evt.eventType = eventType; + } + + for (key in options) + if (hasKey$1(options, key)) { + evt[key] = options[key]; + } + + if (_document.createEvent) { + // IE9 if standards + _document.dispatchEvent(evt); + } else { + // IE8 regardless of Quirks or Standards + // IE9 if quirks + try { + _document.fireEvent('on' + evt.eventType.toLowerCase(), evt); + } catch (e) { + // Do nothing + } + } + }, + + /** + * Wraps addEventListener to capture UI breadcrumbs + * @param evtName the event name (e.g. "click") + * @returns {Function} + * @private + */ + _breadcrumbEventHandler: function(evtName) { + var self = this; + return function(evt) { + // reset keypress timeout; e.g. triggering a 'click' after + // a 'keypress' will reset the keypress debounce so that a new + // set of keypresses can be recorded + self._keypressTimeout = null; + + // It's possible this handler might trigger multiple times for the same + // event (e.g. event propagation through node ancestors). Ignore if we've + // already captured the event. + if (self._lastCapturedEvent === evt) return; + + self._lastCapturedEvent = evt; + + // try/catch both: + // - accessing evt.target (see getsentry/raven-js#838, #768) + // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly + // can throw an exception in some circumstances. + var target; + try { + target = htmlTreeAsString$1(evt.target); + } catch (e) { + target = '<unknown>'; + } + + self.captureBreadcrumb({ + category: 'ui.' + evtName, // e.g. ui.click, ui.input + message: target + }); + }; + }, + + /** + * Wraps addEventListener to capture keypress UI events + * @returns {Function} + * @private + */ + _keypressEventHandler: function() { + var self = this, + debounceDuration = 1000; // milliseconds + + // TODO: if somehow user switches keypress target before + // debounce timeout is triggered, we will only capture + // a single breadcrumb from the FIRST target (acceptable?) + return function(evt) { + var target; + try { + target = evt.target; + } catch (e) { + // just accessing event properties can throw an exception in some rare circumstances + // see: https://github.com/getsentry/raven-js/issues/838 + return; + } + var tagName = target && target.tagName; + + // only consider keypress events on actual input elements + // this will disregard keypresses targeting body (e.g. tabbing + // through elements, hotkeys, etc) + if ( + !tagName || + (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable) + ) + return; + + // record first keypress in a series, but ignore subsequent + // keypresses until debounce clears + var timeout = self._keypressTimeout; + if (!timeout) { + self._breadcrumbEventHandler('input')(evt); + } + clearTimeout(timeout); + self._keypressTimeout = setTimeout(function() { + self._keypressTimeout = null; + }, debounceDuration); + }; + }, + + /** + * Captures a breadcrumb of type "navigation", normalizing input URLs + * @param to the originating URL + * @param from the target URL + * @private + */ + _captureUrlChange: function(from, to) { + var parsedLoc = parseUrl$1(this._location.href); + var parsedTo = parseUrl$1(to); + var parsedFrom = parseUrl$1(from); + + // because onpopstate only tells you the "new" (to) value of location.href, and + // not the previous (from) value, we need to track the value of the current URL + // state ourselves + this._lastHref = to; + + // Use only the path component of the URL if the URL matches the current + // document (almost all the time when using pushState) + if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) + to = parsedTo.relative; + if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) + from = parsedFrom.relative; + + this.captureBreadcrumb({ + category: 'navigation', + data: { + to: to, + from: from + } + }); + }, + + _patchFunctionToString: function() { + var self = this; + self._originalFunctionToString = Function.prototype.toString; + // eslint-disable-next-line no-extend-native + Function.prototype.toString = function() { + if (typeof this === 'function' && this.__raven__) { + return self._originalFunctionToString.apply(this.__orig__, arguments); + } + return self._originalFunctionToString.apply(this, arguments); + }; + }, + + _unpatchFunctionToString: function() { + if (this._originalFunctionToString) { + // eslint-disable-next-line no-extend-native + Function.prototype.toString = this._originalFunctionToString; + } + }, + + /** + * Wrap timer functions and event targets to catch errors and provide + * better metadata. + */ + _instrumentTryCatch: function() { + var self = this; + + var wrappedBuiltIns = self._wrappedBuiltIns; + + function wrapTimeFn(orig) { + return function(fn, t) { + // preserve arity + // Make a copy of the arguments to prevent deoptimization + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } + var originalCallback = args[0]; + if (isFunction$1(originalCallback)) { + args[0] = self.wrap( + { + mechanism: { + type: 'instrument', + data: {function: orig.name || '<anonymous>'} + } + }, + originalCallback + ); + } + + // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it + // also supports only two arguments and doesn't care what this is, so we + // can just call the original function directly. + if (orig.apply) { + return orig.apply(this, args); + } else { + return orig(args[0], args[1]); + } + }; + } + + var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; + + function wrapEventTarget(global) { + var proto = _window$2[global] && _window$2[global].prototype; + if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) { + fill$1( + proto, + 'addEventListener', + function(orig) { + return function(evtName, fn, capture, secure) { + // preserve arity + try { + if (fn && fn.handleEvent) { + fn.handleEvent = self.wrap( + { + mechanism: { + type: 'instrument', + data: { + target: global, + function: 'handleEvent', + handler: (fn && fn.name) || '<anonymous>' + } + } + }, + fn.handleEvent + ); + } + } catch (err) { + // can sometimes get 'Permission denied to access property "handle Event' + } + + // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs` + // so that we don't have more than one wrapper function + var before, clickHandler, keypressHandler; + + if ( + autoBreadcrumbs && + autoBreadcrumbs.dom && + (global === 'EventTarget' || global === 'Node') + ) { + // NOTE: generating multiple handlers per addEventListener invocation, should + // revisit and verify we can just use one (almost certainly) + clickHandler = self._breadcrumbEventHandler('click'); + keypressHandler = self._keypressEventHandler(); + before = function(evt) { + // need to intercept every DOM event in `before` argument, in case that + // same wrapped method is re-used for different events (e.g. mousemove THEN click) + // see #724 + if (!evt) return; + + var eventType; + try { + eventType = evt.type; + } catch (e) { + // just accessing event properties can throw an exception in some rare circumstances + // see: https://github.com/getsentry/raven-js/issues/838 + return; + } + if (eventType === 'click') return clickHandler(evt); + else if (eventType === 'keypress') return keypressHandler(evt); + }; + } + return orig.call( + this, + evtName, + self.wrap( + { + mechanism: { + type: 'instrument', + data: { + target: global, + function: 'addEventListener', + handler: (fn && fn.name) || '<anonymous>' + } + } + }, + fn, + before + ), + capture, + secure + ); + }; + }, + wrappedBuiltIns + ); + fill$1( + proto, + 'removeEventListener', + function(orig) { + return function(evt, fn, capture, secure) { + try { + fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn); + } catch (e) { + // ignore, accessing __raven_wrapper__ will throw in some Selenium environments + } + return orig.call(this, evt, fn, capture, secure); + }; + }, + wrappedBuiltIns + ); + } + } + + fill$1(_window$2, 'setTimeout', wrapTimeFn, wrappedBuiltIns); + fill$1(_window$2, 'setInterval', wrapTimeFn, wrappedBuiltIns); + if (_window$2.requestAnimationFrame) { + fill$1( + _window$2, + 'requestAnimationFrame', + function(orig) { + return function(cb) { + return orig( + self.wrap( + { + mechanism: { + type: 'instrument', + data: { + function: 'requestAnimationFrame', + handler: (orig && orig.name) || '<anonymous>' + } + } + }, + cb + ) + ); + }; + }, + wrappedBuiltIns + ); + } + + // event targets borrowed from bugsnag-js: + // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666 + var eventTargets = [ + 'EventTarget', + 'Window', + 'Node', + 'ApplicationCache', + 'AudioTrackList', + 'ChannelMergerNode', + 'CryptoOperation', + 'EventSource', + 'FileReader', + 'HTMLUnknownElement', + 'IDBDatabase', + 'IDBRequest', + 'IDBTransaction', + 'KeyOperation', + 'MediaController', + 'MessagePort', + 'ModalWindow', + 'Notification', + 'SVGElementInstance', + 'Screen', + 'TextTrack', + 'TextTrackCue', + 'TextTrackList', + 'WebSocket', + 'WebSocketWorker', + 'Worker', + 'XMLHttpRequest', + 'XMLHttpRequestEventTarget', + 'XMLHttpRequestUpload' + ]; + for (var i = 0; i < eventTargets.length; i++) { + wrapEventTarget(eventTargets[i]); + } + }, + + /** + * Instrument browser built-ins w/ breadcrumb capturing + * - XMLHttpRequests + * - DOM interactions (click/typing) + * - window.location changes + * - console + * + * Can be disabled or individually configured via the `autoBreadcrumbs` config option + */ + _instrumentBreadcrumbs: function() { + var self = this; + var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; + + var wrappedBuiltIns = self._wrappedBuiltIns; + + function wrapProp(prop, xhr) { + if (prop in xhr && isFunction$1(xhr[prop])) { + fill$1(xhr, prop, function(orig) { + return self.wrap( + { + mechanism: { + type: 'instrument', + data: {function: prop, handler: (orig && orig.name) || '<anonymous>'} + } + }, + orig + ); + }); // intentionally don't track filled methods on XHR instances + } + } + + if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window$2) { + var xhrproto = _window$2.XMLHttpRequest && _window$2.XMLHttpRequest.prototype; + fill$1( + xhrproto, + 'open', + function(origOpen) { + return function(method, url) { + // preserve arity + + // if Sentry key appears in URL, don't capture + if (isString$1(url) && url.indexOf(self._globalKey) === -1) { + this.__raven_xhr = { + method: method, + url: url, + status_code: null + }; + } + + return origOpen.apply(this, arguments); + }; + }, + wrappedBuiltIns + ); + + fill$1( + xhrproto, + 'send', + function(origSend) { + return function() { + // preserve arity + var xhr = this; + + function onreadystatechangeHandler() { + if (xhr.__raven_xhr && xhr.readyState === 4) { + try { + // touching statusCode in some platforms throws + // an exception + xhr.__raven_xhr.status_code = xhr.status; + } catch (e) { + /* do nothing */ + } + + self.captureBreadcrumb({ + type: 'http', + category: 'xhr', + data: xhr.__raven_xhr + }); + } + } + + var props = ['onload', 'onerror', 'onprogress']; + for (var j = 0; j < props.length; j++) { + wrapProp(props[j], xhr); + } + + if ('onreadystatechange' in xhr && isFunction$1(xhr.onreadystatechange)) { + fill$1( + xhr, + 'onreadystatechange', + function(orig) { + return self.wrap( + { + mechanism: { + type: 'instrument', + data: { + function: 'onreadystatechange', + handler: (orig && orig.name) || '<anonymous>' + } + } + }, + orig, + onreadystatechangeHandler + ); + } /* intentionally don't track this instrumentation */ + ); + } else { + // if onreadystatechange wasn't actually set by the page on this xhr, we + // are free to set our own and capture the breadcrumb + xhr.onreadystatechange = onreadystatechangeHandler; + } + + return origSend.apply(this, arguments); + }; + }, + wrappedBuiltIns + ); + } + + if (autoBreadcrumbs.xhr && supportsFetch$1()) { + fill$1( + _window$2, + 'fetch', + function(origFetch) { + return function() { + // preserve arity + // Make a copy of the arguments to prevent deoptimization + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } + + var fetchInput = args[0]; + var method = 'GET'; + var url; + + if (typeof fetchInput === 'string') { + url = fetchInput; + } else if ('Request' in _window$2 && fetchInput instanceof _window$2.Request) { + url = fetchInput.url; + if (fetchInput.method) { + method = fetchInput.method; + } + } else { + url = '' + fetchInput; + } + + // if Sentry key appears in URL, don't capture, as it's our own request + if (url.indexOf(self._globalKey) !== -1) { + return origFetch.apply(this, args); + } + + if (args[1] && args[1].method) { + method = args[1].method; + } + + var fetchData = { + method: method, + url: url, + status_code: null + }; + + return origFetch + .apply(this, args) + .then(function(response) { + fetchData.status_code = response.status; + + self.captureBreadcrumb({ + type: 'http', + category: 'fetch', + data: fetchData + }); + + return response; + }) + ['catch'](function(err) { + // if there is an error performing the request + self.captureBreadcrumb({ + type: 'http', + category: 'fetch', + data: fetchData, + level: 'error' + }); + + throw err; + }); + }; + }, + wrappedBuiltIns + ); + } + + // Capture breadcrumbs from any click that is unhandled / bubbled up all the way + // to the document. Do this before we instrument addEventListener. + if (autoBreadcrumbs.dom && this._hasDocument) { + if (_document.addEventListener) { + _document.addEventListener('click', self._breadcrumbEventHandler('click'), false); + _document.addEventListener('keypress', self._keypressEventHandler(), false); + } else if (_document.attachEvent) { + // IE8 Compatibility + _document.attachEvent('onclick', self._breadcrumbEventHandler('click')); + _document.attachEvent('onkeypress', self._keypressEventHandler()); + } + } + + // record navigation (URL) changes + // NOTE: in Chrome App environment, touching history.pushState, *even inside + // a try/catch block*, will cause Chrome to output an error to console.error + // borrowed from: https://github.com/angular/angular.js/pull/13945/files + var chrome = _window$2.chrome; + var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime; + var hasPushAndReplaceState = + !isChromePackagedApp && + _window$2.history && + _window$2.history.pushState && + _window$2.history.replaceState; + if (autoBreadcrumbs.location && hasPushAndReplaceState) { + // TODO: remove onpopstate handler on uninstall() + var oldOnPopState = _window$2.onpopstate; + _window$2.onpopstate = function() { + var currentHref = self._location.href; + self._captureUrlChange(self._lastHref, currentHref); + + if (oldOnPopState) { + return oldOnPopState.apply(this, arguments); + } + }; + + var historyReplacementFunction = function(origHistFunction) { + // note history.pushState.length is 0; intentionally not declaring + // params to preserve 0 arity + return function(/* state, title, url */) { + var url = arguments.length > 2 ? arguments[2] : undefined; + + // url argument is optional + if (url) { + // coerce to string (this is what pushState does) + self._captureUrlChange(self._lastHref, url + ''); + } + + return origHistFunction.apply(this, arguments); + }; + }; + + fill$1(_window$2.history, 'pushState', historyReplacementFunction, wrappedBuiltIns); + fill$1(_window$2.history, 'replaceState', historyReplacementFunction, wrappedBuiltIns); + } + + if (autoBreadcrumbs.console && 'console' in _window$2 && console.log) { + // console + var consoleMethodCallback = function(msg, data) { + self.captureBreadcrumb({ + message: msg, + level: data.level, + category: 'console' + }); + }; + + each$1(['debug', 'info', 'warn', 'error', 'log'], function(_, level) { + wrapConsoleMethod(console, level, consoleMethodCallback); + }); + } + }, + + _restoreBuiltIns: function() { + // restore any wrapped builtins + var builtin; + while (this._wrappedBuiltIns.length) { + builtin = this._wrappedBuiltIns.shift(); + + var obj = builtin[0], + name = builtin[1], + orig = builtin[2]; + + obj[name] = orig; + } + }, + + _restoreConsole: function() { + // eslint-disable-next-line guard-for-in + for (var method in this._originalConsoleMethods) { + this._originalConsole[method] = this._originalConsoleMethods[method]; + } + }, + + _drainPlugins: function() { + var self = this; + + // FIX ME TODO + each$1(this._plugins, function(_, plugin) { + var installer = plugin[0]; + var args = plugin[1]; + installer.apply(self, [self].concat(args)); + }); + }, + + _parseDSN: function(str) { + var m = dsnPattern.exec(str), + dsn = {}, + i = 7; + + try { + while (i--) dsn[dsnKeys[i]] = m[i] || ''; + } catch (e) { + throw new configError('Invalid DSN: ' + str); + } + + if (dsn.pass && !this._globalOptions.allowSecretKey) { + throw new configError( + 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key' + ); + } + + return dsn; + }, + + _getGlobalServer: function(uri) { + // assemble the endpoint from the uri pieces + var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : ''); + + if (uri.protocol) { + globalServer = uri.protocol + ':' + globalServer; + } + return globalServer; + }, + + _handleOnErrorStackInfo: function(stackInfo, options) { + options = options || {}; + options.mechanism = options.mechanism || { + type: 'onerror', + handled: false + }; + + // if we are intentionally ignoring errors via onerror, bail out + if (!this._ignoreOnError) { + this._handleStackInfo(stackInfo, options); + } + }, + + _handleStackInfo: function(stackInfo, options) { + var frames = this._prepareFrames(stackInfo, options); + + this._triggerEvent('handle', { + stackInfo: stackInfo, + options: options + }); + + this._processException( + stackInfo.name, + stackInfo.message, + stackInfo.url, + stackInfo.lineno, + frames, + options + ); + }, + + _prepareFrames: function(stackInfo, options) { + var self = this; + var frames = []; + if (stackInfo.stack && stackInfo.stack.length) { + each$1(stackInfo.stack, function(i, stack) { + var frame = self._normalizeFrame(stack, stackInfo.url); + if (frame) { + frames.push(frame); + } + }); + + // e.g. frames captured via captureMessage throw + if (options && options.trimHeadFrames) { + for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) { + frames[j].in_app = false; + } + } + } + frames = frames.slice(0, this._globalOptions.stackTraceLimit); + return frames; + }, + + _normalizeFrame: function(frame, stackInfoUrl) { + // normalize the frames data + var normalized = { + filename: frame.url, + lineno: frame.line, + colno: frame.column, + function: frame.func || '?' + }; + + // Case when we don't have any information about the error + // E.g. throwing a string or raw object, instead of an `Error` in Firefox + // Generating synthetic error doesn't add any value here + // + // We should probably somehow let a user know that they should fix their code + if (!frame.url) { + normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler + } + + normalized.in_app = !// determine if an exception came from outside of our app + // first we check the global includePaths list. + ( + (!!this._globalOptions.includePaths.test && + !this._globalOptions.includePaths.test(normalized.filename)) || + // Now we check for fun, if the function name is Raven or TraceKit + /(Raven|TraceKit)\./.test(normalized['function']) || + // finally, we do a last ditch effort and check for raven.min.js + /raven\.(min\.)?js$/.test(normalized.filename) + ); + + return normalized; + }, + + _processException: function(type, message, fileurl, lineno, frames, options) { + var prefixedMessage = (type ? type + ': ' : '') + (message || ''); + if ( + !!this._globalOptions.ignoreErrors.test && + (this._globalOptions.ignoreErrors.test(message) || + this._globalOptions.ignoreErrors.test(prefixedMessage)) + ) { + return; + } + + var stacktrace; + + if (frames && frames.length) { + fileurl = frames[0].filename || fileurl; + // Sentry expects frames oldest to newest + // and JS sends them as newest to oldest + frames.reverse(); + stacktrace = {frames: frames}; + } else if (fileurl) { + stacktrace = { + frames: [ + { + filename: fileurl, + lineno: lineno, + in_app: true + } + ] + }; + } + + if ( + !!this._globalOptions.ignoreUrls.test && + this._globalOptions.ignoreUrls.test(fileurl) + ) { + return; + } + + if ( + !!this._globalOptions.whitelistUrls.test && + !this._globalOptions.whitelistUrls.test(fileurl) + ) { + return; + } + + var data = objectMerge$1( + { + // sentry.interfaces.Exception + exception: { + values: [ + { + type: type, + value: message, + stacktrace: stacktrace + } + ] + }, + transaction: fileurl + }, + options + ); + + var ex = data.exception.values[0]; + if (ex.type == null && ex.value === '') { + ex.value = 'Unrecoverable error caught'; + } + + // Move mechanism from options to exception interface + // We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be + // too much + if (!data.exception.mechanism && data.mechanism) { + data.exception.mechanism = data.mechanism; + delete data.mechanism; + } + + data.exception.mechanism = objectMerge$1( + { + type: 'generic', + handled: true + }, + data.exception.mechanism || {} + ); + + // Fire away! + this._send(data); + }, + + _trimPacket: function(data) { + // For now, we only want to truncate the two different messages + // but this could/should be expanded to just trim everything + var max = this._globalOptions.maxMessageLength; + if (data.message) { + data.message = truncate$1(data.message, max); + } + if (data.exception) { + var exception = data.exception.values[0]; + exception.value = truncate$1(exception.value, max); + } + + var request = data.request; + if (request) { + if (request.url) { + request.url = truncate$1(request.url, this._globalOptions.maxUrlLength); + } + if (request.Referer) { + request.Referer = truncate$1(request.Referer, this._globalOptions.maxUrlLength); + } + } + + if (data.breadcrumbs && data.breadcrumbs.values) + this._trimBreadcrumbs(data.breadcrumbs); + + return data; + }, + + /** + * Truncate breadcrumb values (right now just URLs) + */ + _trimBreadcrumbs: function(breadcrumbs) { + // known breadcrumb properties with urls + // TODO: also consider arbitrary prop values that start with (https?)?:// + var urlProps = ['to', 'from', 'url'], + urlProp, + crumb, + data; + + for (var i = 0; i < breadcrumbs.values.length; ++i) { + crumb = breadcrumbs.values[i]; + if ( + !crumb.hasOwnProperty('data') || + !isObject$1(crumb.data) || + objectFrozen$1(crumb.data) + ) + continue; + + data = objectMerge$1({}, crumb.data); + for (var j = 0; j < urlProps.length; ++j) { + urlProp = urlProps[j]; + if (data.hasOwnProperty(urlProp) && data[urlProp]) { + data[urlProp] = truncate$1(data[urlProp], this._globalOptions.maxUrlLength); + } + } + breadcrumbs.values[i].data = data; + } + }, + + _getHttpData: function() { + if (!this._hasNavigator && !this._hasDocument) return; + var httpData = {}; + + if (this._hasNavigator && _navigator.userAgent) { + httpData.headers = { + 'User-Agent': _navigator.userAgent + }; + } + + // Check in `window` instead of `document`, as we may be in ServiceWorker environment + if (_window$2.location && _window$2.location.href) { + httpData.url = _window$2.location.href; + } + + if (this._hasDocument && _document.referrer) { + if (!httpData.headers) httpData.headers = {}; + httpData.headers.Referer = _document.referrer; + } + + return httpData; + }, + + _resetBackoff: function() { + this._backoffDuration = 0; + this._backoffStart = null; + }, + + _shouldBackoff: function() { + return this._backoffDuration && now() - this._backoffStart < this._backoffDuration; + }, + + /** + * Returns true if the in-process data payload matches the signature + * of the previously-sent data + * + * NOTE: This has to be done at this level because TraceKit can generate + * data from window.onerror WITHOUT an exception object (IE8, IE9, + * other old browsers). This can take the form of an "exception" + * data object with a single frame (derived from the onerror args). + */ + _isRepeatData: function(current) { + var last = this._lastData; + + if ( + !last || + current.message !== last.message || // defined for captureMessage + current.transaction !== last.transaction // defined for captureException/onerror + ) + return false; + + // Stacktrace interface (i.e. from captureMessage) + if (current.stacktrace || last.stacktrace) { + return isSameStacktrace$1(current.stacktrace, last.stacktrace); + } else if (current.exception || last.exception) { + // Exception interface (i.e. from captureException/onerror) + return isSameException$1(current.exception, last.exception); + } + + return true; + }, + + _setBackoffState: function(request) { + // If we are already in a backoff state, don't change anything + if (this._shouldBackoff()) { + return; + } + + var status = request.status; + + // 400 - project_id doesn't exist or some other fatal + // 401 - invalid/revoked dsn + // 429 - too many requests + if (!(status === 400 || status === 401 || status === 429)) return; + + var retry; + try { + // If Retry-After is not in Access-Control-Expose-Headers, most + // browsers will throw an exception trying to access it + if (supportsFetch$1()) { + retry = request.headers.get('Retry-After'); + } else { + retry = request.getResponseHeader('Retry-After'); + } + + // Retry-After is returned in seconds + retry = parseInt(retry, 10) * 1000; + } catch (e) { + /* eslint no-empty:0 */ + } + + this._backoffDuration = retry + ? // If Sentry server returned a Retry-After value, use it + retry + : // Otherwise, double the last backoff duration (starts at 1 sec) + this._backoffDuration * 2 || 1000; + + this._backoffStart = now(); + }, + + _send: function(data) { + var globalOptions = this._globalOptions; + + var baseData = { + project: this._globalProject, + logger: globalOptions.logger, + platform: 'javascript' + }, + httpData = this._getHttpData(); + + if (httpData) { + baseData.request = httpData; + } + + // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload + if (data.trimHeadFrames) delete data.trimHeadFrames; + + data = objectMerge$1(baseData, data); + + // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge + data.tags = objectMerge$1(objectMerge$1({}, this._globalContext.tags), data.tags); + data.extra = objectMerge$1(objectMerge$1({}, this._globalContext.extra), data.extra); + + // Send along our own collected metadata with extra + data.extra['session:duration'] = now() - this._startTime; + + if (this._breadcrumbs && this._breadcrumbs.length > 0) { + // intentionally make shallow copy so that additions + // to breadcrumbs aren't accidentally sent in this request + data.breadcrumbs = { + values: [].slice.call(this._breadcrumbs, 0) + }; + } + + if (this._globalContext.user) { + // sentry.interfaces.User + data.user = this._globalContext.user; + } + + // Include the environment if it's defined in globalOptions + if (globalOptions.environment) data.environment = globalOptions.environment; + + // Include the release if it's defined in globalOptions + if (globalOptions.release) data.release = globalOptions.release; + + // Include server_name if it's defined in globalOptions + if (globalOptions.serverName) data.server_name = globalOptions.serverName; + + data = this._sanitizeData(data); + + // Cleanup empty properties before sending them to the server + Object.keys(data).forEach(function(key) { + if (data[key] == null || data[key] === '' || isEmptyObject$1(data[key])) { + delete data[key]; + } + }); + + if (isFunction$1(globalOptions.dataCallback)) { + data = globalOptions.dataCallback(data) || data; + } + + // Why?????????? + if (!data || isEmptyObject$1(data)) { + return; + } + + // Check if the request should be filtered or not + if ( + isFunction$1(globalOptions.shouldSendCallback) && + !globalOptions.shouldSendCallback(data) + ) { + return; + } + + // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests), + // so drop requests until "cool-off" period has elapsed. + if (this._shouldBackoff()) { + this._logDebug('warn', 'Raven dropped error due to backoff: ', data); + return; + } + + if (typeof globalOptions.sampleRate === 'number') { + if (Math.random() < globalOptions.sampleRate) { + this._sendProcessedPayload(data); + } + } else { + this._sendProcessedPayload(data); + } + }, + + _sanitizeData: function(data) { + return sanitize$1(data, this._globalOptions.sanitizeKeys); + }, + + _getUuid: function() { + return uuid4$1(); + }, + + _sendProcessedPayload: function(data, callback) { + var self = this; + var globalOptions = this._globalOptions; + + if (!this.isSetup()) return; + + // Try and clean up the packet before sending by truncating long values + data = this._trimPacket(data); + + // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback, + // but this would require copying an un-truncated copy of the data packet, which can be + // arbitrarily deep (extra_data) -- could be worthwhile? will revisit + if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) { + this._logDebug('warn', 'Raven dropped repeat event: ', data); + return; + } + + // Send along an event_id if not explicitly passed. + // This event_id can be used to reference the error within Sentry itself. + // Set lastEventId after we know the error should actually be sent + this._lastEventId = data.event_id || (data.event_id = this._getUuid()); + + // Store outbound payload after trim + this._lastData = data; + + this._logDebug('debug', 'Raven about to send:', data); + + var auth = { + sentry_version: '7', + sentry_client: 'raven-js/' + this.VERSION, + sentry_key: this._globalKey + }; + + if (this._globalSecret) { + auth.sentry_secret = this._globalSecret; + } + + var exception = data.exception && data.exception.values[0]; + + // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy + if ( + this._globalOptions.autoBreadcrumbs && + this._globalOptions.autoBreadcrumbs.sentry + ) { + this.captureBreadcrumb({ + category: 'sentry', + message: exception + ? (exception.type ? exception.type + ': ' : '') + exception.value + : data.message, + event_id: data.event_id, + level: data.level || 'error' // presume error unless specified + }); + } + + var url = this._globalEndpoint; + (globalOptions.transport || this._makeRequest).call(this, { + url: url, + auth: auth, + data: data, + options: globalOptions, + onSuccess: function success() { + self._resetBackoff(); + + self._triggerEvent('success', { + data: data, + src: url + }); + callback && callback(); + }, + onError: function failure(error) { + self._logDebug('error', 'Raven transport failed to send: ', error); + + if (error.request) { + self._setBackoffState(error.request); + } + + self._triggerEvent('failure', { + data: data, + src: url + }); + error = error || new Error('Raven send failed (no additional details provided)'); + callback && callback(error); + } + }); + }, + + _makeRequest: function(opts) { + // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests + var url = opts.url + '?' + urlencode$1(opts.auth); + + var evaluatedHeaders = null; + var evaluatedFetchParameters = {}; + + if (opts.options.headers) { + evaluatedHeaders = this._evaluateHash(opts.options.headers); + } + + if (opts.options.fetchParameters) { + evaluatedFetchParameters = this._evaluateHash(opts.options.fetchParameters); + } + + if (supportsFetch$1()) { + evaluatedFetchParameters.body = stringify_1(opts.data); + + var defaultFetchOptions = objectMerge$1({}, this._fetchDefaults); + var fetchOptions = objectMerge$1(defaultFetchOptions, evaluatedFetchParameters); + + if (evaluatedHeaders) { + fetchOptions.headers = evaluatedHeaders; + } + + return _window$2 + .fetch(url, fetchOptions) + .then(function(response) { + if (response.ok) { + opts.onSuccess && opts.onSuccess(); + } else { + var error = new Error('Sentry error code: ' + response.status); + // It's called request only to keep compatibility with XHR interface + // and not add more redundant checks in setBackoffState method + error.request = response; + opts.onError && opts.onError(error); + } + }) + ['catch'](function() { + opts.onError && + opts.onError(new Error('Sentry error code: network unavailable')); + }); + } + + var request = _window$2.XMLHttpRequest && new _window$2.XMLHttpRequest(); + if (!request) return; + + // if browser doesn't support CORS (e.g. IE7), we are out of luck + var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined'; + + if (!hasCORS) return; + + if ('withCredentials' in request) { + request.onreadystatechange = function() { + if (request.readyState !== 4) { + return; + } else if (request.status === 200) { + opts.onSuccess && opts.onSuccess(); + } else if (opts.onError) { + var err = new Error('Sentry error code: ' + request.status); + err.request = request; + opts.onError(err); + } + }; + } else { + request = new XDomainRequest(); + // xdomainrequest cannot go http -> https (or vice versa), + // so always use protocol relative + url = url.replace(/^https?:/, ''); + + // onreadystatechange not supported by XDomainRequest + if (opts.onSuccess) { + request.onload = opts.onSuccess; + } + if (opts.onError) { + request.onerror = function() { + var err = new Error('Sentry error code: XDomainRequest'); + err.request = request; + opts.onError(err); + }; + } + } + + request.open('POST', url); + + if (evaluatedHeaders) { + each$1(evaluatedHeaders, function(key, value) { + request.setRequestHeader(key, value); + }); + } + + request.send(stringify_1(opts.data)); + }, + + _evaluateHash: function(hash) { + var evaluated = {}; + + for (var key in hash) { + if (hash.hasOwnProperty(key)) { + var value = hash[key]; + evaluated[key] = typeof value === 'function' ? value() : value; + } + } + + return evaluated; + }, + + _logDebug: function(level) { + // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change + if ( + this._originalConsoleMethods[level] && + (this.debug || this._globalOptions.debug) + ) { + // In IE<10 console methods do not have their own 'apply' method + Function.prototype.apply.call( + this._originalConsoleMethods[level], + this._originalConsole, + [].slice.call(arguments, 1) + ); + } + }, + + _mergeContext: function(key, context) { + if (isUndefined$1(context)) { + delete this._globalContext[key]; + } else { + this._globalContext[key] = objectMerge$1(this._globalContext[key] || {}, context); + } + } + }; + + // Deprecations + Raven.prototype.setUser = Raven.prototype.setUserContext; + Raven.prototype.setReleaseContext = Raven.prototype.setRelease; + + var raven = Raven; + + /** + * Enforces a single instance of the Raven client, and the + * main entry point for Raven. If you are a consumer of the + * Raven library, you SHOULD load this file (vs raven.js). + **/ + + + + // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) + var _window$3 = + typeof window !== 'undefined' + ? window + : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; + var _Raven = _window$3.Raven; + + var Raven$1 = new raven(); + + /* + * Allow multiple versions of Raven to be installed. + * Strip Raven from the global context and returns the instance. + * + * @return {Raven} + */ + Raven$1.noConflict = function() { + _window$3.Raven = _Raven; + return Raven$1; + }; + + Raven$1.afterLoad(); + + var singleton = Raven$1; + + /** + * DISCLAIMER: + * + * Expose `Client` constructor for cases where user want to track multiple "sub-applications" in one larger app. + * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it. + * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug. + * + * It's called `Client' to be in-line with Raven Node implementation. + * + * HOWTO: + * + * import Raven from 'raven-js'; + * + * const someAppReporter = new Raven.Client(); + * const someOtherAppReporter = new Raven.Client(); + * + * someAppReporter.config('__DSN__', { + * ...config goes here + * }); + * + * someOtherAppReporter.config('__OTHER_DSN__', { + * ...config goes here + * }); + * + * someAppReporter.captureMessage(...); + * someAppReporter.captureException(...); + * someAppReporter.captureBreadcrumb(...); + * + * someOtherAppReporter.captureMessage(...); + * someOtherAppReporter.captureException(...); + * someOtherAppReporter.captureBreadcrumb(...); + * + * It should "just work". + */ + var Client = raven; + singleton.Client = Client; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + + // ========================================================================== + // Type checking utils + // ========================================================================== + var getConstructor = function getConstructor(input) { + return input !== null && typeof input !== 'undefined' ? input.constructor : null; + }; + + var instanceOf = function instanceOf(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); + }; + + var isNullOrUndefined = function isNullOrUndefined(input) { + return input === null || typeof input === 'undefined'; + }; + + var isObject$2 = function isObject(input) { + return getConstructor(input) === Object; + }; + + var isNumber = function isNumber(input) { + return getConstructor(input) === Number && !Number.isNaN(input); + }; + + var isString$2 = function isString(input) { + return getConstructor(input) === String; + }; + + var isBoolean = function isBoolean(input) { + return getConstructor(input) === Boolean; + }; + + var isFunction$2 = function isFunction(input) { + return getConstructor(input) === Function; + }; + + var isArray$2 = function isArray(input) { + return Array.isArray(input); + }; + + var isWeakMap = function isWeakMap(input) { + return instanceOf(input, WeakMap); + }; + + var isNodeList = function isNodeList(input) { + return instanceOf(input, NodeList); + }; + + var isElement = function isElement(input) { + return instanceOf(input, Element); + }; + + var isTextNode = function isTextNode(input) { + return getConstructor(input) === Text; + }; + + var isEvent = function isEvent(input) { + return instanceOf(input, Event); + }; + + var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); + }; + + var isCue = function isCue(input) { + return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); + }; + + var isTrack = function isTrack(input) { + return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString$2(input.kind); + }; + + var isEmpty = function isEmpty(input) { + return isNullOrUndefined(input) || (isString$2(input) || isArray$2(input) || isNodeList(input)) && !input.length || isObject$2(input) && !Object.keys(input).length; + }; + + var isUrl = function isUrl(input) { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } // Must be string from here + + + if (!isString$2(input)) { + return false; + } // Add the protocol if required + + + var string = input; + + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = "http://".concat(input); + } + + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } + }; + + var is = { + nullOrUndefined: isNullOrUndefined, + object: isObject$2, + number: isNumber, + string: isString$2, + boolean: isBoolean, + function: isFunction$2, + array: isArray$2, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty + }; + + // ========================================================================== + // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // https://www.youtube.com/watch?v=NPM6172J22g + + var supportsPassiveListeners = function () { + // Test via a getter in the options object to see if the passive property is accessed + var supported = false; + + try { + var options = Object.defineProperty({}, 'passive', { + get: function get() { + supported = true; + return null; + } + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) {// Do nothing + } + + return supported; + }(); // Toggle event listener + + + function toggleListener(element, event, callback) { + var _this = this; + + var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { + return; + } // Allow multiple events + + + var events = event.split(' '); // Build options + // Default to just the capture boolean for browsers with no passive listener support + + var options = capture; // If passive events listeners are supported + + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: passive, + // Whether the listener is a capturing listener or not + capture: capture + }; + } // If a single node is passed, bind the event listener + + + events.forEach(function (type) { + if (_this && _this.eventListeners && toggle) { + // Cache event listener + _this.eventListeners.push({ + element: element, + type: type, + callback: callback, + options: options + }); + } + + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); + } // Bind event handler + + function on(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, true, passive, capture); + } // Unbind event handler + + function off(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, false, passive, capture); + } // Bind once-only event handler + + function once(element) { + var _this2 = this; + + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + var onceCallback = function onceCallback() { + off(element, events, onceCallback, passive, capture); + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply(_this2, args); + }; + + toggleListener.call(this, element, events, onceCallback, true, passive, capture); + } // Trigger event + + function triggerEvent(element) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + // Bail if no element + if (!is.element(element) || is.empty(type)) { + return; + } // Create and dispatch the event + + + var event = new CustomEvent(type, { + bubbles: bubbles, + detail: Object.assign({}, detail, { + plyr: this + }) + }); // Dispatch the event + + element.dispatchEvent(event); + } // Unbind all cached event listeners + + function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(function (item) { + var element = item.element, + type = item.type, + callback = item.callback, + options = item.options; + element.removeEventListener(type, callback, options); + }); + this.eventListeners = []; + } + } // Run method when / if player is ready + + function ready() { + var _this3 = this; + + return new Promise(function (resolve) { + return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve); + }).then(function () {}); + } + + function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + + Array.from(targets).reverse().forEach(function (element, index) { + var child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling. + + var parent = element.parentNode; + var sibling = element.nextSibling; // Wrap the element (is automatically removed from its current + // parent). + + child.appendChild(element); // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); + } // Set attributes + + function setAttributes(element, attributes) { + if (!is.element(element) || is.empty(attributes)) { + return; + } // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" + + + Object.entries(attributes).filter(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + value = _ref2[1]; + + return !is.nullOrUndefined(value); + }).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + + return element.setAttribute(key, value); + }); + } // Create a DocumentFragment + + function createElement(type, attributes, text) { + // Create a new <element> + var element = document.createElement(type); // Set all passed attributes + + if (is.object(attributes)) { + setAttributes(element, attributes); + } // Add text node + + + if (is.string(text)) { + element.innerText = text; + } // Return built element + + + return element; + } // Inaert an element after another + + function insertAfter(element, target) { + if (!is.element(element) || !is.element(target)) { + return; + } + + target.parentNode.insertBefore(element, target.nextSibling); + } // Insert a DocumentFragment + + function insertElement(type, parent, attributes, text) { + if (!is.element(parent)) { + return; + } + + parent.appendChild(createElement(type, attributes, text)); + } // Remove element(s) + + function removeElement(element) { + if (is.nodeList(element) || is.array(element)) { + Array.from(element).forEach(removeElement); + return; + } + + if (!is.element(element) || !is.element(element.parentNode)) { + return; + } + + element.parentNode.removeChild(element); + } // Remove all child elements + + function emptyElement(element) { + if (!is.element(element)) { + return; + } + + var length = element.childNodes.length; + + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } + } // Replace element + + function replaceElement(newChild, oldChild) { + if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { + return null; + } + + oldChild.parentNode.replaceChild(newChild, oldChild); + return newChild; + } // Get an attribute object from a string selector + + function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + if (!is.string(sel) || is.empty(sel)) { + return {}; + } + + var attributes = {}; + var existing = existingAttributes; + sel.split(',').forEach(function (s) { + // Remove whitespace + var selector = s.trim(); + var className = selector.replace('.', ''); + var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value + + var parts = stripped.split('='); + var key = parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character + + var start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is.object(existing) && is.string(existing.class)) { + existing.class += " ".concat(className); + } + + attributes.class = className; + break; + + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + + case '[': + // Attribute selector + attributes[key] = value; + break; + + default: + break; + } + }); + return attributes; + } // Toggle hidden + + function toggleHidden(element, hidden) { + if (!is.element(element)) { + return; + } + + var hide = hidden; + + if (!is.boolean(hide)) { + hide = !element.hidden; + } + + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } + } // Mirror Element.classList.toggle, with IE compatibility for "force" argument + + function toggleClass(element, className, force) { + if (is.nodeList(element)) { + return Array.from(element).map(function (e) { + return toggleClass(e, className, force); + }); + } + + if (is.element(element)) { + var method = 'toggle'; + + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } + + element.classList[method](className); + return element.classList.contains(className); + } + + return false; + } // Has class name + + function hasClass(element, className) { + return is.element(element) && element.classList.contains(className); + } // Element matches selector + + function matches(element, selector) { + + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } + + var matches = match; + return matches.call(element, selector); + } // Find all elements + + function getElements(selector) { + return this.elements.container.querySelectorAll(selector); + } // Find a single element + + function getElement(selector) { + return this.elements.container.querySelector(selector); + } // Trap focus inside container + + function trapFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is.element(element)) { + return; + } + + var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + var first = focusable[0]; + var last = focusable[focusable.length - 1]; + + var trap = function trap(event) { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } // Get the current focused element + + + var focused = document.activeElement; + + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); + } // Set focus and tab focus class + + function setFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is.element(element)) { + return; + } // Set regular focus + + + element.focus({ + preventScroll: true + }); // If we want to mimic keyboard focus via tab + + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } + } + + // ========================================================================== + var transitionEndEvent = function () { + var element = document.createElement('span'); + var events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + var type = Object.keys(events).find(function (event) { + return element.style[event] !== undefined; + }); + return is.string(type) ? events[type] : false; + }(); // Force repaint of element + + function repaint(element) { + setTimeout(function () { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line + + toggleHidden(element, false); + } catch (e) {// Do nothing + } + }, 0); + } + + // ========================================================================== + // Browser sniffing + // Unfortunately, due to mixed support, UA sniffing is required + // ========================================================================== + var browser = { + isIE: + /* @cc_on!@ */ + !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) + }; + + var defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora' + }; // Check for feature support + + var support = { + // Basic support + audio: 'canPlayType' in document.createElement('audio'), + video: 'canPlayType' in document.createElement('video'), + // Check for support + // Basic functionality vs full UI + check: function check(type, provider, playsinline) { + var canPlayInline = browser.isIPhone && playsinline && support.playsinline; + var api = support[type] || provider !== 'html5'; + var ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); + return { + api: api, + ui: ui + }; + }, + // Picture-in-picture support + // Safari & Chrome only currently + pip: function () { + if (browser.isIPhone) { + return false; + } // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls + + + if (is.function(createElement('video').webkitSetPresentationMode)) { + return true; + } // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture + + + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } + + return false; + }(), + // Airplay support + // Safari only currently + airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent), + // Inline playback support + // https://webkit.org/blog/6784/new-video-policies-for-ios/ + playsinline: 'playsInline' in document.createElement('video'), + // Check for mime type support against a player instance + // Credits: http://diveintohtml5.info/everything.html + // Related: http://www.leanbackplayer.com/test/h5mt.html + mime: function mime(input) { + if (is.empty(input)) { + return false; + } + + var _input$split = input.split('/'), + _input$split2 = _slicedToArray(_input$split, 1), + mediaType = _input$split2[0]; + + var type = input; // Verify we're using HTML5 and there's no media type mismatch + + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } // Add codec if required + + + if (Object.keys(defaultCodecs).includes(type)) { + type += "; codecs=\"".concat(defaultCodecs[input], "\""); + } + + try { + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); + } catch (e) { + return false; + } + }, + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), + // <input type="range"> Sliders + rangeInput: function () { + var range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; + }(), + // Touch + // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event + touch: 'ontouchstart' in document.documentElement, + // Detect transitions support + transitions: transitionEndEvent !== false, + // Reduced motion iOS & MacOS setting + // https://webkit.org/blog/7551/responsive-design-for-motion/ + reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches + }; + + // ========================================================================== + var html5 = { + getSources: function getSources() { + var _this = this; + + if (!this.isHTML5) { + return []; + } + + var sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified) + + return sources.filter(function (source) { + var type = source.getAttribute('type'); + + if (is.empty(type)) { + return true; + } + + return support.mime.call(_this, type); + }); + }, + // Get quality levels + getQualityOptions: function getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources.call(this).map(function (source) { + return Number(source.getAttribute('size')); + }).filter(Boolean); + }, + extend: function extend() { + if (!this.isHTML5) { + return; + } + + var player = this; // Quality + + Object.defineProperty(player.media, 'quality', { + get: function get() { + // Get sources + var sources = html5.getSources.call(player); + var source = sources.find(function (source) { + return source.getAttribute('src') === player.source; + }); // Return size, if match is found + + return source && Number(source.getAttribute('size')); + }, + set: function set(input) { + // Get sources + var sources = html5.getSources.call(player); // Get first match for requested size + + var source = sources.find(function (source) { + return Number(source.getAttribute('size')) === input; + }); // No matching source found + + if (!source) { + return; + } // Get current state + + + var _player$media = player.media, + currentTime = _player$media.currentTime, + paused = _player$media.paused, + preload = _player$media.preload, + readyState = _player$media.readyState; // Set new source + + player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044) + + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', function () { + player.currentTime = currentTime; // Resume playing + + if (!paused) { + player.play(); + } + }); // Load new source + + player.media.load(); + } // Trigger change event + + + triggerEvent.call(player, player.media, 'qualitychange', false, { + quality: input + }); + } + }); + }, + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests: function cancelRequests() { + if (!this.isHTML5) { + return; + } // Remove child sources + + + removeElement(html5.getSources.call(this)); // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + + this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + + this.media.load(); // Debugging + + this.debug.log('Cancelled network requests'); + } + }; + + // ========================================================================== + + function dedupe(array) { + if (!is.array(array)) { + return array; + } + + return array.filter(function (item, index) { + return array.indexOf(item) === index; + }); + } // Get the closest value in an array + + function closest(array, value) { + if (!is.array(array) || !array.length) { + return null; + } + + return array.reduce(function (prev, curr) { + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); + } + + function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); + } // Get a nested value in an object + + function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); + } // Deep extend destination object with N more objects + + function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + if (!sources.length) { + return target; + } + + var source = sources.shift(); + + if (!is.object(source)) { + return target; + } + + Object.keys(source).forEach(function (key) { + if (is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); + } + + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); + } + }); + return extend.apply(void 0, [target].concat(sources)); + } + + // ========================================================================== + + function generateId(prefix) { + return "".concat(prefix, "-").concat(Math.floor(Math.random() * 10000)); + } // Format string + + function format(input) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (is.empty(input)) { + return input; + } + + return input.toString().replace(/{(\d+)}/g, function (match, i) { + return args[i].toString(); + }); + } // Get percentage + + function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } + + return (current / max * 100).toFixed(2); + } // Replace all occurances of a string in a string + + function replaceAll() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); + } // Convert to title case + + function toTitleCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return input.toString().replace(/\w\S*/g, function (text) { + return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); + }); + } // Convert string to pascalCase + + function toPascalCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert kebab case + + string = replaceAll(string, '-', ' '); // Convert snake case + + string = replaceAll(string, '_', ' '); // Convert to title case + + string = toTitleCase(string); // Convert to pascal case + + return replaceAll(string, ' ', ''); + } // Convert string to pascalCase + + function toCamelCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert to pascal case + + string = toPascalCase(string); // Convert first character to lowercase + + return string.charAt(0).toLowerCase() + string.slice(1); + } // Remove HTML from a string + + function stripHTML(source) { + var fragment = document.createDocumentFragment(); + var element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; + } // Like outerHTML, but also works for DocumentFragment + + function getHTML(element) { + var wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; + } + + var resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube' + }; + var i18n = { + get: function get() { + var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (is.empty(key) || is.empty(config)) { + return ''; + } + + var string = getDeep(config.i18n, key); + + if (is.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; + } + + return ''; + } + + var replace = { + '{seektime}': config.seekTime, + '{title}': config.title + }; + Object.entries(replace).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + string = replaceAll(string, key, value); + }); + return string; + } + }; + + var Storage = + /*#__PURE__*/ + function () { + function Storage(player) { + _classCallCheck(this, Storage); + + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } // Check for actual support (see if we can use it) + + + _createClass(Storage, [{ + key: "get", + value: function get(key) { + if (!Storage.supported || !this.enabled) { + return null; + } + + var store = window.localStorage.getItem(this.key); + + if (is.empty(store)) { + return null; + } + + var json = JSON.parse(store); + return is.string(key) && key.length ? json[key] : json; + } + }, { + key: "set", + value: function set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } // Can only store objectst + + + if (!is.object(object)) { + return; + } // Get current storage + + + var storage = this.get(); // Default to empty object + + if (is.empty(storage)) { + storage = {}; + } // Update the working copy of the values + + + extend(storage, object); // Update storage + + window.localStorage.setItem(this.key, JSON.stringify(storage)); + } + }], [{ + key: "supported", + get: function get() { + try { + if (!('localStorage' in window)) { + return false; + } + + var test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 + + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + } + }]); + + return Storage; + }(); + + // ========================================================================== + // Fetch wrapper + // Using XHR to avoid issues with older browsers + // ========================================================================== + function fetch(url) { + var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + return new Promise(function (resolve, reject) { + try { + var request = new XMLHttpRequest(); // Check for CORS support + + if (!('withCredentials' in request)) { + return; + } + + request.addEventListener('load', function () { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); + request.addEventListener('error', function () { + throw new Error(request.status); + }); + request.open('GET', url, true); // Set the required response type + + request.responseType = responseType; + request.send(); + } catch (e) { + reject(e); + } + }); + } + + // ========================================================================== + + function loadSprite(url, id) { + if (!is.string(url)) { + return; + } + + var prefix = 'cache'; + var hasId = is.string(id); + var isCached = false; + + var exists = function exists() { + return document.getElementById(id) !== null; + }; + + var update = function update(container, data) { + container.innerHTML = data; // Check again incase of race condition + + if (hasId && exists()) { + return; + } // Inject the SVG to the body + + + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set + + + if (!hasId || !exists()) { + var useStorage = Storage.supported; // Create container + + var container = document.createElement('div'); + container.setAttribute('hidden', ''); + + if (hasId) { + container.setAttribute('id', id); + } // Check in cache + + + if (useStorage) { + var cached = window.localStorage.getItem("".concat(prefix, "-").concat(id)); + isCached = cached !== null; + + if (isCached) { + var data = JSON.parse(cached); + update(container, data.content); + } + } // Get the sprite + + + fetch(url).then(function (result) { + if (is.empty(result)) { + return; + } + + if (useStorage) { + window.localStorage.setItem("".concat(prefix, "-").concat(id), JSON.stringify({ + content: result + })); + } + + update(container, result); + }).catch(function () {}); + } + } + + // ========================================================================== + + var getHours = function getHours(value) { + return Math.trunc(value / 60 / 60 % 60, 10); + }; + var getMinutes = function getMinutes(value) { + return Math.trunc(value / 60 % 60, 10); + }; + var getSeconds = function getSeconds(value) { + return Math.trunc(value % 60, 10); + }; // Format time to UI friendly string + + function formatTime() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if the value isn't a number + if (!is.number(time)) { + return formatTime(null, displayHours, inverted); + } // Format time component to add leading zero + + + var format = function format(value) { + return "0".concat(value).slice(-2); + }; // Breakdown to hours, mins, secs + + + var hours = getHours(time); + var mins = getMinutes(time); + var secs = getSeconds(time); // Do we need to display hours? + + if (displayHours || hours > 0) { + hours = "".concat(hours, ":"); + } else { + hours = ''; + } // Render + + + return "".concat(inverted && time > 0 ? '-' : '').concat(hours).concat(format(mins), ":").concat(format(secs)); + } + + var controls = { + // Get icon URL + getIconUrl: function getIconUrl() { + var url = new URL(this.config.iconUrl, window.location); + var cors = url.host !== window.location.host || browser.isIE && !window.svg4everybody; + return { + url: this.config.iconUrl, + cors: cors + }; + }, + // Find the UI controls + findElements: function findElements() { + try { + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons + + this.elements.buttons = { + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen) + }; // Progress + + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs + + this.elements.inputs = { + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume) + }; // Display + + this.elements.display = { + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration) + }; // Seek tooltip + + if (is.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip)); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls + + this.toggleNativeControls(true); + return false; + } + }, + // Create <svg> icon + createIcon: function createIcon(type, attributes) { + var namespace = 'http://www.w3.org/2000/svg'; + var iconUrl = controls.getIconUrl.call(this); + var iconPath = "".concat(!iconUrl.cors ? iconUrl.url : '', "#").concat(this.config.iconPrefix); // Create <svg> + + var icon = document.createElementNS(namespace, 'svg'); + setAttributes(icon, extend(attributes, { + role: 'presentation', + focusable: 'false' + })); // Create the <use> to reference sprite + + var use = document.createElementNS(namespace, 'use'); + var path = "".concat(iconPath, "-").concat(type); // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href + + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } // Always set the older attribute even though it's "deprecated" (it'll be around for ages) + + + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg> + + icon.appendChild(use); + return icon; + }, + // Create hidden text label + createLabel: function createLabel(key) { + var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var text = i18n.get(key, this.config); + var attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') + }); + return createElement('span', attributes, text); + }, + // Create a badge + createBadge: function createBadge(text) { + if (is.empty(text)) { + return null; + } + + var badge = createElement('span', { + class: this.config.classNames.menu.value + }); + badge.appendChild(createElement('span', { + class: this.config.classNames.menu.badge + }, text)); + return badge; + }, + // Create a <button> + createButton: function createButton(buttonType, attr) { + var attributes = Object.assign({}, attr); + var type = toCamelCase(buttonType); + var props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null + }; + ['element', 'icon', 'label'].forEach(function (key) { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); // Default to 'button' type to prevent form submission + + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { + attributes.type = 'button'; + } // Set class name + + + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { + attributes.class += " ".concat(this.config.classNames.control); + } + } else { + attributes.class = this.config.classNames.control; + } // Large play button + + + switch (buttonType) { + case 'play': + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; + break; + + case 'mute': + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; + break; + + case 'captions': + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; + break; + + case 'fullscreen': + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; + break; + + case 'play-large': + attributes.class += " ".concat(this.config.classNames.control, "--overlaid"); + type = 'play'; + props.label = 'play'; + props.icon = 'play'; + break; + + default: + if (is.empty(props.label)) { + props.label = type; + } + + if (is.empty(props.icon)) { + props.icon = buttonType; + } + + } + + var button = createElement(props.element); // Setup toggle icon and labels + + if (props.toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed' + })); + button.appendChild(controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed' + })); // Label/Tooltip + + button.appendChild(controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed' + })); + button.appendChild(controls.createLabel.call(this, props.label, { + class: 'label--not-pressed' + })); + } else { + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); + } // Merge and set attributes + + + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons + + if (type === 'play') { + if (!is.array(this.elements.buttons[type])) { + this.elements.buttons[type] = []; + } + + this.elements.buttons[type].push(button); + } else { + this.elements.buttons[type] = button; + } + + return button; + }, + // Create an <input type='range'> + createRange: function createRange(type, attributes) { + // Seek input + var input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + // A11y fixes for https://github.com/sampotts/plyr/issues/905 + role: 'slider', + 'aria-label': i18n.get(type, this.config), + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'aria-valuenow': 0 + }, attributes)); + this.elements.inputs[type] = input; // Set the fill for webkit now + + controls.updateRangeFill.call(this, input); + return input; + }, + // Create a <progress> + createProgress: function createProgress(type, attributes) { + var progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), { + min: 0, + max: 100, + value: 0, + role: 'presentation', + 'aria-hidden': true + }, attributes)); // Create the label inside + + if (type !== 'volume') { + progress.appendChild(createElement('span', null, '0')); + var suffixKey = { + played: 'played', + buffer: 'buffered' + }[type]; + var suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; + progress.innerText = "% ".concat(suffix.toLowerCase()); + } + + this.elements.display[type] = progress; + return progress; + }, + // Create time display + createTime: function createTime(type) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + var container = createElement('div', extend(attributes, { + class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-label': i18n.get(type, this.config) + }), '00:00'); // Reference for updates + + this.elements.display[type] = container; + return container; + }, + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { + var _this = this; + + // Navigate through menus via arrow keys and space + on(menuItem, 'keydown keyup', function (event) { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } // Prevent play / seek + + + event.preventDefault(); + event.stopPropagation(); // We're just here to prevent the keydown bubbling + + if (event.type === 'keydown') { + return; + } + + var isRadioButton = matches(menuItem, '[role="menuitemradio"]'); // Show the respective menu + + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(_this, type, true); + } else { + var target; + + if (event.which !== 32) { + if (event.which === 40 || isRadioButton && event.which === 39) { + target = menuItem.nextElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.lastElementChild; + } + } + + setFocus.call(_this, target, true); + } + } + }, false); // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here + + on(menuItem, 'keyup', function (event) { + if (event.which !== 13) { + return; + } + + controls.focusFirstMenuItem.call(_this, null, true); + }); + }, + // Create a settings menu item + createMenuItem: function createMenuItem(_ref) { + var _this2 = this; + + var value = _ref.value, + list = _ref.list, + type = _ref.type, + title = _ref.title, + _ref$badge = _ref.badge, + badge = _ref$badge === void 0 ? null : _ref$badge, + _ref$checked = _ref.checked, + checked = _ref$checked === void 0 ? false : _ref$checked; + var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + var menuItem = createElement('button', extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: "".concat(this.config.classNames.control, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-checked': checked, + value: value + })); + var flex = createElement('span'); // We have to set as HTML incase of special characters + + flex.innerHTML = title; + + if (is.element(badge)) { + flex.appendChild(badge); + } + + menuItem.appendChild(flex); // Replicate radio button behaviour + + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get: function get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set: function set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children).filter(function (node) { + return matches(node, '[role="menuitemradio"]'); + }).forEach(function (node) { + return node.setAttribute('aria-checked', 'false'); + }); + } + + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + } + }); + this.listeners.bind(menuItem, 'click keyup', function (event) { + if (is.keyboardEvent(event) && event.which !== 32) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + menuItem.checked = true; + + switch (type) { + case 'language': + _this2.currentTrack = Number(value); + break; + + case 'quality': + _this2.quality = value; + break; + + case 'speed': + _this2.speed = parseFloat(value); + break; + + default: + break; + } + + controls.showMenuPanel.call(_this2, 'home', is.keyboardEvent(event)); + }, type, false); + controls.bindMenuItemShortcuts.call(this, menuItem, type); + list.appendChild(menuItem); + }, + // Format a time for display + formatTime: function formatTime$$1() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + // Bail if the value isn't a number + if (!is.number(time)) { + return time; + } // Always display hours if duration is over an hour + + + var forceHours = getHours(this.duration) > 0; + return formatTime(time, forceHours, inverted); + }, + // Update the displayed time + updateTimeDisplay: function updateTimeDisplay() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if there's no element to display or the value isn't a number + if (!is.element(target) || !is.number(time)) { + return; + } // eslint-disable-next-line no-param-reassign + + + target.innerText = controls.formatTime(time, inverted); + }, + // Update volume UI and storage + updateVolume: function updateVolume() { + if (!this.supported.ui) { + return; + } // Update range + + + if (is.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } // Update mute state + + + if (is.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } + }, + // Update seek value and lower fill + setRange: function setRange(target) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (!is.element(target)) { + return; + } // eslint-disable-next-line + + + target.value = value; // Webkit range fill + + controls.updateRangeFill.call(this, target); + }, + // Update <progress> elements + updateProgress: function updateProgress(event) { + var _this3 = this; + + if (!this.supported.ui || !is.event(event)) { + return; + } + + var value = 0; + + var setProgress = function setProgress(target, input) { + var value = is.number(input) ? input : 0; + var progress = is.element(target) ? target : _this3.elements.display.buffer; // Update value and label + + if (is.element(progress)) { + progress.value = value; // Update text label inside + + var label = progress.getElementsByTagName('span')[0]; + + if (is.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event + + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + // Check buffer status + + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + break; -}()); + default: + break; + } + } + }, + // Webkit polyfill for lower fill range + updateRangeFill: function updateRangeFill(target) { + // Get range from event if event passed + var range = is.event(target) ? target.target : target; // Needs to be a valid <input type='range'> + + if (!is.element(range) || range.getAttribute('type') !== 'range') { + return; + } // Set aria values for https://github.com/sampotts/plyr/issues/905 + + + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + var currentTime = controls.formatTime(this.currentTime); + var duration = controls.formatTime(this.duration); + var format$$1 = i18n.get('seekLabel', this.config); + range.setAttribute('aria-valuetext', format$$1.replace('{currentTime}', currentTime).replace('{duration}', duration)); + } else if (matches(range, this.config.selectors.inputs.volume)) { + var percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', "".concat(percent.toFixed(1), "%")); + } else { + range.setAttribute('aria-valuenow', range.value); + } // WebKit only + + + if (!browser.isWebkit) { + return; + } // Set CSS custom property + + + range.style.setProperty('--value', "".concat(range.value / range.max * 100, "%")); + }, + // Update hover tooltip for seeking + updateSeekTooltip: function updateSeekTooltip(event) { + var _this4 = this; + + // Bail if setting not true + if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) { + return; + } // Calculate percentage + + + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + var visible = "".concat(this.config.classNames.tooltip, "--visible"); + + var toggle = function toggle(_toggle) { + toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + }; // Hide on touch + + + if (this.touch) { + toggle(false); + return; + } // Determine percentage, if already visible + + + if (is.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } // Set bounds + + + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } // Display the time a click would seek to + + + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position + + this.elements.display.seekTooltip.style.left = "".concat(percent, "%"); // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds + + if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + toggle(event.type === 'mouseenter'); + } + }, + // Handle time change event + timeUpdate: function timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + var invert = !is.element(this.elements.display.duration) && this.config.invertTime; // Duration + + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking + + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } // Playing progress + + + controls.updateProgress.call(this, event); + }, + // Show the duration on metadataloaded or durationchange events + durationUpdate: function durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || !this.config.invertTime && this.currentTime) { + return; + } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 + + + if (this.duration >= Math.pow(2, 32)) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } // Update ARIA values + + + if (is.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); + } // If there's a spot to display duration + + + var hasDuration = is.element(this.elements.display.duration); // If there's only one time display, display duration there + + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } // If there's a duration element, update content + + + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } // Update the tooltip (if visible) + + + controls.updateSeekTooltip.call(this); + }, + // Hide/show a tab + toggleMenuButton: function toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); + }, + // Update the selected setting + updateSetting: function updateSetting(setting, container, input) { + var pane = this.elements.settings.panels[setting]; + var value = null; + var list = container; + + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is.empty(input) ? input : this[setting]; // Get default + + if (is.empty(value)) { + value = this.config[setting].default; + } // Unsupported value + + + if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn("Unsupported value of '".concat(value, "' for ").concat(setting)); + return; + } // Disabled value + + + if (!this.config[setting].options.includes(value)) { + this.debug.warn("Disabled value of '".concat(value, "' for ").concat(setting)); + return; + } + } // Get the list if we need to + + + if (!is.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } // If there's no list it means it's not been rendered... + + + if (!is.element(list)) { + return; + } // Update the label + + + var label = this.elements.settings.buttons[setting].querySelector(".".concat(this.config.classNames.menu.value)); + label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it + + var target = list && list.querySelector("[value=\"".concat(value, "\"]")); + + if (is.element(target)) { + target.checked = true; + } + }, + // Translate a value into a nice label + getLabel: function getLabel(setting, value) { + switch (setting) { + case 'speed': + return value === 1 ? i18n.get('normal', this.config) : "".concat(value, "×"); + + case 'quality': + if (is.number(value)) { + var label = i18n.get("qualityLabel.".concat(value), this.config); + + if (!label.length) { + return "".concat(value, "p"); + } + + return label; + } + + return toTitleCase(value); + + case 'captions': + return captions.getLabel.call(this); + + default: + return null; + } + }, + // Set the quality menu + setQualityMenu: function setQualityMenu(options) { + var _this5 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.quality)) { + return; + } + + var type = 'quality'; + var list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); // Set options if passed and filter based on uniqueness and config + + if (is.array(options)) { + this.options.quality = dedupe(options).filter(function (quality) { + return _this5.config.quality.options.includes(quality); + }); + } // Toggle the pane and tab + + + var toggle = !is.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Get the badge HTML for HD, 4K etc + + + var getBadge = function getBadge(quality) { + var label = i18n.get("qualityBadge.".concat(quality), _this5.config); + + if (!label.length) { + return null; + } + + return controls.createBadge.call(_this5, label); + }; // Sort options by the config and then render options + + + this.options.quality.sort(function (a, b) { + var sorting = _this5.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }).forEach(function (quality) { + controls.createMenuItem.call(_this5, { + value: quality, + list: list, + type: type, + title: controls.getLabel.call(_this5, 'quality', quality), + badge: getBadge(quality) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Set the looping options + + /* setLoopMenu() { + // Menu required + if (!is.element(this.elements.settings.panels.loop)) { + return; + } + const options = ['start', 'end', 'all', 'reset']; + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); + // Show the pane and tab + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); + // Toggle the pane and tab + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); + // Empty the menu + emptyElement(list); + options.forEach(option => { + const item = createElement('li'); + const button = createElement( + 'button', + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { + type: 'button', + class: this.config.classNames.control, + 'data-plyr-loop-action': option, + }), + i18n.get(option, this.config) + ); + if (['start', 'end'].includes(option)) { + const badge = controls.createBadge.call(this, '00:00'); + button.appendChild(badge); + } + item.appendChild(button); + list.appendChild(item); + }); + }, */ + // Get current selected caption language + // TODO: rework this to user the getter in the API? + // Set a list of available captions languages + setCaptionsMenu: function setCaptionsMenu() { + var _this6 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.captions)) { + return; + } // TODO: Captions or language? Currently it's mixed + + + var type = 'captions'; + var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + var tracks = captions.getTracks.call(this); + var toggle = Boolean(tracks.length); // Toggle the pane and tab + + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If there's no captions, bail + + if (!toggle) { + return; + } // Generate options data + + + var options = tracks.map(function (track, value) { + return { + value: value, + checked: _this6.captions.toggled && _this6.currentTrack === value, + title: captions.getLabel.call(_this6, track), + badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + list: list, + type: 'language' + }; + }); // Add the "Disabled" option to turn off captions + + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list: list, + type: 'language' + }); // Generate options + + options.forEach(controls.createMenuItem.bind(this)); + controls.updateSetting.call(this, type, list); + }, + // Set a list of available captions languages + setSpeedMenu: function setSpeedMenu(options) { + var _this7 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.speed)) { + return; + } + + var type = 'speed'; + var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options + + if (is.array(options)) { + this.options.speed = options; + } else if (this.isHTML5 || this.isVimeo) { + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + } // Set options if passed and filter based on config + + + this.options.speed = this.options.speed.filter(function (speed) { + return _this7.config.speed.options.includes(speed); + }); // Toggle the pane and tab + + var toggle = !is.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Create items + + + this.options.speed.forEach(function (speed) { + controls.createMenuItem.call(_this7, { + value: speed, + list: list, + type: type, + title: controls.getLabel.call(_this7, 'speed', speed) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Check if we need to hide/show the settings menu + checkMenu: function checkMenu() { + var buttons = this.elements.settings.buttons; + var visible = !is.empty(buttons) && Object.values(buttons).some(function (button) { + return !button.hidden; + }); + toggleHidden(this.elements.settings.menu, !visible); + }, + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem: function focusFirstMenuItem(pane) { + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (this.elements.settings.popup.hidden) { + return; + } + + var target = pane; + + if (!is.element(target)) { + target = Object.values(this.elements.settings.panels).find(function (pane) { + return !pane.hidden; + }); + } + + var firstItem = target.querySelector('[role^="menuitem"]'); + setFocus.call(this, firstItem, tabFocus); + }, + // Show/hide menu + toggleMenu: function toggleMenu(input) { + var popup = this.elements.settings.popup; + var button = this.elements.buttons.settings; // Menu and button are required + + if (!is.element(popup) || !is.element(button)) { + return; + } // True toggle by default + + + var hidden = popup.hidden; + var show = hidden; + + if (is.boolean(input)) { + show = input; + } else if (is.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is.event(input)) { + var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) + + if (isMenuItem || !isMenuItem && input.target !== button && show) { + return; + } + } // Set button attributes + + + button.setAttribute('aria-expanded', show); // Show the actual popup + + toggleHidden(popup, !show); // Add class hook + + toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction + + if (show && is.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is.keyboardEvent(input)); + } + }, + // Get the natural size of a menu panel + getMenuSize: function getMenuSize(tab) { + var clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.removeAttribute('hidden'); // Append to parent so we get the "real" size + + tab.parentNode.appendChild(clone); // Get the sizes before we remove + + var width = clone.scrollWidth; + var height = clone.scrollHeight; // Remove from the DOM + + removeElement(clone); + return { + width: width, + height: height + }; + }, + // Show a panel in the menu + showMenuPanel: function showMenuPanel() { + var _this8 = this; + + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail + + if (!is.element(target)) { + return; + } // Hide all other panels + + + var container = target.parentNode; + var current = Array.from(container.children).find(function (node) { + return !node.hidden; + }); // If we can do fancy animations, we'll animate the height/width + + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = "".concat(current.scrollWidth, "px"); + container.style.height = "".concat(current.scrollHeight, "px"); // Get potential sizes + + var size = controls.getMenuSize.call(this, target); // Restore auto height/width + + var restore = function restore(event) { + // We're only bothered about height and width on the container + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { + return; + } // Revert back to auto + + + container.style.width = ''; + container.style.height = ''; // Only listen once + + off.call(_this8, container, transitionEndEvent, restore); + }; // Listen for the transition finishing and restore auto height/width + + + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target + + container.style.width = "".concat(size.width, "px"); + container.style.height = "".concat(size.height, "px"); + } // Set attributes on current tab + + + toggleHidden(current, true); // Set attributes on target + + toggleHidden(target, false); // Focus the first item + + controls.focusFirstMenuItem.call(this, target, tabFocus); + }, + // Set the download link + setDownloadLink: function setDownloadLink() { + var button = this.elements.buttons.download; // Bail if no button + + if (!is.element(button)) { + return; + } // Set download link + + + button.setAttribute('href', this.download); + }, + // Build the default HTML + // TODO: Set order based on order in the config.controls array? + create: function create(data) { + var _this9 = this; + + // Create the container + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button + + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } // Rewind button + + + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } // Play/Pause button + + + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + } // Fast forward button + + + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } // Progress + + + if (this.config.controls.includes('progress')) { + var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider + + progress.appendChild(controls.createRange.call(this, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress + + progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip + + if (this.config.tooltips.seek) { + var tooltip = createElement('span', { + class: this.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; + } + + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } // Media current time display + + + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } // Media duration display + + + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } // Volume controls + + + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + var volume = createElement('div', { + class: 'plyr__volume' + }); // Toggle mute button + + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } // Volume range control + + + if (this.config.controls.includes('volume')) { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: this.config.volume + }; // Create the volume range slider + + volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + this.elements.volume = volume; + } + + container.appendChild(volume); + } // Toggle captions button + + + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } // Settings button / menu + + + if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + var control = createElement('div', { + class: 'plyr__menu', + hidden: '' + }); + control.appendChild(controls.createButton.call(this, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu + + var menu = createElement('div', { + role: 'menu' + }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; // Build the menu items + + this.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + controls.showMenuPanel.call(_this9, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this9.config)); + var value = createElement('span', { + class: _this9.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this9.config))); // Screen reader label + + backButton.appendChild(createElement('span', { + class: _this9.config.classNames.hidden + }, i18n.get('menuBack', _this9.config))); // Go back via keyboard + + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek + + + event.preventDefault(); + event.stopPropagation(); // Show the respective menu + + controls.showMenuPanel.call(_this9, 'home', true); + }, false); // Go back via button click + + on(backButton, 'click', function () { + controls.showMenuPanel.call(_this9, 'home', false); + }); // Add to pane + + pane.appendChild(backButton); // Menu + + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this9.elements.settings.buttons[type] = menuItem; + _this9.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); + this.elements.settings.popup = popup; + this.elements.settings.menu = control; + } // Picture in picture button + + + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } // Airplay button + + + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } // Download button + + + if (this.config.controls.includes('download')) { + var _attributes = { + element: 'a', + href: this.download, + target: '_blank' + }; + var download = this.config.urls.download; + + if (!is.url(download) && this.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(this.provider), + label: this.provider + }); + } + + container.appendChild(controls.createButton.call(this, 'download', _attributes)); + } // Toggle fullscreen button + + + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } // Larger overlaid play button + + + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } + + this.elements.controls = container; // Set available quality levels + + if (this.isHTML5) { + controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + } + + controls.setSpeedMenu.call(this); + return container; + }, + // Insert controls + inject: function inject() { + var _this10 = this; + + // Sprite + if (this.config.loadSprite) { + var icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX + + if (icon.cors) { + loadSprite(icon.url, 'sprite-plyr'); + } + } // Create a unique ID + + + this.id = Math.floor(Math.random() * 10000); // Null by default + + var container = null; + this.elements.controls = null; // Set template properties + + var props = { + id: this.id, + seektime: this.config.seekTime, + title: this.config.title + }; + var update = true; // If function, run it and use output + + if (is.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } // Convert falsy controls to empty array (primarily for empty strings) + + + if (!this.config.controls) { + this.config.controls = []; + } + + if (is.element(this.config.controls) || is.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option + container = this.config.controls; + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: captions.getLabel.call(this) // TODO: Looping + // loop: 'None', + + }); + update = false; + } // Replace props with their value + + + var replace = function replace(input) { + var result = input; + Object.entries(props).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + value = _ref3[1]; + + result = replaceAll(result, "{".concat(key, "}"), value); + }); + return result; + }; // Update markup + + + if (update) { + if (is.string(this.config.controls)) { + container = replace(container); + } else if (is.element(container)) { + container.innerHTML = replace(container.innerHTML); + } + } // Controls container + + + var target; // Inject to custom location + + if (is.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } // Inject into the container by default + + + if (!is.element(target)) { + target = this.elements.container; + } // Inject controls HTML (needs to be before captions, hence "afterbegin") + + + var insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be + + if (!is.element(this.elements.controls)) { + controls.findElements.call(this); + } // Add pressed property to buttons + + + if (!is.empty(this.elements.buttons)) { + var addProperty = function addProperty(button) { + var className = _this10.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get: function get() { + return hasClass(button, className); + }, + set: function set() { + var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + toggleClass(button, className, pressed); + } + }); + }; // Toggle classname when pressed property is set + + + Object.values(this.elements.buttons).filter(Boolean).forEach(function (button) { + if (is.array(button) || is.nodeList(button)) { + Array.from(button).filter(Boolean).forEach(addProperty); + } else { + addProperty(button); + } + }); + } // Edge sometimes doesn't finish the paint so force a repaint + + + if (browser.isEdge) { + repaint(target); + } // Setup tooltips + + + if (this.config.tooltips.controls) { + var _this$config = this.config, + classNames = _this$config.classNames, + selectors = _this$config.selectors; + var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); + var labels = getElements.call(this, selector); + Array.from(labels).forEach(function (label) { + toggleClass(label, _this10.config.classNames.hidden, false); + toggleClass(label, _this10.config.classNames.tooltip, true); + }); + } + } + }; + + /** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ + + function parseUrl$2(input) { + var safe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var url = input; + + if (safe) { + var parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } + + try { + return new URL(url); + } catch (e) { + return null; + } + } // Convert object to URLSearchParams + + function buildUrlParams(input) { + var params = new URLSearchParams(); + + if (is.object(input)) { + Object.entries(input).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + params.set(key, value); + }); + } + + return params; + } + + var captions = { + // Setup captions + setup: function setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } // Only Vimeo and HTML5 video supported at this point + + + if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { + // Clear menu and hide + if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + + return; + } // Inject the container + + + if (!is.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); + insertAfter(this.elements.captions, this.elements.wrapper); + } // Fix IE captions if CORS is used + // Fetch captions and inject as blobs instead (data URIs not supported!) + + + if (browser.isIE && window.URL) { + var elements = this.media.querySelectorAll('track'); + Array.from(elements).forEach(function (track) { + var src = track.getAttribute('src'); + var url = parseUrl$2(src); + + if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + fetch(src, 'blob').then(function (blob) { + track.setAttribute('src', window.URL.createObjectURL(blob)); + }).catch(function () { + removeElement(track); + }); + } + }); + } // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state + + + var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + var languages = dedupe(browserLanguages.map(function (language) { + return language.split('-')[0]; + })); + var language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto' + + if (language === 'auto') { + var _languages = _slicedToArray(languages, 1); + + language = _languages[0]; + } + + var active = this.storage.get('captions'); + + if (!is.boolean(active)) { + active = this.config.captions.active; + } + + Object.assign(this.captions, { + toggled: false, + active: active, + language: language, + languages: languages + }); // Watch changes to textTracks and update captions menu + + if (this.isHTML5) { + var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); + } // Update available languages in list next tick (the event must not be triggered before the listeners) + + + setTimeout(captions.update.bind(this), 0); + }, + // Update available language options in settings based on tracks + update: function update() { + var _this = this; + + var tracks = captions.getTracks.call(this, true); // Get the wanted language + + var _this$captions = this.captions, + active = _this$captions.active, + language = _this$captions.language, + meta = _this$captions.meta, + currentTrackNode = _this$captions.currentTrackNode; + var languageExists = Boolean(tracks.find(function (track) { + return track.language === language; + })); // Handle tracks (add event listener and "pseudo"-default) + + if (this.isHTML5 && this.isVideo) { + tracks.filter(function (track) { + return !meta.get(track); + }).forEach(function (track) { + _this.debug.log('Track added', track); // Attempt to store if the original dom element was "default" + + + meta.set(track, { + default: track.mode === 'showing' + }); // Turn off native caption rendering to avoid double captions + + track.mode = 'hidden'; // Add event listener for cue changes + + on.call(_this, track, 'cuechange', function () { + return captions.updateCues.call(_this); + }); + }); + } // Update language first time it matches, or if the previous matching track was removed + + + if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } // Enable or disable captions based on track length + + + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks)); // Update available languages in list + + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + }, + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle: function toggle(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // If there's no full support + if (!this.supported.ui) { + return; + } + + var toggled = this.captions.toggled; // Current state + + var activeClass = this.config.classNames.captions.active; // Get the next state + // If the method is called without parameter, toggle based on current value + + var active = is.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event + + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ + captions: active + }); + } // Force language if the call isn't passive and there is no matching language to toggle to + + + if (!this.language && active && !passive) { + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [this.captions.language].concat(_toConsumableArray(this.captions.languages)), true); // Override user preferences to avoid switching languages if a matching track is added + + this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference + + captions.set.call(this, tracks.indexOf(track)); + return; + } // Toggle button if it's enabled + + + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } // Add class hook + + + toggleClass(this.elements.container, activeClass, active); + this.captions.toggled = active; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) + + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } + }, + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set: function set(index) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var tracks = captions.getTracks.call(this); // Disable captions if setting to -1 + + if (index === -1) { + captions.toggle.call(this, false, passive); + return; + } + + if (!is.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } + + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; + } + + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + var track = tracks[index]; + + var _ref = track || {}, + language = _ref.language; // Store reference to node for invalidation on remove + + + this.captions.currentTrackNode = track; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences + + if (!passive) { + this.captions.language = language; + this.storage.set({ + language: language + }); + } // Handle Vimeo captions + + + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } // Trigger event + + + triggerEvent.call(this, this.media, 'languagechange'); + } // Show captions + + + captions.toggle.call(this, true, passive); + + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } + }, + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage: function setLanguage(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (!is.string(input)) { + this.debug.warn('Invalid language argument', input); + return; + } // Normalize + + + var language = input.toLowerCase(); + this.captions.language = language; // Set currentTrack + + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks: function getTracks() { + var _this2 = this; + + var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + // Handle media or textTracks missing or null + var tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + + return tracks.filter(function (track) { + return !_this2.isHTML5 || update || _this2.captions.meta.has(track); + }).filter(function (track) { + return ['captions', 'subtitles'].includes(track.kind); + }); + }, + // Match tracks based on languages and get the first + findTrack: function findTrack(languages) { + var _this3 = this; + + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var tracks = captions.getTracks.call(this); + + var sortIsDefault = function sortIsDefault(track) { + return Number((_this3.captions.meta.get(track) || {}).default); + }; + + var sorted = Array.from(tracks).sort(function (a, b) { + return sortIsDefault(b) - sortIsDefault(a); + }); + var track; + languages.every(function (language) { + track = sorted.find(function (track) { + return track.language === language; + }); + return !track; // Break iteration if there is a match + }); // If no match is found but is required, get first + + return track || (force ? sorted[0] : undefined); + }, + // Get the current track + getCurrentTrack: function getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; + }, + // Get UI label for track + getLabel: function getLabel(track) { + var currentTrack = track; + + if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) { + currentTrack = captions.getCurrentTrack.call(this); + } + + if (is.track(currentTrack)) { + if (!is.empty(currentTrack.label)) { + return currentTrack.label; + } + + if (!is.empty(currentTrack.language)) { + return track.language.toUpperCase(); + } + + return i18n.get('enabled', this.config); + } + + return i18n.get('disabled', this.config); + }, + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues: function updateCues(input) { + // Requires UI + if (!this.supported.ui) { + return; + } + + if (!is.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; + } // Only accept array or empty input + + + if (!is.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); + return; + } + + var cues = input; // Get cues from track + + if (!cues) { + var track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []).map(function (cue) { + return cue.getCueAsHTML(); + }).map(getHTML); + } // Set new caption text + + + var content = cues.map(function (cueText) { + return cueText.trim(); + }).join('\n'); + var changed = content !== this.elements.captions.innerHTML; + + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + var caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); // Trigger event + + triggerEvent.call(this, this.media, 'cuechange'); + } + } + }; + + // ========================================================================== + // Plyr default config + // ========================================================================== + var defaults = { + // Disable + enabled: true, + // Custom media title + title: '', + // Logging to console + debug: false, + // Auto play (if supported) + autoplay: false, + // Only allow one media playing at once (vimeo only) + autopause: true, + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, + // Default time to skip when rewind/fast forward + seekTime: 10, + // Default volume + volume: 1, + muted: false, + // Pass a custom duration + duration: null, + // Display the media duration on load in the current time position + // If you have opted to display both duration and currentTime, this is ignored + displayDuration: true, + // Invert the current time to be a countdown + invertTime: true, + // Clicking the currentTime inverts it's value to show time left rather than elapsed + toggleInvert: true, + // Aspect ratio (for embeds) + ratio: '16:9', + // Click video container to play/pause + clickToPlay: true, + // Auto hide the controls + hideControls: true, + // Reset to start when playback ended + resetOnEnd: false, + // Disable the standard context menu + disableContextMenu: true, + // Sprite (for icons) + loadSprite: true, + iconPrefix: 'plyr', + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', + // Blank video (used to prevent errors on source change) + blankVideo: 'https://cdn.plyr.io/static/blank.mp4', + // Quality default + quality: { + default: 576, + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] + }, + // Set loops + loop: { + active: false // start: null, + // end: null, + + }, + // Speed default and options to display + speed: { + selected: 1, + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] + }, + // Keyboard shortcut settings + keyboard: { + focused: true, + global: false + }, + // Display tooltips + tooltips: { + controls: false, + seek: true + }, + // Captions settings + captions: { + active: false, + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false + }, + // Fullscreen settings + fullscreen: { + enabled: true, + // Allow fullscreen? + fallback: true, + // Fallback using full viewport/window + iosNative: false // Use the native fullscreen in iOS (disables custom controls) + + }, + // Local storage + storage: { + enabled: true, + key: 'plyr' + }, + // Default controls + controls: ['play-large', // 'restart', + // 'rewind', + 'play', // 'fast-forward', + 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download', + 'fullscreen'], + settings: ['captions', 'quality', 'speed'], + // Localisation + i18n: { + restart: 'Restart', + rewind: 'Rewind {seektime}s', + play: 'Play', + pause: 'Pause', + fastForward: 'Forward {seektime}s', + seek: 'Seek', + seekLabel: '{currentTime} of {duration}', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + download: 'Download', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + menuBack: 'Go back to previous menu', + speed: 'Speed', + normal: 'Normal', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + disabled: 'Disabled', + enabled: 'Enabled', + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } + }, + // URLs + urls: { + download: null, + vimeo: { + sdk: 'https://player.vimeo.com/api/player.js', + iframe: 'https://player.vimeo.com/video/{0}?{1}', + api: 'https://vimeo.com/api/v2/video/{0}.json' + }, + youtube: { + sdk: 'https://www.youtube.com/iframe_api', + api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + }, + googleIMA: { + sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' + } + }, + // Custom control listeners + listeners: { + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + fastForward: null, + mute: null, + volume: null, + captions: null, + download: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null + }, + // Events to watch and bubble + events: [// Events to watch on HTML5 media elements and bubble + // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events + 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube + 'statechange', // Quality + 'qualitychange', // Ads + 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], + // Selectors + // Change these to match your template if using custom HTML + selectors: { + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls' + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + fastForward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]' + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]' + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', + // Used later + volume: '.plyr__volume--display' + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + caption: '.plyr__caption', + menu: { + quality: '.js-plyr__menu__list--quality' + } + }, + // Class hooks added to the player in different states + classNames: { + type: 'plyr--{0}', + provider: 'plyr--{0}', + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + embedContainer: 'plyr__video-embed__container', + poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', + ads: 'plyr__ads', + control: 'plyr__control', + controlPressed: 'plyr__control--pressed', + playing: 'plyr--playing', + paused: 'plyr--paused', + stopped: 'plyr--stopped', + loading: 'plyr--loading', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + cues: 'plyr__cues', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time' + }, + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open' + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active' + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback' + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active' + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active' + }, + tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' + } + }, + // Embed attributes + attributes: { + embed: { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id' + } + }, + // API keys + keys: { + google: null + }, + // Advertisements plugin + // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio + ads: { + enabled: false, + publisherId: '', + tagUrl: '' + }, + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '' + }, + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false + }, + // YouTube plugin + youtube: { + noCookie: false, + // Whether to use an alternative version of YouTube without cookies + rel: 0, + // No related vids + showinfo: 0, + // Hide info + iv_load_policy: 3, + // Hide annotations + modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) + + } + }; + + // ========================================================================== + // Plyr states + // ========================================================================== + var pip = { + active: 'picture-in-picture', + inactive: 'inline' + }; + + // ========================================================================== + // Plyr supported types and providers + // ========================================================================== + var providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo' + }; + var types = { + audio: 'audio', + video: 'video' + }; + /** + * Get provider by URL + * @param {String} url + */ + + function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } // Vimeo + + + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; + } + + return null; + } + + // ========================================================================== + // Console wrapper + // ========================================================================== + var noop = function noop() {}; + + var Console = + /*#__PURE__*/ + function () { + function Console() { + var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + _classCallCheck(this, Console); + + this.enabled = window.console && enabled; + + if (this.enabled) { + this.log('Debugging enabled'); + } + } + + _createClass(Console, [{ + key: "log", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + }, { + key: "warn", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + }, { + key: "error", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } + }]); + + return Console; + }(); + + function onChange() { + if (!this.enabled) { + return; + } // Update toggle button + + + var button = this.player.elements.buttons.fullscreen; + + if (is.element(button)) { + button.pressed = this.active; + } // Trigger an event + + + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container + + if (!browser.isIos) { + trapFocus.call(this.player, this.target, this.active); + } + } + + function toggleFallback() { + var _this = this; + + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + // Store or restore scroll position + if (toggle) { + this.scrollPosition = { + x: window.scrollX || 0, + y: window.scrollY || 0 + }; + } else { + window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + } // Toggle scroll + + + document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook + + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+ + + if (browser.isIos) { + var viewport = document.head.querySelector('meta[name="viewport"]'); + var property = 'viewport-fit=cover'; // Inject the viewport meta if required + + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } // Check if the property already exists + + + var hasProperty = is.string(viewport.content) && viewport.content.includes(property); + + if (toggle) { + this.cleanupViewport = !hasProperty; + + if (!hasProperty) { + viewport.content += ",".concat(property); + } + } else if (this.cleanupViewport) { + viewport.content = viewport.content.split(',').filter(function (part) { + return part.trim() !== property; + }).join(','); + } // Force a repaint as sometimes Safari doesn't want to fill the screen + + + setTimeout(function () { + return repaint(_this.target); + }, 100); + } // Toggle button and fire events + + + onChange.call(this); + } + + var Fullscreen = + /*#__PURE__*/ + function () { + function Fullscreen(player) { + var _this2 = this; + + _classCallCheck(this, Fullscreen); + + // Keep reference to parent + this.player = player; // Get prefix + + this.prefix = Fullscreen.prefix; + this.property = Fullscreen.property; // Scroll position + + this.scrollPosition = { + x: 0, + y: 0 + }; // Force the use of 'full window/browser' rather than fullscreen + + this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners + // Handle event (incase user presses escape etc) + + on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { + // TODO: Filter for target?? + onChange.call(_this2); + }); // Fullscreen toggle on double click + + on.call(this.player, this.player.elements.container, 'dblclick', function (event) { + // Ignore double click in controls + if (is.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) { + return; + } + + _this2.toggle(); + }); // Update the UI + + this.update(); + } // Determine if native supported + + + _createClass(Fullscreen, [{ + key: "update", + // Update UI + value: function update() { + if (this.enabled) { + var mode; + + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } + + this.player.debug.log("".concat(mode, " fullscreen enabled")); + } else { + this.player.debug.log('Fullscreen not supported and fallback disabled'); + } // Add styling hook to show button + + + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + } // Make an element fullscreen + + }, { + key: "enter", + value: function enter() { + if (!this.enabled) { + return; + } // iOS native fullscreen doesn't need the request step + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, true); + } else if (!this.prefix) { + this.target.requestFullscreen(); + } else if (!is.empty(this.prefix)) { + this.target["".concat(this.prefix, "Request").concat(this.property)](); + } + } // Bail from fullscreen + + }, { + key: "exit", + value: function exit() { + if (!this.enabled) { + return; + } // iOS native fullscreen + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitExitFullscreen(); + this.player.play(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, false); + } else if (!this.prefix) { + (document.cancelFullScreen || document.exitFullscreen).call(document); + } else if (!is.empty(this.prefix)) { + var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; + document["".concat(this.prefix).concat(action).concat(this.property)](); + } + } // Toggle state + + }, { + key: "toggle", + value: function toggle() { + if (!this.active) { + this.enter(); + } else { + this.exit(); + } + } + }, { + key: "usingNative", + // If we're actually using native + get: function get() { + return Fullscreen.native && !this.forceFallback; + } // Get the prefix for handlers + + }, { + key: "enabled", + // Determine if fullscreen is enabled + get: function get() { + return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + } // Get active state + + }, { + key: "active", + get: function get() { + if (!this.enabled) { + return false; + } // Fallback using classname + + + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + } + + var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; + return element === this.target; + } // Get target element + + }, { + key: "target", + get: function get() { + return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + } + }], [{ + key: "native", + get: function get() { + return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + } + }, { + key: "prefix", + get: function get() { + // No prefix + if (is.function(document.exitFullscreen)) { + return ''; + } // Check for fullscreen support by vendor prefix + + + var value = ''; + var prefixes = ['webkit', 'moz', 'ms']; + prefixes.some(function (pre) { + if (is.function(document["".concat(pre, "ExitFullscreen")]) || is.function(document["".concat(pre, "CancelFullScreen")])) { + value = pre; + return true; + } + + return false; + }); + return value; + } + }, { + key: "property", + get: function get() { + return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + } + }]); + + return Fullscreen; + }(); + + // ========================================================================== + // Load image avoiding xhr/fetch CORS issues + // Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded + // By default it checks if it is at least 1px, but you can add a second argument to change this + // ========================================================================== + function loadImage(src) { + var minWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return new Promise(function (resolve, reject) { + var image = new Image(); + + var handler = function handler() { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { + onload: handler, + onerror: handler, + src: src + }); + }); + } + + // ========================================================================== + var ui = { + addStyleHook: function addStyleHook() { + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + }, + // Toggle native HTML5 media controls + toggleNativeControls: function toggleNativeControls() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + // Setup the UI + build: function build() { + var _this = this; + + // Re-attach media element listeners + // TODO: Use event bubbling? + this.listeners.media(); // Don't setup interface if no support + + if (!this.supported.ui) { + this.debug.warn("Basic support only for ".concat(this.provider, " ").concat(this.type)); // Restore native controls + + ui.toggleNativeControls.call(this, true); // Bail + + return; + } // Inject custom controls if not present + + + if (!is.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); // Re-attach control listeners + + this.listeners.controls(); + } // Remove native controls + + + ui.toggleNativeControls.call(this); // Setup captions for HTML5 + + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume + + + this.volume = null; // Reset mute state + + this.muted = null; // Reset speed + + this.speed = null; // Reset loop state + + this.loop = null; // Reset quality setting + + this.quality = null; // Reset volume display + + controls.updateVolume.call(this); // Reset time display + + controls.timeUpdate.call(this); // Update the UI + + ui.checkPlaying.call(this); // Check for picture-in-picture support + + toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support + + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class + + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class + + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls + + this.ready = true; // Ready event at end of execution stack + + setTimeout(function () { + triggerEvent.call(_this, _this.media, 'ready'); + }, 0); // Set the title + + ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created + + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(function () {}); + } // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + + + if (this.config.duration) { + controls.durationUpdate.call(this); + } + }, + // Setup aria attribute for play and iframe title + setTitle: function setTitle() { + // Find the current text + var label = i18n.get('play', this.config); // If there's a media title set, use that for the label + + if (is.string(this.config.title) && !is.empty(this.config.title)) { + label += ", ".concat(this.config.title); + } // If there's a play button, set label + + + Array.from(this.elements.buttons.play || []).forEach(function (button) { + button.setAttribute('aria-label', label); + }); // Set iframe title + // https://github.com/sampotts/plyr/issues/124 + + if (this.isEmbed) { + var iframe = getElement.call(this, 'iframe'); + + if (!is.element(iframe)) { + return; + } // Default to media type + + + var title = !is.empty(this.config.title) ? this.config.title : 'video'; + var format = i18n.get('frameTitle', this.config); + iframe.setAttribute('title', format.replace('{title}', title)); + } + }, + // Toggle poster + togglePoster: function togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster: function setPoster(poster) { + var _this2 = this; + + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); + } // Set property synchronously to respect the call order + + + this.media.setAttribute('poster', poster); // Wait until ui is ready + + return ready.call(this) // Load image + .then(function () { + return loadImage(poster); + }).catch(function (err) { + // Hide poster on error unless it's been set by another call + if (poster === _this2.poster) { + ui.togglePoster.call(_this2, false); + } // Rethrow + + + throw err; + }).then(function () { + // Prevent race conditions + if (poster !== _this2.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }).then(function () { + Object.assign(_this2.elements.poster.style, { + backgroundImage: "url('".concat(poster, "')"), + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '' + }); + ui.togglePoster.call(_this2, true); + return poster; + }); + }, + // Check playing state + checkPlaying: function checkPlaying(event) { + var _this3 = this; + + // Class hooks + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state + + Array.from(this.elements.buttons.play || []).forEach(function (target) { + target.pressed = _this3.playing; + }); // Only update controls on non timeupdate events + + if (is.event(event) && event.type === 'timeupdate') { + return; + } // Toggle controls + + + ui.toggleControls.call(this); + }, + // Check if media is loading + checkLoading: function checkLoading(event) { + var _this4 = this; + + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer + + clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking + + this.timers.loading = setTimeout(function () { + // Update progress bar loading class state + toggleClass(_this4.elements.container, _this4.config.classNames.loading, _this4.loading); // Update controls visibility + + ui.toggleControls.call(_this4); + }, this.loading ? 250 : 0); + }, + // Toggle controls based on state and `force` argument + toggleControls: function toggleControls(force) { + var controls$$1 = this.elements.controls; + + if (controls$$1 && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide + + this.toggleControls(Boolean(force || this.loading || this.paused || controls$$1.pressed || controls$$1.hover || recentTouchSeek)); + } + } + }; + + /* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; + } */ + // Set aspect ratio for responsive container + + function setAspectRatio(input) { + var ratio = input; + + if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { + ratio = this.embed.ratio; + } + + if (!is.string(ratio)) { + ratio = this.config.ratio; + } + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + x = _ratio$split$map2[0], + y = _ratio$split$map2[1]; + + var padding = 100 / x * y; + this.elements.wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI + + if (this.isVimeo && this.supported.ui) { + var height = 240; + var offset = (height - padding) / (height / 50); + this.media.style.transform = "translateY(-".concat(offset, "%)"); + } + + return { + padding: padding, + ratio: ratio + }; + } + + var Listeners = + /*#__PURE__*/ + function () { + function Listeners(player) { + _classCallCheck(this, Listeners); + + this.player = player; + this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; + this.handleKey = this.handleKey.bind(this); + this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); + this.firstTouch = this.firstTouch.bind(this); + } // Handle key presses + + + _createClass(Listeners, [{ + key: "handleKey", + value: function handleKey(event) { + var player = this.player; + var elements = player.elements; + var code = event.keyCode ? event.keyCode : event.which; + var pressed = event.type === 'keydown'; + var repeat = pressed && code === this.lastKey; // Bail if a modifier key is set + + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason + + + if (!is.number(code)) { + return; + } // Seek by the number keys + + + var seekByKey = function seekByKey() { + // Divide the max duration into 10th's and times by the number value + player.currentTime = player.duration / 10 * (code - 48); + }; // Handle the key on keydown + // Reset on keyup + + + if (pressed) { + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + var focused = document.activeElement; + + if (is.element(focused)) { + var editable = player.config.selectors.editable; + var seek = elements.inputs.seek; + + if (focused !== seek && matches(focused, editable)) { + return; + } + + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } + } // Which keycodes should we prevent default + + + var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows) + + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } + + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + player.togglePlay(); + } + + break; + + case 38: + // Arrow up + player.increaseVolume(0.1); + break; + + case 40: + // Arrow down + player.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + player.muted = !player.muted; + } + + break; + + case 39: + // Arrow forward + player.forward(); + break; + + case 37: + // Arrow back + player.rewind(); + break; + + case 70: + // F key + player.fullscreen.toggle(); + break; + + case 67: + // C key + if (!repeat) { + player.toggleCaptions(); + } + + break; + + case 76: + // L key + player.loop = !player.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ + + default: + break; + } // Escape is handle natively when in full screen + // So we only need to worry about non native + + + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); + } // Store last code for next cycle + + + this.lastKey = code; + } else { + this.lastKey = null; + } + } // Toggle menu + + }, { + key: "toggleMenu", + value: function toggleMenu(event) { + controls.toggleMenu.call(this.player, event); + } // Device is touch enabled + + }, { + key: "firstTouch", + value: function firstTouch() { + var player = this.player; + var elements = player.elements; + player.touch = true; // Add touch class + + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + }, { + key: "setTabFocus", + value: function setTabFocus(event) { + var player = this.player; + var elements = player.elements; + clearTimeout(this.focusTimer); // Ignore any key other than tab + + if (event.type === 'keydown' && event.which !== 9) { + return; + } // Store reference to event timeStamp + + + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } // Remove current classes + + + var removeCurrent = function removeCurrent() { + var className = player.config.classNames.tabFocus; + var current = getElements.call(player, ".".concat(className)); + toggleClass(current, className, false); + }; // Determine if a key was pressed to trigger this event + + + var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior + + if (event.type === 'focus' && !wasKeyDown) { + return; + } // Remove all current + + + removeCurrent(); // Delay the adding of classname until the focus has changed + // This event fires before the focusin event -//# sourceMappingURL=demo.js.map + this.focusTimer = setTimeout(function () { + var focused = document.activeElement; // Ignore if current focus element isn't inside the player + + if (!elements.container.contains(focused)) { + return; + } + + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); + } // Global window & document listeners + + }, { + key: "global", + value: function global() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var player = this.player; // Keyboard shortcuts + + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); + } // Click anywhere closes menu + + + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events + + once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection + + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); + } // Container listeners + + }, { + key: "container", + value: function container() { + var player = this.player; + var config = player.config, + elements = player.elements, + timers = player.timers; // Keyboard shortcuts + + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); + } // Toggle controls on mouse events and entering fullscreen + + + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen + + if (controls$$1 && event.type === 'enterfullscreen') { + controls$$1.pressed = false; + controls$$1.hover = false; + } // Show, then hide after a timeout unless another control event occurs + + + var show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + var delay = 0; + + if (show) { + ui.toggleControls.call(player, true); // Use longer timeout for touch devices + + delay = player.touch ? 3000 : 2000; + } // Clear timer + + + clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen + + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); + }); + } */ + // Set a gutter for Vimeo + + var setGutter = function setGutter(ratio, padding, toggle) { + if (!player.isVimeo) { + return; + } + + var target = player.elements.wrapper.firstChild; + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + height = _ratio$split$map2[1]; + + var _player$embed$ratio$s = player.embed.ratio.split(':').map(Number), + _player$embed$ratio$s2 = _slicedToArray(_player$embed$ratio$s, 2), + videoWidth = _player$embed$ratio$s2[0], + videoHeight = _player$embed$ratio$s2[1]; + + target.style.maxWidth = toggle ? "".concat(height / videoHeight * videoWidth, "px") : null; + target.style.margin = toggle ? '0 auto' : null; + }; // Resize on fullscreen change + + + var setPlayerSize = function setPlayerSize(measure) { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } + + var rect = elements.container.getBoundingClientRect(); + var width = rect.width, + height = rect.height; + return setAspectRatio.call(player, "".concat(width, ":").concat(height)); + }; + + var resized = function resized() { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; + + on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) { + var _player$fullscreen = player.fullscreen, + target = _player$fullscreen.target, + usingNative = _player$fullscreen.usingNative; // Ignore for iOS native + + if (!player.isEmbed || target !== elements.container) { + return; + } + + var isEnter = event.type === 'enterfullscreen'; // Set the player size when entering fullscreen to viewport size + + var _setPlayerSize = setPlayerSize(isEnter), + padding = _setPlayerSize.padding, + ratio = _setPlayerSize.ratio; // Set Vimeo gutter + + + setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport + + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); + } + } + }); + } // Listen for media events + + }, { + key: "media", + value: function media() { + var _this = this; + + var player = this.player; + var elements = player.elements; // Time change on media + + on.call(player, player.media, 'timeupdate seeking seeked', function (event) { + return controls.timeUpdate.call(player, event); + }); // Display duration + + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) { + return controls.durationUpdate.call(player, event); + }); // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point + + on.call(player, player.media, 'canplay loadeddata', function () { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); + }); // Handle the media finishing + + on.call(player, player.media, 'ended', function () { + // Show poster on end + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { + // Restart + player.restart(); + } + }); // Check for buffer progress + + on.call(player, player.media, 'progress playing seeking seeked', function (event) { + return controls.updateProgress.call(player, event); + }); // Handle volume changes + + on.call(player, player.media, 'volumechange', function (event) { + return controls.updateVolume.call(player, event); + }); // Handle play/pause + + on.call(player, player.media, 'playing play pause ended emptied timeupdate', function (event) { + return ui.checkPlaying.call(player, event); + }); // Loading state + + on.call(player, player.media, 'waiting canplay seeked playing', function (event) { + return ui.checkLoading.call(player, event); + }); // If autoplay, then load advertisement if required + // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows + + on.call(player, player.media, 'playing', function () { + if (!player.ads) { + return; + } // If ads are enabled, wait for them first + + + if (player.ads.enabled && !player.ads.initialized) { + // Wait for manager response + player.ads.managerPromise.then(function () { + return player.ads.play(); + }).catch(function () { + return player.play(); + }); + } + }); // Click video + + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { + // Re-fetch the wrapper + var wrapper = getElement.call(player, ".".concat(player.config.classNames.video)); // Bail if there's no wrapper (this should never happen) + + if (!is.element(wrapper)) { + return; + } // On click play, pause or restart + + + on.call(player, elements.container, 'click', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper + + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } // Touch devices will just show controls (if hidden) + + + if (player.touch && player.config.hideControls) { + return; + } + + if (player.ended) { + _this.proxy(event, player.restart, 'restart'); + + _this.proxy(event, player.play, 'play'); + } else { + _this.proxy(event, player.togglePlay, 'play'); + } + }); + } // Disable right click + + + if (player.supported.ui && player.config.disableContextMenu) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { + event.preventDefault(); + }, false); + } // Volume change + + + on.call(player, player.media, 'volumechange', function () { + // Save to storage + player.storage.set({ + volume: player.volume, + muted: player.muted + }); + }); // Speed change + + on.call(player, player.media, 'ratechange', function () { + // Update UI + controls.updateSetting.call(player, 'speed'); // Save to storage + + + player.storage.set({ + speed: player.speed + }); + }); // Quality change + + on.call(player, player.media, 'qualitychange', function (event) { + // Update UI + controls.updateSetting.call(player, 'quality', null, event.detail.quality); + }); // Update download link when ready and if quality changes + + on.call(player, player.media, 'ready qualitychange', function () { + controls.setDownloadLink.call(player); + }); // Proxy events to container + // Bubble up key events for Edge + + var proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + on.call(player, player.media, proxyEvents, function (event) { + var _event$detail = event.detail, + detail = _event$detail === void 0 ? {} : _event$detail; // Get error details from media + + if (event.type === 'error') { + detail = player.media.error; + } + + triggerEvent.call(player, elements.container, event.type, true, detail); + }); + } // Run default and custom handlers + + }, { + key: "proxy", + value: function proxy(event, defaultHandler, customHandlerKey) { + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + var returned = true; // Execute custom handler + + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } // Only call default handler if not prevented in custom handler + + + if (returned && is.function(defaultHandler)) { + defaultHandler.call(player, event); + } + } // Trigger custom and default handlers + + }, { + key: "bind", + value: function bind(element, type, defaultHandler, customHandlerKey) { + var _this2 = this; + + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + on.call(player, element, type, function (event) { + return _this2.proxy(event, defaultHandler, customHandlerKey); + }, passive && !hasCustomHandler); + } // Listen for control events + + }, { + key: "controls", + value: function controls$$1() { + var _this3 = this; + + var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change + + var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle + + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { + _this3.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause + + + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind + + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind + + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle + + this.bind(elements.buttons.mute, 'click', function () { + player.muted = !player.muted; + }, 'mute'); // Captions toggle + + this.bind(elements.buttons.captions, 'click', function () { + return player.toggleCaptions(); + }); // Download + + this.bind(elements.buttons.download, 'click', function () { + triggerEvent.call(player, player.media, 'download'); + }, 'download'); // Fullscreen toggle + + this.bind(elements.buttons.fullscreen, 'click', function () { + player.fullscreen.toggle(); + }, 'fullscreen'); // Picture-in-Picture + + this.bind(elements.buttons.pip, 'click', function () { + player.pip = 'toggle'; + }, 'pip'); // Airplay + + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle + + this.bind(elements.buttons.settings, 'click', function (event) { + // Prevent the document click listener closing the menu + event.stopPropagation(); + + controls.toggleMenu.call(player, event); + }); // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + + this.bind(elements.buttons.settings, 'keyup', function (event) { + var code = event.which; // We only care about space and return + + if (![13, 32].includes(code)) { + return; + } // Because return triggers a click anyway, all we need to do is set focus + + + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); + + return; + } // Prevent scroll + + + event.preventDefault(); // Prevent playing video (Firefox) + + event.stopPropagation(); // Toggle menu + + controls.toggleMenu.call(player, event); + }, null, false // Can't be passive as we're preventing default + ); // Escape closes menu + + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); // Set range input alternative "value", which matches the tooltip time (#954) + + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); + var percent = 100 / rect.width * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); // Pause while seeking + + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var attribute = 'play-on-seeked'; + + if (is.keyboardEvent(event) && code !== 39 && code !== 37) { + return; + } // Record seek time so we can prevent hiding controls for a few seconds after seek + + + player.lastSeekTime = Date.now(); // Was playing before? + + var play = seek.hasAttribute(attribute); // Done seeking + + var done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback + + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); + } + }); // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + + if (browser.isIos) { + var inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(function (input) { + return _this3.bind(input, inputEvent, function (event) { + return repaint(event.target); + }); + }); + } // Seek + + + this.bind(elements.inputs.seek, inputEvent, function (event) { + var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) + + var seekTo = seek.getAttribute('seek-value'); + + if (is.empty(seekTo)) { + seekTo = seek.value; + } + + seek.removeAttribute('seek-value'); + player.currentTime = seekTo / seek.max * player.duration; + }, 'seek'); // Seek tooltip + + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this + + this.bind(elements.progress, 'mousemove touchmove', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + + this.bind(elements.progress, 'mouseleave click', function () { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); // Show scrubbing preview + + this.bind(elements.progress, 'mousedown touchstart', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } + }); + this.bind(elements.progress, 'mouseup touchend', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); // Polyfill for lower fill in <input type="range"> for webkit + + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this3.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); + }); + }); + } // Current time invert + // Only if one time element is used for both currentTime and duration + + + if (player.config.toggleInvert && !is.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { + // Do nothing if we're at the start + if (player.currentTime === 0) { + return; + } + + player.config.invertTime = !player.config.invertTime; + + controls.timeUpdate.call(player); + }); + } // Volume + + + this.bind(elements.inputs.volume, inputEvent, function (event) { + player.volume = event.target.value; + }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); // Show controls when they receive focus (e.g., when using keyboard tab key) + + this.bind(elements.controls, 'focusin', function () { + var config = player.config, + elements = player.elements, + timers = player.timers; // Skip transition to prevent focus from scrolling the parent element + + toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle + + ui.toggleControls.call(player, true); // Restore transition + + setTimeout(function () { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); // Delay a little more for mouse users + + var delay = _this3.touch ? 3000 : 4000; // Clear timer + + clearTimeout(timers.controls); // Hide again after delay + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Mouse wheel for volume + + this.bind(elements.inputs.volume, 'wheel', function (event) { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + var inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true + + var _map = [event.deltaX, -event.deltaY].map(function (value) { + return inverted ? -value : value; + }), + _map2 = _slicedToArray(_map, 2), + x = _map2[0], + y = _map2[1]; // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) + + + var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2% + + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min + + var volume = player.media.volume; + + if (direction === 1 && volume < 1 || direction === -1 && volume > 0) { + event.preventDefault(); + } + }, 'volume', false); + } + }]); + + return Listeners; + }(); + + var loadjs_umd = createCommonjsModule(function (module, exports) { + (function(root, factory) { + { + module.exports = factory(); + } + }(commonjsGlobal, function() { + /** + * Global dependencies. + * @global {Object} document - DOM + */ + + var devnull = function() {}, + bundleIdCache = {}, + bundleResultCache = {}, + bundleCallbackQueue = {}; + + + /** + * Subscribe to bundle load event. + * @param {string[]} bundleIds - Bundle ids + * @param {Function} callbackFn - The callback function + */ + function subscribe(bundleIds, callbackFn) { + // listify + bundleIds = bundleIds.push ? bundleIds : [bundleIds]; + + var depsNotFound = [], + i = bundleIds.length, + numWaiting = i, + fn, + bundleId, + r, + q; + + // define callback function + fn = function (bundleId, pathsNotFound) { + if (pathsNotFound.length) depsNotFound.push(bundleId); + + numWaiting--; + if (!numWaiting) callbackFn(depsNotFound); + }; + + // register callback + while (i--) { + bundleId = bundleIds[i]; + + // execute callback if in result cache + r = bundleResultCache[bundleId]; + if (r) { + fn(bundleId, r); + continue; + } + + // add to callback queue + q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; + q.push(fn); + } + } + + + /** + * Publish bundle load event. + * @param {string} bundleId - Bundle id + * @param {string[]} pathsNotFound - List of files not found + */ + function publish(bundleId, pathsNotFound) { + // exit if id isn't defined + if (!bundleId) return; + + var q = bundleCallbackQueue[bundleId]; + + // cache result + bundleResultCache[bundleId] = pathsNotFound; + + // exit if queue is empty + if (!q) return; + + // empty callback queue + while (q.length) { + q[0](bundleId, pathsNotFound); + q.splice(0, 1); + } + } + + + /** + * Execute callbacks. + * @param {Object or Function} args - The callback args + * @param {string[]} depsNotFound - List of dependencies not found + */ + function executeCallbacks(args, depsNotFound) { + // accept function as argument + if (args.call) args = {success: args}; + + // success and error callbacks + if (depsNotFound.length) (args.error || devnull)(depsNotFound); + else (args.success || devnull)(args); + } + + + /** + * Load individual file. + * @param {string} path - The file path + * @param {Function} callbackFn - The callback function + */ + function loadFile(path, callbackFn, args, numTries) { + var doc = document, + async = args.async, + maxTries = (args.numRetries || 0) + 1, + beforeCallbackFn = args.before || devnull, + pathStripped = path.replace(/^(css|img)!/, ''), + isCss, + e; + + numTries = numTries || 0; + + if (/(^css!|\.css$)/.test(path)) { + isCss = true; + + // css + e = doc.createElement('link'); + e.rel = 'stylesheet'; + e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix + } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { + // image + e = doc.createElement('img'); + e.src = pathStripped; + } else { + // javascript + e = doc.createElement('script'); + e.src = path; + e.async = async === undefined ? true : async; + } + + e.onload = e.onerror = e.onbeforeload = function (ev) { + var result = ev.type[0]; + + // Note: The following code isolates IE using `hideFocus` and treats empty + // stylesheets as failures to get around lack of onerror support + if (isCss && 'hideFocus' in e) { + try { + if (!e.sheet.cssText.length) result = 'e'; + } catch (x) { + // sheets objects created from load errors don't allow access to + // `cssText` (unless error is Code:18 SecurityError) + if (x.code != 18) result = 'e'; + } + } + + // handle retries in case of load failure + if (result == 'e') { + // increment counter + numTries += 1; + + // exit function and try again + if (numTries < maxTries) { + return loadFile(path, callbackFn, args, numTries); + } + } + + // execute callback + callbackFn(path, result, ev.defaultPrevented); + }; + + // add to document (unless callback returns `false`) + if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); + } + + + /** + * Load multiple files. + * @param {string[]} paths - The file paths + * @param {Function} callbackFn - The callback function + */ + function loadFiles(paths, callbackFn, args) { + // listify paths + paths = paths.push ? paths : [paths]; + + var numWaiting = paths.length, + x = numWaiting, + pathsNotFound = [], + fn, + i; + + // define callback function + fn = function(path, result, defaultPrevented) { + // handle error + if (result == 'e') pathsNotFound.push(path); + + // handle beforeload event. If defaultPrevented then that means the load + // will be blocked (ex. Ghostery/ABP on Safari) + if (result == 'b') { + if (defaultPrevented) pathsNotFound.push(path); + else return; + } + + numWaiting--; + if (!numWaiting) callbackFn(pathsNotFound); + }; + + // load scripts + for (i=0; i < x; i++) loadFile(paths[i], fn, args); + } + + + /** + * Initiate script load and register bundle. + * @param {(string|string[])} paths - The file paths + * @param {(string|Function)} [arg1] - The bundleId or success callback + * @param {Function} [arg2] - The success or error callback + * @param {Function} [arg3] - The error callback + */ + function loadjs(paths, arg1, arg2) { + var bundleId, + args; + + // bundleId (if string) + if (arg1 && arg1.trim) bundleId = arg1; + + // args (default is {}) + args = (bundleId ? arg2 : arg1) || {}; + + // throw error if bundle is already defined + if (bundleId) { + if (bundleId in bundleIdCache) { + throw "LoadJS"; + } else { + bundleIdCache[bundleId] = true; + } + } + + // load scripts + loadFiles(paths, function (pathsNotFound) { + // execute callbacks + executeCallbacks(args, pathsNotFound); + + // publish bundle load event + publish(bundleId, pathsNotFound); + }, args); + } + + + /** + * Execute callbacks when dependencies have been satisfied. + * @param {(string|string[])} deps - List of bundle ids + * @param {Object} args - success/error arguments + */ + loadjs.ready = function ready(deps, args) { + // subscribe to bundle load event + subscribe(deps, function (depsNotFound) { + // execute callbacks + executeCallbacks(args, depsNotFound); + }); + + return loadjs; + }; + + + /** + * Manually satisfy bundle dependencies. + * @param {string} bundleId - The bundle id + */ + loadjs.done = function done(bundleId) { + publish(bundleId, []); + }; + + + /** + * Reset loadjs dependencies statuses + */ + loadjs.reset = function reset() { + bundleIdCache = {}; + bundleResultCache = {}; + bundleCallbackQueue = {}; + }; + + + /** + * Determine if bundle has already been defined + * @param String} bundleId - The bundle id + */ + loadjs.isDefined = function isDefined(bundleId) { + return bundleId in bundleIdCache; + }; + + + // export + return loadjs; + + })); + }); + + // ========================================================================== + function loadScript(url) { + return new Promise(function (resolve, reject) { + loadjs_umd(url, { + success: resolve, + error: reject + }); + }); + } + + function parseId(url) { + if (is.empty(url)) { + return null; + } + + if (is.number(Number(url))) { + return url; + } + + var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) + + + function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } + + var vimeo = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio + + setAspectRatio.call(this); // Load the API if not already + + if (!is.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk).then(function () { + vimeo.ready.call(_this); + }).catch(function (error) { + _this.debug.warn('Vimeo API failed to load', error); + }); + } else { + vimeo.ready.call(this); + } + }, + // API Ready + ready: function ready$$1() { + var _this2 = this; + + var player = this; + var config = player.config.vimeo; // Get Vimeo params for the iframe + + var params = buildUrlParams(extend({}, { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative + }, config)); // Get the source URL or ID + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is.empty(source)) { + source = player.media.getAttribute(player.config.attributes.embed.id); + } + + var id = parseId(source); // Build an iframe + + var iframe = createElement('iframe'); + var src = format(player.config.urls.vimeo.iframe, id, params); + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + iframe.setAttribute('allowtransparency', ''); + iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set + + var poster = player.poster; // Inject the package + + var wrapper = createElement('div', { + poster: poster, + class: player.config.classNames.embedContainer + }); + wrapper.appendChild(iframe); + player.media = replaceElement(wrapper, player.media); // Get poster image + + fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { + if (is.empty(response)) { + return; + } // Get the URL for thumbnail + + + var url = new URL(response[0].thumbnail_large); // Get original image + + url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster + + ui.setPoster.call(player, url.href).catch(function () {}); + }); // Setup instance + // https://github.com/vimeo/player.js + + player.embed = new window.Vimeo.Player(iframe, { + autopause: player.config.autopause, + muted: player.muted + }); + player.media.paused = true; + player.media.currentTime = 0; // Disable native text track rendering + + if (player.supported.ui) { + player.embed.disableTextTrack(); + } // Create a faux HTML5 API using the Vimeo API + + + player.media.play = function () { + assurePlaybackState.call(player, true); + return player.embed.play(); + }; + + player.media.pause = function () { + assurePlaybackState.call(player, false); + return player.embed.pause(); + }; + + player.media.stop = function () { + player.pause(); + player.currentTime = 0; + }; // Seeking + + + var currentTime = player.media.currentTime; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return currentTime; + }, + set: function set(time) { + // Vimeo will automatically play on seek if the video hasn't been played before + // Get current paused state and volume etc + var embed = player.embed, + media = player.media, + paused = player.paused, + volume = player.volume; + var restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event + + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete + + Promise.resolve(restorePause && embed.setVolume(0)) // Seek + .then(function () { + return embed.setCurrentTime(time); + }) // Restore paused + .then(function () { + return restorePause && embed.pause(); + }) // Restore volume + .then(function () { + return restorePause && embed.setVolume(volume); + }).catch(function () {// Do nothing + }); + } + }); // Playback speed + + var speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return speed; + }, + set: function set(input) { + player.embed.setPlaybackRate(input).then(function () { + speed = input; + triggerEvent.call(player, player.media, 'ratechange'); + }).catch(function (error) { + // Hide menu item (and menu if empty) + if (error.name === 'Error') { + controls.setSpeedMenu.call(player, []); + } + }); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + player.embed.setVolume(input).then(function () { + volume = input; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : false; + player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { + muted = toggle; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Loop + + var loop = player.config.loop; + Object.defineProperty(player.media, 'loop', { + get: function get() { + return loop; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : player.config.loop.active; + player.embed.setLoop(toggle).then(function () { + loop = toggle; + }); + } + }); // Source + + var currentSrc; + player.embed.getVideoUrl().then(function (value) { + currentSrc = value; + controls.setDownloadLink.call(player); + }).catch(function (error) { + _this2.debug.warn(error); + }); + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return currentSrc; + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Set aspect ratio based on video size + + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { + var _dimensions = _slicedToArray(dimensions, 2), + width = _dimensions[0], + height = _dimensions[1]; + + player.embed.ratio = "".concat(width, ":").concat(height); + setAspectRatio.call(_this2, player.embed.ratio); + }); // Set autopause + + player.embed.setAutopause(player.config.autopause).then(function (state) { + player.config.autopause = state; + }); // Get title + + player.embed.getVideoTitle().then(function (title) { + player.config.title = title; + ui.setTitle.call(_this2); + }); // Get current time + + player.embed.getCurrentTime().then(function (value) { + currentTime = value; + triggerEvent.call(player, player.media, 'timeupdate'); + }); // Get duration + + player.embed.getDuration().then(function (value) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + }); // Get captions + + player.embed.getTextTracks().then(function (tracks) { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + player.embed.on('cuechange', function (_ref) { + var _ref$cues = _ref.cues, + cues = _ref$cues === void 0 ? [] : _ref$cues; + var strippedCues = cues.map(function (cue) { + return stripHTML(cue.text); + }); + captions.updateCues.call(player, strippedCues); + }); + player.embed.on('loaded', function () { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(function (paused) { + assurePlaybackState.call(player, !paused); + + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); + + if (is.element(player.embed.element) && player.supported.ui) { + var frame = player.embed.element; // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 + + frame.setAttribute('tabindex', -1); + } + }); + player.embed.on('play', function () { + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); + }); + player.embed.on('pause', function () { + assurePlaybackState.call(player, false); + }); + player.embed.on('timeupdate', function (data) { + player.media.seeking = false; + currentTime = data.seconds; + triggerEvent.call(player, player.media, 'timeupdate'); + }); + player.embed.on('progress', function (data) { + player.media.buffered = data.percent; + triggerEvent.call(player, player.media, 'progress'); // Check all loaded + + if (parseInt(data.percent, 10) === 1) { + triggerEvent.call(player, player.media, 'canplaythrough'); + } // Get duration as if we do it before load, it gives an incorrect value + // https://github.com/sampotts/plyr/issues/891 + + + player.embed.getDuration().then(function (value) { + if (value !== player.media.duration) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + } + }); + }); + player.embed.on('seeked', function () { + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + }); + player.embed.on('ended', function () { + player.media.paused = true; + triggerEvent.call(player, player.media, 'ended'); + }); + player.embed.on('error', function (detail) { + player.media.error = detail; + triggerEvent.call(player, player.media, 'error'); + }); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 0); + } + }; + + // ========================================================================== + + function parseId$1(url) { + if (is.empty(url)) { + return null; + } + + var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) + + + function assurePlaybackState$1(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } + + var youtube = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio + + setAspectRatio.call(this); // Setup API + + if (is.object(window.YT) && is.function(window.YT.Player)) { + youtube.ready.call(this); + } else { + // Load the API + loadScript(this.config.urls.youtube.sdk).catch(function (error) { + _this.debug.warn('YouTube API failed to load', error); + }); // Setup callback for the API + // YouTube has it's own system of course... + + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue + + window.onYouTubeReadyCallbacks.push(function () { + youtube.ready.call(_this); + }); // Set callback to process queue + + window.onYouTubeIframeAPIReady = function () { + window.onYouTubeReadyCallbacks.forEach(function (callback) { + callback(); + }); + }; + } + }, + // Get the media title + getTitle: function getTitle(videoId) { + var _this2 = this; + + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (is.function(this.embed.getVideoData)) { + var _this$embed$getVideoD = this.embed.getVideoData(), + title = _this$embed$getVideoD.title; + + if (is.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; + } + } // Or via Google API + + + var key = this.config.keys.google; + + if (is.string(key) && !is.empty(key)) { + var url = format(this.config.urls.youtube.api, videoId, key); + fetch(url).then(function (result) { + if (is.object(result)) { + _this2.config.title = result.items[0].snippet.title; + ui.setTitle.call(_this2); + } + }).catch(function () {}); + } + }, + // API ready + ready: function ready$$1() { + var player = this; // Ignore already setup (race condition) + + var currentId = player.media.getAttribute('id'); + + if (!is.empty(currentId) && currentId.startsWith('youtube-')) { + return; + } // Get the source URL or ID + + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is.empty(source)) { + source = player.media.getAttribute(this.config.attributes.embed.id); + } // Replace the <iframe> with a <div> due to YouTube API issues + + + var videoId = parseId$1(source); + var id = generateId(player.provider); // Get poster, if already set + + var poster = player.poster; // Replace media element + + var container = createElement('div', { + id: id, + poster: poster + }); + player.media = replaceElement(container, player.media); // Id to poster wrapper + + var posterSrc = function posterSrc(format$$1) { + return "https://img.youtube.com/vi/".concat(videoId, "/").concat(format$$1, "default.jpg"); + }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + + + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(function () { + return loadImage(posterSrc('sd'), 121); + }) // 480p padded 4:3 + .catch(function () { + return loadImage(posterSrc('hq')); + }) // 360p padded 4:3. Always exists + .then(function (image) { + return ui.setPoster.call(player, image.src); + }).then(function (posterSrc) { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }).catch(function () {}); + var config = player.config.youtube; // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + + player.embed = new window.YT.Player(id, { + videoId: videoId, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend({}, { + autoplay: player.config.autoplay ? 1 : 0, + // Autoplay + hl: player.config.hl, + // iframe interface language + controls: player.supported.ui ? 0 : 1, + // Only show controls if not fully supported + disablekb: 1, + // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, + // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null + }, config), + events: { + onError: function onError(event) { + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + var code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + + var message = { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.' + }[code] || 'An unknown error occured'; + player.media.error = { + code: code, + message: message + }; + triggerEvent.call(player, player.media, 'error'); + } + }, + onPlaybackRateChange: function onPlaybackRateChange(event) { + // Get the instance + var instance = event.target; // Get current speed + + player.media.playbackRate = instance.getPlaybackRate(); + triggerEvent.call(player, player.media, 'ratechange'); + }, + onReady: function onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is.function(player.media.play)) { + return; + } // Get the instance + + + var instance = event.target; // Get the title + + youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API + + player.media.play = function () { + assurePlaybackState$1.call(player, true); + instance.playVideo(); + }; + + player.media.pause = function () { + assurePlaybackState$1.call(player, false); + instance.pauseVideo(); + }; + + player.media.stop = function () { + instance.stopVideo(); + }; + + player.media.duration = instance.getDuration(); + player.media.paused = true; // Seeking + + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return Number(instance.getCurrentTime()); + }, + set: function set(time) { + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } // Set seeking state and trigger event + + + player.media.seeking = true; + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent + + instance.seekTo(time); + } + }); // Playback speed + + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return instance.getPlaybackRate(); + }, + set: function set(input) { + instance.setPlaybackRate(input); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + volume = input; + instance.setVolume(volume * 100); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Source + + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return instance.getVideoUrl(); + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Get available speeds + + player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe + + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } + + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer + + clearInterval(player.timers.buffering); // Setup buffering + + player.timers.buffering = setInterval(function () { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something + + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + triggerEvent.call(player, player.media, 'progress'); + } // Set last buffer point + + + player.media.lastBuffered = player.media.buffered; // Bail if we're at 100% + + if (player.media.buffered === 1) { + clearInterval(player.timers.buffering); // Trigger event + + triggerEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 50); + }, + onStateChange: function onStateChange(event) { + // Get the instance + var instance = event.target; // Reset timer + + clearInterval(player.timers.playing); + var seeked = player.media.seeking && [1, 2].includes(event.data); + + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued + + + switch (event.data) { + case -1: + // Update scrubber + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube + + player.media.buffered = instance.getVideoLoadedFraction(); + triggerEvent.call(player, player.media, 'progress'); + break; + + case 0: + assurePlaybackState$1.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. + + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + triggerEvent.call(player, player.media, 'ended'); + } + + break; + + case 1: + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState$1.call(player, true); + triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress + + player.timers.playing = setInterval(function () { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + triggerEvent.call(player, player.media, 'durationchange'); + } + } + + break; + + case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } + + assurePlaybackState$1.call(player, false); + break; + + default: + break; + } + + triggerEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data + }); + } + } + }); + } + }; + + // ========================================================================== + var media = { + // Setup media + setup: function setup() { + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } // Add type class + + + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class + + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds + // This will require changes if audio embeds are added + + if (this.isEmbed) { + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } // Inject the player wrapper + + + if (this.isVideo) { + // Create the wrapper div + this.elements.wrapper = createElement('div', { + class: this.config.classNames.video + }); // Wrap the video in a container + + wrap(this.media, this.elements.wrapper); // Faux poster container + + this.elements.poster = createElement('div', { + class: this.config.classNames.poster + }); + this.elements.wrapper.appendChild(this.elements.poster); + } + + if (this.isHTML5) { + html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); + } + } + }; + + var Ads = + /*#__PURE__*/ + function () { + /** + * Ads constructor. + * @param {object} player + * @return {Ads} + */ + function Ads(player) { + var _this = this; + + _classCallCheck(this, Ads); + + this.player = player; + this.config = player.config.ads; + this.playing = false; + this.initialized = false; + this.elements = { + container: null, + displayContainer: null + }; + this.manager = null; + this.loader = null; + this.cuePoints = null; + this.events = {}; + this.safetyTimer = null; + this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready + + this.managerPromise = new Promise(function (resolve, reject) { + // The ad is loaded and ready + _this.on('loaded', resolve); // Ads failed + + + _this.on('error', reject); + }); + this.load(); + } + + _createClass(Ads, [{ + key: "load", + + /** + * Load the IMA SDK + */ + value: function load() { + var _this2 = this; + + if (this.enabled) { + // Check if the Google IMA3 SDK is loaded or load it ourselves + if (!is.object(window.google) || !is.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); + } + } + } + /** + * Get the ads instance ready + */ + + }, { + key: "ready", + value: function ready$$1() { + var _this3 = this; + + // Start ticking our safety timer. If the whole advertisement + // thing doesn't resolve within our set time; we bail + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer + + this.managerPromise.then(function () { + _this3.clearSafetyTimer('onAdsManagerLoaded()'); + }); // Set listeners on the Plyr instance + + this.listeners(); // Setup the IMA SDK + + this.setupIMA(); + } // Build the tag URL + + }, { + key: "setupIMA", + + /** + * In order for the SDK to display ads for our video, we need to tell it where to put them, + * so here we define our ad container. This div is set up to render on top of the video player. + * Using the code below, we tell the SDK to render ads within that div. We also provide a + * handle to the content video player - the SDK will poll the current time of our player to + * properly place mid-rolls. After we create the ad display container, we initialize it. On + * mobile devices, this initialization is done as the result of a user action. + */ + value: function setupIMA() { + // Create the container for our advertisements + this.elements.container = createElement('div', { + class: this.player.config.classNames.ads + }); + this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2 + + google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language + + google.ima.settings.setLocale(this.player.config.ads.language); // We assume the adContainer is the video container of the plyr element + // that will house the ads + + this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); // Request video ads to be pre-loaded + + this.requestAds(); + } + /** + * Request advertisements + */ + + }, { + key: "requestAds", + value: function requestAds() { + var _this4 = this; + + var container = this.player.elements.container; + + try { + // Create ads loader + this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events + + this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { + return _this4.onAdsManagerLoaded(event); + }, false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this4.onAdError(error); + }, false); // Request video ads + + var request = new google.ima.AdsRequest(); + request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK + // to select the correct creative if multiple are returned + + request.linearAdSlotWidth = container.offsetWidth; + request.linearAdSlotHeight = container.offsetHeight; + request.nonLinearAdSlotWidth = container.offsetWidth; + request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video. + + request.forceNonLinearFullSlot = false; // Mute based on current state + + request.setAdWillPlayMuted(!this.player.muted); + this.loader.requestAds(request); + } catch (e) { + this.onAdError(e); + } + } + /** + * Update the ad countdown + * @param {boolean} start + */ + + }, { + key: "pollCountdown", + value: function pollCountdown() { + var _this5 = this; + + var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (!start) { + clearInterval(this.countdownTimer); + this.elements.container.removeAttribute('data-badge-text'); + return; + } + + var update = function update() { + var time = formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); + var label = "".concat(i18n.get('advertisement', _this5.player.config), " - ").concat(time); + + _this5.elements.container.setAttribute('data-badge-text', label); + }; + + this.countdownTimer = setInterval(update, 100); + } + /** + * This method is called whenever the ads are ready inside the AdDisplayContainer + * @param {Event} adsManagerLoadedEvent + */ + + }, { + key: "onAdsManagerLoaded", + value: function onAdsManagerLoaded(event) { + var _this6 = this; + + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } // Get the ads manager + + + var settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf + + settings.restoreCustomPlaybackStateOnAdBreakComplete = true; + settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration + // so it can determine when to start the mid- and post-roll + + this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll + + this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available + + if (!is.empty(this.cuePoints)) { + this.cuePoints.forEach(function (cuePoint) { + if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { + var seekElement = _this6.player.elements.progress; + + if (is.element(seekElement)) { + var cuePercentage = 100 / _this6.player.duration * cuePoint; + var cue = createElement('span', { + class: _this6.player.config.classNames.cues + }); + cue.style.left = "".concat(cuePercentage.toString(), "%"); + seekElement.appendChild(cue); + } + } + }); + } // Set volume to match player + + + this.manager.setVolume(this.player.volume); // Add listeners to the required events + // Advertisement error events + + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this6.onAdError(error); + }); // Advertisement regular events + + Object.keys(google.ima.AdEvent.Type).forEach(function (type) { + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { + return _this6.onAdEvent(event); + }); + }); // Resolve our adsManager + + this.trigger('loaded'); + } + /** + * This is where all the event handling takes place. Retrieve the ad from the event. Some + * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated + * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type + * @param {Event} event + */ + + }, { + key: "onAdEvent", + value: function onAdEvent(event) { + var _this7 = this; + + var container = this.player.elements.container; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) + // don't have ad object associated + + var ad = event.getAd(); + var adData = event.getAdData(); // Proxy event + + var dispatchEvent = function dispatchEvent(type) { + var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); + triggerEvent.call(_this7.player, _this7.player.media, event); + }; + + switch (event.type) { + case google.ima.AdEvent.Type.LOADED: + // This is the first event sent for an ad - it is possible to determine whether the + // ad is a video ad or an overlay + this.trigger('loaded'); // Bubble event + + dispatchEvent(event.type); // Start countdown + + this.pollCountdown(true); + + if (!ad.isLinear()) { + // Position AdDisplayContainer correctly for overlay + ad.width = container.offsetWidth; + ad.height = container.offsetHeight; + } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); + // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); + + + break; + + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: + // All ads for the current videos are done. We can now request new advertisements + // in case the video is re-played + // Fire event + dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // So here we load a new video when all ads are done. + // Then we load new ads within a new adsManager. When the video + // Is started - after - the ads are loaded, then we get ads. + // You can also easily test cancelling and reloading by running + // player.ads.cancel() and player.ads.play from the console I guess. + // this.player.source = { + // type: 'video', + // title: 'View From A Blue Moon', + // sources: [{ + // src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: + // 'video/mp4', }], poster: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: + // [ { kind: 'captions', label: 'English', srclang: 'en', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], + // }; + // TODO: So there is still this thing where a video should only be allowed to start + // playing when the IMA SDK is ready or has failed + + this.loadAds(); + break; + + case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: + // This event indicates the ad has started - the video player can adjust the UI, + // for example display a pause button and remaining time. Fired when content should + // be paused. This usually happens right before an ad is about to cover the content + dispatchEvent(event.type); + this.pauseContent(); + break; + + case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: + // This event indicates the ad has finished - the video player can perform + // appropriate UI actions, such as removing the timer for remaining time detection. + // Fired when content should be resumed. This usually happens when an ad finishes + // or collapses + dispatchEvent(event.type); + this.pollCountdown(); + this.resumeContent(); + break; + + case google.ima.AdEvent.Type.STARTED: + case google.ima.AdEvent.Type.MIDPOINT: + case google.ima.AdEvent.Type.COMPLETE: + case google.ima.AdEvent.Type.IMPRESSION: + case google.ima.AdEvent.Type.CLICK: + dispatchEvent(event.type); + break; + + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); + } + + break; + + default: + break; + } + } + /** + * Any ad error handling comes through here + * @param {Event} event + */ + + }, { + key: "onAdError", + value: function onAdError(event) { + this.cancel(); + this.player.debug.warn('Ads error', event); + } + /** + * Setup hooks for Plyr and window events. This ensures + * the mid- and post-roll launch at the correct time. And + * resize the advertisement when the player resizes + */ + + }, { + key: "listeners", + value: function listeners() { + var _this8 = this; + + var container = this.player.elements.container; + var time; // Add listeners to the required events + + this.player.on('ended', function () { + _this8.loader.contentComplete(); + }); + this.player.on('timeupdate', function () { + time = _this8.player.currentTime; + }); + this.player.on('seeked', function () { + var seekedTime = _this8.player.currentTime; + + if (is.empty(_this8.cuePoints)) { + return; + } + + _this8.cuePoints.forEach(function (cuePoint, index) { + if (time < cuePoint && cuePoint < seekedTime) { + _this8.manager.discardAdBreak(); + + _this8.cuePoints.splice(index, 1); + } + }); + }); // Listen to the resizing of the window. And resize ad accordingly + // TODO: eventually implement ResizeObserver + + window.addEventListener('resize', function () { + if (_this8.manager) { + _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); + } + }); + } + /** + * Initialize the adsManager and start playing advertisements + */ + + }, { + key: "play", + value: function play() { + var _this9 = this; + + var container = this.player.elements.container; + + if (!this.managerPromise) { + this.resumeContent(); + } // Play the requested advertisement whenever the adsManager is ready + + + this.managerPromise.then(function () { + // Initialize the container. Must be done via a user action on mobile devices + _this9.elements.displayContainer.initialize(); + + try { + if (!_this9.initialized) { + // Initialize the ads manager. Ad rules playlist will start at this time + _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will + // start at this time; the call will be ignored for ad rules + + + _this9.manager.start(); + } + + _this9.initialized = true; + } catch (adError) { + // An error may be thrown if there was a problem with the + // VAST response + _this9.onAdError(adError); + } + }).catch(function () {}); + } + /** + * Resume our video + */ + + }, { + key: "resumeContent", + value: function resumeContent() { + // Hide the advertisement container + this.elements.container.style.zIndex = ''; // Ad is stopped + + this.playing = false; // Play our video + + if (this.player.currentTime < this.player.duration) { + this.player.play(); + } + } + /** + * Pause our video + */ + + }, { + key: "pauseContent", + value: function pauseContent() { + // Show the advertisement container + this.elements.container.style.zIndex = 3; // Ad is playing. + + this.playing = true; // Pause our video. + + this.player.pause(); + } + /** + * Destroy the adsManager so we can grab new ads after this. If we don't then we're not + * allowed to call new ads based on google policies, as they interpret this as an accidental + * video requests. https://developers.google.com/interactive- + * media-ads/docs/sdks/android/faq#8 + */ + + }, { + key: "cancel", + value: function cancel() { + // Pause our video + if (this.initialized) { + this.resumeContent(); + } // Tell our instance that we're done for now + + + this.trigger('error'); // Re-create our adsManager + + this.loadAds(); + } + /** + * Re-create our adsManager + */ + + }, { + key: "loadAds", + value: function loadAds() { + var _this10 = this; + + // Tell our adsManager to go bye bye + this.managerPromise.then(function () { + // Destroy our adsManager + if (_this10.manager) { + _this10.manager.destroy(); + } // Re-set our adsManager promises + + + _this10.managerPromise = new Promise(function (resolve) { + _this10.on('loaded', resolve); + + _this10.player.debug.log(_this10.manager); + }); // Now request some new advertisements + + _this10.requestAds(); + }).catch(function () {}); + } + /** + * Handles callbacks after an ad event was invoked + * @param {string} event - Event type + */ + + }, { + key: "trigger", + value: function trigger(event) { + var _this11 = this; + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var handlers = this.events[event]; + + if (is.array(handlers)) { + handlers.forEach(function (handler) { + if (is.function(handler)) { + handler.apply(_this11, args); + } + }); + } + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + * @return {Ads} + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + if (!is.array(this.events[event])) { + this.events[event] = []; + } + + this.events[event].push(callback); + return this; + } + /** + * Setup a safety timer for when the ad network doesn't respond for whatever reason. + * The advertisement has 12 seconds to get its things together. We stop this timer when the + * advertisement is playing, or when a user action is required to start, then we clear the + * timer on ad ready + * @param {number} time + * @param {string} from + */ + + }, { + key: "startSafetyTimer", + value: function startSafetyTimer(time, from) { + var _this12 = this; + + this.player.debug.log("Safety timer invoked from: ".concat(from)); + this.safetyTimer = setTimeout(function () { + _this12.cancel(); + + _this12.clearSafetyTimer('startSafetyTimer()'); + }, time); + } + /** + * Clear our safety timer(s) + * @param {string} from + */ + + }, { + key: "clearSafetyTimer", + value: function clearSafetyTimer(from) { + if (!is.nullOrUndefined(this.safetyTimer)) { + this.player.debug.log("Safety timer cleared from: ".concat(from)); + clearTimeout(this.safetyTimer); + this.safetyTimer = null; + } + } + }, { + key: "enabled", + get: function get() { + var config = this.config; + return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl)); + } + }, { + key: "tagUrl", + get: function get() { + var config = this.config; + + if (is.url(config.tagUrl)) { + return config.tagUrl; + } + + var params = { + AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', + AV_CHANNELID: '5a0458dc28a06145e4519d21', + AV_URL: window.location.hostname, + cb: Date.now(), + AV_WIDTH: 640, + AV_HEIGHT: 480, + AV_CDIM2: this.publisherId + }; + var base = 'https://go.aniview.com/api/adserver6/vast/'; + return "".concat(base, "?").concat(buildUrlParams(params)); + } + }]); + + return Ads; + }(); + + var parseVtt = function parseVtt(vttDataString) { + var processedList = []; + var frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + frames.forEach(function (frame) { + var result = {}; + var lines = frame.split(/\r\n|\n|\r/); + lines.forEach(function (line) { + if (!is.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + var matchTimes = line.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = Number(matchTimes[1]) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number("0.".concat(matchTimes[4])); + result.endTime = Number(matchTimes[6]) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number("0.".concat(matchTimes[9])); + } + } else if (!is.empty(line.trim()) && is.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + var lineSplit = line.trim().split('#xywh='); + + var _lineSplit = _slicedToArray(lineSplit, 1); + + result.text = _lineSplit[0]; + + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + var _lineSplit$1$split = lineSplit[1].split(','); + + var _lineSplit$1$split2 = _slicedToArray(_lineSplit$1$split, 4); + + result.x = _lineSplit$1$split2[0]; + result.y = _lineSplit$1$split2[1]; + result.w = _lineSplit$1$split2[2]; + result.h = _lineSplit$1$split2[3]; + } + } + }); + + if (result.text) { + processedList.push(result); + } + }); + return processedList; + }; + /** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + + + var PreviewThumbnails = + /*#__PURE__*/ + function () { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + function PreviewThumbnails(player) { + _classCallCheck(this, PreviewThumbnails); + + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + this.elements = { + thumb: {}, + scrubbing: {} + }; + this.load(); + } + + _createClass(PreviewThumbnails, [{ + key: "load", + value: function load() { + var _this = this; + + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; + } + + if (!this.enabled) { + return; + } + + this.getThumbnails().then(function () { + // Render DOM elements + _this.render(); // Check to see if thumb container size was specified manually in CSS + + + _this.determineContainerAutoSizing(); + + _this.loaded = true; + }); + } // Download VTT files and parse them + + }, { + key: "getThumbnails", + value: function getThumbnails() { + var _this2 = this; + + return new Promise(function (resolve) { + var src = _this2.player.config.previewThumbnails.src; + + if (is.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } // If string, convert into single-element list + + + var urls = is.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails + + var promises = urls.map(function (u) { + return _this2.getThumbnail(u); + }); + Promise.all(promises).then(function () { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + _this2.thumbnails.sort(function (x, y) { + return x.height - y.height; + }); + + _this2.player.debug.log('Preview thumbnails', _this2.thumbnails); + + resolve(); + }); + }); + } // Process individual VTT file + + }, { + key: "getThumbnail", + value: function getThumbnail(url) { + var _this3 = this; + + return new Promise(function (resolve) { + fetch(url).then(function (response) { + var thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '' + }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank + + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } // Download the first frame, so that we can determine/set the height of this thumbnailsDef + + + var tempImage = new Image(); + + tempImage.onload = function () { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; + + _this3.thumbnails.push(thumbnail); + + resolve(); + }; + + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } + }, { + key: "startMove", + value: function startMove(event) { + if (!this.loaded) { + return; + } + + if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } // Wait until media has a duration + + + if (!this.player.media.duration) { + return; + } + + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + var clientRect = this.player.elements.progress.getBoundingClientRect(); + var percentage = 100 / clientRect.width * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); + + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } + + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } + + this.mousePosX = event.pageX; // Set time text inside image container + + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } // Download and show image + + + this.showImageAtCurrentTime(); + } + }, { + key: "endMove", + value: function endMove() { + this.toggleThumbContainer(false, true); + } + }, { + key: "startScrubbing", + value: function startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; // Wait until media has a duration + + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); // Download and show image + + this.showImageAtCurrentTime(); + } + } + } + }, { + key: "finishScrubbing", + value: function finishScrubbing() { + var _this4 = this; + + this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview + + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', function () { + // Re-check mousedown - we might have already started scrubbing again + if (!_this4.mouseDown) { + _this4.toggleScrubbingContainer(false); + } + }); + } + } + /** + * Setup hooks for Plyr and window events + */ + + }, { + key: "listeners", + value: function listeners() { + var _this5 = this; + + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', function () { + _this5.toggleThumbContainer(false, true); + }); + this.player.on('seeked', function () { + _this5.toggleThumbContainer(false); + }); + this.player.on('timeupdate', function () { + _this5.lastTime = _this5.player.media.currentTime; + }); + } + /** + * Create HTML elements for image containers + */ + + }, { + key: "render", + value: function render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer + }); // Wrapper for the image for styling + + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00) + + var timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer + }); + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb + + this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container + + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer + }); + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + }, { + key: "showImageAtCurrentTime", + value: function showImageAtCurrentTime() { + var _this6 = this; + + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null + + + var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) { + return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime; + }); + var hasThumb = thumbNum >= 0; + var qualityIndex = 0; + this.toggleThumbContainer(hasThumb); // No matching thumb found + + if (!hasThumb) { + return; + } // Check to see if we've already downloaded higher quality versions of this image + + + this.thumbnails.forEach(function (thumbnail, index) { + if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); // Only proceed if either thumbnum or thumbfilename has changed + + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); + } + } // Show the image that's currently specified in this.showingThumb + + }, { + key: "loadImage", + value: function loadImage() { + var _this7 = this; + + var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var thumbNum = this.showingThumb; + var thumbnail = this.thumbnails[qualityIndex]; + var urlPrefix = thumbnail.urlPrefix; + var frame = thumbnail.frames[thumbNum]; + var thumbFilename = thumbnail.frames[thumbNum].text; + var thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + + + var previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + + previewImage.onload = function () { + return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + }; + + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); + } + } + }, { + key: "showImage", + value: function showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename) { + var newImage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this.player.debug.log("Showing thumb: ".concat(thumbFilename, ". num: ").concat(thumbNum, ". qual: ").concat(qualityIndex, ". newimg: ").concat(newImage)); + this.setImageSizeAndOffset(previewImage, frame); + + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; + + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading + + + this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } // Remove all preview images that aren't the designated current image + + }, { + key: "removeOldImages", + value: function removeOldImages(currentImage) { + var _this8 = this; + + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(function (image) { + if (image.tagName.toLowerCase() !== 'img') { + return; + } + + var removeDelay = _this8.usingSprites ? 500 : 1000; + + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub + + var currentImageContainer = _this8.currentImageContainer; + setTimeout(function () { + currentImageContainer.removeChild(image); + + _this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename)); + }, removeDelay); + } + }); + } // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality + + }, { + key: "preloadNearby", + value: function preloadNearby(thumbNum) { + var _this9 = this; + + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return new Promise(function (resolve) { + setTimeout(function () { + var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text; + + if (_this9.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + var thumbnailsClone; + + if (forward) { + thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } + + var foundOne = false; + thumbnailsClone.forEach(function (frame) { + var newThumbFilename = frame.text; + + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!_this9.loadedImages.includes(newThumbFilename)) { + foundOne = true; + + _this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename)); + + var urlPrefix = _this9.thumbnails[0].urlPrefix; + var thumbURL = urlPrefix + newThumbFilename; + var previewImage = new Image(); + previewImage.src = thumbURL; + + previewImage.onload = function () { + _this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename)); + + if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded + + resolve(); + }; + } + } + }); // If there are none to preload then we want to resolve immediately + + if (!foundOne) { + resolve(); + } + } + }, 300); + }); + } // If user has been hovering current image for half a second, look for a higher quality one + + }, { + key: "getHigherQuality", + value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + var _this10 = this; + + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + var previewImageHeight = previewImage.naturalHeight; + + if (this.usingSprites) { + previewImageHeight = frame.h; + } + + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(function () { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (_this10.showingThumbFilename === thumbFilename) { + _this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename)); + + _this10.loadImage(currentQualityIndex + 1); + } + }, 300); + } + } + } + }, { + key: "toggleThumbContainer", + value: function toggleThumbContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var clearShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); + + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "toggleScrubbingContainer", + value: function toggleScrubbingContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); + + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "determineContainerAutoSizing", + value: function determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS + + }, { + key: "setThumbContainerSizeAndPos", + value: function setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px"); + this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px"); + } + + this.setThumbContainerPos(); + } + }, { + key: "setThumbContainerPos", + value: function setThumbContainerPos() { + var seekbarRect = this.player.elements.progress.getBoundingClientRect(); + var plyrRect = this.player.elements.container.getBoundingClientRect(); + var container = this.elements.thumb.container; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container + + var minVal = plyrRect.left - seekbarRect.left + 10; + var maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth + + var previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; + + if (previewPos < minVal) { + previewPos = minVal; + } + + if (previewPos > maxVal) { + previewPos = maxVal; + } + + container.style.left = "".concat(previewPos, "px"); + } // Can't use 100% width, in case the video is a different aspect ratio to the video container + + }, { + key: "setScrubbingContainerSize", + value: function setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below + + this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px"); + } // Sprites need to be offset to the correct location + + }, { + key: "setImageSizeAndOffset", + value: function setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } // Find difference between height and preview container height + + + var multiplier = this.thumbContainerHeight / frame.h; + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); + } + }, { + key: "enabled", + get: function get() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + }, { + key: "currentImageContainer", + get: function get() { + if (this.mouseDown) { + return this.elements.scrubbing.container; + } + + return this.elements.thumb.imageContainer; + } + }, { + key: "usingSprites", + get: function get() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } + }, { + key: "thumbAspectRatio", + get: function get() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; + } + + return this.thumbnails[0].width / this.thumbnails[0].height; + } + }, { + key: "thumbContainerHeight", + get: function get() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); + } + + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + }, { + key: "currentImageElement", + get: function get() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } + + return this.currentThumbnailImageElement; + }, + set: function set(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; + } + } + }]); + + return PreviewThumbnails; + }(); + + var source = { + // Add elements to HTML5 media (source, tracks, etc) + insertElements: function insertElements(type, attributes) { + var _this = this; + + if (is.string(attributes)) { + insertElement(type, this.media, { + src: attributes + }); + } else if (is.array(attributes)) { + attributes.forEach(function (attribute) { + insertElement(type, _this.media, attribute); + }); + } + }, + // Update source + // Sources are not checked for support so be careful + change: function change(input) { + var _this2 = this; + + if (!getDeep(input, 'sources.length')) { + this.debug.warn('Invalid source format'); + return; + } // Cancel current network requests + + + html5.cancelRequests.call(this); // Destroy instance and re-setup + + this.destroy.call(this, function () { + // Reset quality options + _this2.options.quality = []; // Remove elements + + removeElement(_this2.media); + _this2.media = null; // Reset class name + + if (is.element(_this2.elements.container)) { + _this2.elements.container.removeAttribute('class'); + } // Set the type and provider + + + var sources = input.sources, + type = input.type; + + var _sources = _slicedToArray(sources, 1), + _sources$ = _sources[0], + _sources$$provider = _sources$.provider, + provider = _sources$$provider === void 0 ? providers.html5 : _sources$$provider, + src = _sources$.src; + + var tagName = provider === 'html5' ? type : 'div'; + var attributes = provider === 'html5' ? {} : { + src: src + }; + Object.assign(_this2, { + provider: provider, + type: type, + // Check for support + supported: support.check(type, provider, _this2.config.playsinline), + // Create new element + media: createElement(tagName, attributes) + }); // Inject the new element + + _this2.elements.container.appendChild(_this2.media); // Autoplay the new source? + + + if (is.boolean(input.autoplay)) { + _this2.config.autoplay = input.autoplay; + } // Set attributes for audio and video + + + if (_this2.isHTML5) { + if (_this2.config.crossorigin) { + _this2.media.setAttribute('crossorigin', ''); + } + + if (_this2.config.autoplay) { + _this2.media.setAttribute('autoplay', ''); + } + + if (!is.empty(input.poster)) { + _this2.poster = input.poster; + } + + if (_this2.config.loop.active) { + _this2.media.setAttribute('loop', ''); + } + + if (_this2.config.muted) { + _this2.media.setAttribute('muted', ''); + } + + if (_this2.config.playsinline) { + _this2.media.setAttribute('playsinline', ''); + } + } // Restore class hook + + + ui.addStyleHook.call(_this2); // Set new sources for html5 + + if (_this2.isHTML5) { + source.insertElements.call(_this2, 'source', sources); + } // Set video title + + + _this2.config.title = input.title; // Set up from scratch + + media.setup.call(_this2); // HTML5 stuff + + if (_this2.isHTML5) { + // Setup captions + if (Object.keys(input).includes('tracks')) { + source.insertElements.call(_this2, 'track', input.tracks); + } + } // If HTML5 or embed but not fully supported, setupInterface and call ready now + + + if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { + // Setup interface + ui.build.call(_this2); + } // Load HTML5 sources + + + if (_this2.isHTML5) { + _this2.media.load(); + } // Reload thumbnails + + + if (_this2.previewThumbnails) { + _this2.previewThumbnails.load(); + } // Update the fullscreen support + + + _this2.fullscreen.update(); + }, true); + } + }; + + // TODO: Use a WeakMap for private globals + // const globals = new WeakMap(); + // Plyr instance + + var Plyr = + /*#__PURE__*/ + function () { + function Plyr(target, options) { + var _this = this; + + _classCallCheck(this, Plyr); + + this.timers = {}; // State + + this.ready = false; + this.loading = false; + this.failed = false; // Touch device + + this.touch = support.touch; // Set the media element + + this.media = target; // String selector passed + + if (is.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } // jQuery, NodeList or Array passed, use first element + + + if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } // Set config + + + this.config = extend({}, defaults, Plyr.defaults, options || {}, function () { + try { + return JSON.parse(_this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; + } + }()); // Elements cache + + this.elements = { + container: null, + captions: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + popup: null, + menu: null, + panels: {}, + buttons: {} + } + }; // Captions + + this.captions = { + active: null, + currentTrack: -1, + meta: new WeakMap() + }; // Fullscreen + + this.fullscreen = { + active: false + }; // Options + + this.options = { + speed: [], + quality: [] + }; // Debugging + // TODO: move to globals + + this.debug = new Console(this.config.debug); // Log config options and support + + this.debug.log('Config', this.config); + this.debug.log('Support', support); // We need an element to setup + + if (is.nullOrUndefined(this.media) || !is.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); + return; + } // Bail if the element is initialized + + + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; + } // Bail if not enabled + + + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; + } // Bail if disabled or no basic support + // You may want to disable certain UAs etc + + + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; + } // Cache original element state for .destroy() + + + var clone = this.media.cloneNode(true); + clone.autoplay = false; + this.elements.original = clone; // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube + + var type = this.media.tagName.toLowerCase(); // Embed properties + + var iframe = null; + var url = null; // Different setup based on type + + switch (type) { + case 'div': + // Find the frame + iframe = this.media.querySelector('iframe'); // <iframe> type + + if (is.element(iframe)) { + // Detect provider + url = parseUrl$2(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements + + this.elements.container = this.media; + this.media = iframe; // Reset classname + + this.elements.container.className = ''; // Get attributes from URL and set config + + if (url.search.length) { + var truthy = ['1', 'true']; + + if (truthy.includes(url.searchParams.get('autoplay'))) { + this.config.autoplay = true; + } + + if (truthy.includes(url.searchParams.get('loop'))) { + this.config.loop.active = true; + } // TODO: replace fullscreen.iosNative with this playsinline config option + // YouTube requires the playsinline in the URL + + + if (this.isYouTube) { + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? + } else { + this.config.playsinline = true; + } + } + } else { + // <div> with attributes + this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute + + this.media.removeAttribute(this.config.attributes.embed.provider); + } // Unsupported or missing provider + + + if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } // Audio will come later for external providers + + + this.type = types.video; + break; + + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; // Get config from attributes + + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } + + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } + + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { + this.config.playsinline = true; + } + + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } + + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } + + break; + + default: + this.debug.error('Setup failed: unsupported type'); + return; + } // Check for support again but with type + + + this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail + + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); + return; + } + + this.eventListeners = []; // Create listeners + + this.listeners = new Listeners(this); // Setup local storage for user settings + + this.storage = new Storage(this); // Store reference + + this.media.plyr = this; // Wrap media + + if (!is.element(this.elements.container)) { + this.elements.container = createElement('div', { + tabindex: 0 + }); + wrap(this.media, this.elements.container); + } // Add style hook + + + ui.addStyleHook.call(this); // Setup media + + media.setup.call(this); // Listen for events if debugging + + if (this.config.debug) { + on.call(this, this.elements.container, this.config.events.join(' '), function (event) { + _this.debug.log("event: ".concat(event.type)); + }); + } // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls + + + if (this.isHTML5 || this.isEmbed && !this.supported.ui) { + ui.build.call(this); + } // Container listeners + + + this.listeners.container(); // Global listeners + + this.listeners.global(); // Setup fullscreen + + this.fullscreen = new Fullscreen(this); // Setup ads if provided + + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required + + + if (this.config.autoplay) { + this.play(); + } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek + + + this.lastSeekTime = 0; // Setup preview thumbnails if enabled + + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } + } // --------------------------------------- + // API + // --------------------------------------- + + /** + * Types and provider helpers + */ + + + _createClass(Plyr, [{ + key: "play", + + /** + * Play the media, or play the advertisement (if they are not blocked) + */ + value: function play() { + if (!is.function(this.media.play)) { + return null; + } // Return the promise (for HTML5) + + + return this.media.play(); + } + /** + * Pause the media + */ + + }, { + key: "pause", + value: function pause() { + if (!this.playing || !is.function(this.media.pause)) { + return; + } + + this.media.pause(); + } + /** + * Get playing state + */ + + }, { + key: "togglePlay", + + /** + * Toggle playback based on current status + * @param {boolean} input + */ + value: function togglePlay(input) { + // Toggle based on current state if nothing passed + var toggle = is.boolean(input) ? input : !this.playing; + + if (toggle) { + this.play(); + } else { + this.pause(); + } + } + /** + * Stop playback + */ + + }, { + key: "stop", + value: function stop() { + if (this.isHTML5) { + this.pause(); + this.restart(); + } else if (is.function(this.media.stop)) { + this.media.stop(); + } + } + /** + * Restart playback + */ + + }, { + key: "restart", + value: function restart() { + this.currentTime = 0; + } + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ + + }, { + key: "rewind", + value: function rewind(seekTime) { + this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ + + }, { + key: "forward", + value: function forward(seekTime) { + this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ + + }, { + key: "increaseVolume", + + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + value: function increaseVolume(step) { + var volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (is.number(step) ? step : 0); + } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + + }, { + key: "decreaseVolume", + value: function decreaseVolume(step) { + this.increaseVolume(-step); + } + /** + * Set muted state + * @param {boolean} mute + */ + + }, { + key: "toggleCaptions", + + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + value: function toggleCaptions(input) { + captions.toggle.call(this, input, false); + } + /** + * Set the caption track by index + * @param {number} - Caption index + */ + + }, { + key: "airplay", + + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + value: function airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); + } + } + /** + * Toggle the player controls + * @param {boolean} [toggle] - Whether to show the controls + */ + + }, { + key: "toggleControls", + value: function toggleControls(toggle) { + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + var isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls + + var force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state + + var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu + + if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); + } // Trigger event on change + + + if (hiding !== isHidden) { + var eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); + } + + return !hiding; + } + + return false; + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + on.call(this, this.elements.container, event, callback); + } + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "once", + value: function once$$1(event, callback) { + once.call(this, this.elements.container, event, callback); + } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "off", + value: function off$$1(event, callback) { + off(this.elements.container, event, callback); + } + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ + + }, { + key: "destroy", + value: function destroy(callback) { + var _this2 = this; + + var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!this.ready) { + return; + } + + var done = function done() { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; // GC for embed + + _this2.embed = null; // If it's a soft destroy, make minimal changes + + if (soft) { + if (Object.keys(_this2.elements).length) { + // Remove elements + removeElement(_this2.elements.buttons.play); + removeElement(_this2.elements.captions); + removeElement(_this2.elements.controls); + removeElement(_this2.elements.wrapper); // Clear for GC + + _this2.elements.buttons.play = null; + _this2.elements.captions = null; + _this2.elements.controls = null; + _this2.elements.wrapper = null; + } // Callback + + + if (is.function(callback)) { + callback(); + } + } else { + // Unbind listeners + unbindListeners.call(_this2); // Replace the container with the original element provided + + replaceElement(_this2.elements.original, _this2.elements.container); // Event + + triggerEvent.call(_this2, _this2.elements.original, 'destroyed', true); // Callback + + if (is.function(callback)) { + callback.call(_this2.elements.original); + } // Reset state + + + _this2.ready = false; // Clear for garbage collection + + setTimeout(function () { + _this2.elements = null; + _this2.media = null; + }, 200); + } + }; // Stop playback + + + this.stop(); // Provider specific stuff + + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); // Restore native video controls + + ui.toggleNativeControls.call(this, true); // Clean up + + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); // Destroy YouTube API + + if (this.embed !== null && is.function(this.embed.destroy)) { + this.embed.destroy(); + } // Clean up + + + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } // Vimeo does not always return + + + setTimeout(done, 200); + } + } + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ + + }, { + key: "supports", + value: function supports(type) { + return support.mime.call(this, type); + } + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ + + }, { + key: "isHTML5", + get: function get() { + return Boolean(this.provider === providers.html5); + } + }, { + key: "isEmbed", + get: function get() { + return Boolean(this.isYouTube || this.isVimeo); + } + }, { + key: "isYouTube", + get: function get() { + return Boolean(this.provider === providers.youtube); + } + }, { + key: "isVimeo", + get: function get() { + return Boolean(this.provider === providers.vimeo); + } + }, { + key: "isVideo", + get: function get() { + return Boolean(this.type === types.video); + } + }, { + key: "isAudio", + get: function get() { + return Boolean(this.type === types.audio); + } + }, { + key: "playing", + get: function get() { + return Boolean(this.ready && !this.paused && !this.ended); + } + /** + * Get paused state + */ + + }, { + key: "paused", + get: function get() { + return Boolean(this.media.paused); + } + /** + * Get stopped state + */ + + }, { + key: "stopped", + get: function get() { + return Boolean(this.paused && this.currentTime === 0); + } + /** + * Get ended state + */ + + }, { + key: "ended", + get: function get() { + return Boolean(this.media.ended); + } + }, { + key: "currentTime", + set: function set(input) { + // Bail if media duration isn't available yet + if (!this.duration) { + return; + } // Validate input + + + var inputIsValid = is.number(input) && input > 0; // Set + + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging + + this.debug.log("Seeking to ".concat(this.currentTime, " seconds")); + } + /** + * Get current time + */ + , + get: function get() { + return Number(this.media.currentTime); + } + /** + * Get buffered + */ + + }, { + key: "buffered", + get: function get() { + var buffered = this.media.buffered; // YouTube / Vimeo return a float between 0-1 + + if (is.number(buffered)) { + return buffered; + } // HTML5 + // TODO: Handle buffered chunks of the media + // (i.e. seek to another section buffers only that section) + + + if (buffered && buffered.length && this.duration > 0) { + return buffered.end(0) / this.duration; + } + + return 0; + } + /** + * Get seeking status + */ + + }, { + key: "seeking", + get: function get() { + return Boolean(this.media.seeking); + } + /** + * Get the duration of the current media + */ + + }, { + key: "duration", + get: function get() { + // Faux duration set via config + var fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded + + var realDuration = (this.media || {}).duration; + var duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration + + return fauxDuration || duration; + } + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ + + }, { + key: "volume", + set: function set(value) { + var volume = value; + var max = 1; + var min = 0; + + if (is.string(volume)) { + volume = Number(volume); + } // Load volume from storage if no value specified + + + if (!is.number(volume)) { + volume = this.storage.get('volume'); + } // Use config if all else fails + + + if (!is.number(volume)) { + volume = this.config.volume; + } // Maximum is volumeMax + + + if (volume > max) { + volume = max; + } // Minimum is volumeMin + + + if (volume < min) { + volume = min; + } // Update config + + + this.config.volume = volume; // Set the player volume + + this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state + + if (!is.empty(value) && this.muted && volume > 0) { + this.muted = false; + } + } + /** + * Get the current player volume + */ + , + get: function get() { + return Number(this.media.volume); + } + }, { + key: "muted", + set: function set(mute) { + var toggle = mute; // Load muted state from storage + + if (!is.boolean(toggle)) { + toggle = this.storage.get('muted'); + } // Use config if all else fails + + + if (!is.boolean(toggle)) { + toggle = this.config.muted; + } // Update config + + + this.config.muted = toggle; // Set mute on the player + + this.media.muted = toggle; + } + /** + * Get current muted state + */ + , + get: function get() { + return Boolean(this.media.muted); + } + /** + * Check if the media has audio + */ + + }, { + key: "hasAudio", + get: function get() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; + } + + if (this.isAudio) { + return true; + } // Get audio tracks + + + return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } + /** + * Set playback speed + * @param {number} speed - the speed of playback (0.5-2.0) + */ + + }, { + key: "speed", + set: function set(input) { + var speed = null; + + if (is.number(input)) { + speed = input; + } + + if (!is.number(speed)) { + speed = this.storage.get('speed'); + } + + if (!is.number(speed)) { + speed = this.config.speed.selected; + } // Set min/max + + + if (speed < 0.1) { + speed = 0.1; + } + + if (speed > 2.0) { + speed = 2.0; + } + + if (!this.config.speed.options.includes(speed)) { + this.debug.warn("Unsupported speed (".concat(speed, ")")); + return; + } // Update config + + + this.config.speed.selected = speed; // Set media speed + + this.media.playbackRate = speed; + } + /** + * Get current playback speed + */ + , + get: function get() { + return Number(this.media.playbackRate); + } + /** + * Set playback quality + * Currently HTML5 & YouTube only + * @param {number} input - Quality level + */ + + }, { + key: "quality", + set: function set(input) { + var config = this.config.quality; + var options = this.options.quality; + + if (!options.length) { + return; + } + + var quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number); + var updateStorage = true; + + if (!options.includes(quality)) { + var value = closest(options, quality); + this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); + quality = value; // Don't update storage if quality is not supported + + updateStorage = false; + } // Update config + + + config.selected = quality; // Set quality + + this.media.quality = quality; // Save to storage + + if (updateStorage) { + this.storage.set({ + quality: quality + }); + } + } + /** + * Get current quality level + */ + , + get: function get() { + return this.media.quality; + } + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ + + }, { + key: "loop", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; // Set default to be a true toggle + + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; + } + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; + } + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; + case 'toggle': + if (this.config.loop.active) { + this.config.loop.start = 0; + this.config.loop.end = null; + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } + /** + * Get current loop state + */ + , + get: function get() { + return Boolean(this.media.loop); + } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ + + }, { + key: "source", + set: function set(input) { + source.change.call(this, input); + } + /** + * Get current source + */ + , + get: function get() { + return this.media.currentSrc; + } + /** + * Get a download URL (either source or custom) + */ + + }, { + key: "download", + get: function get() { + var download = this.config.urls.download; + return is.url(download) ? download : this.source; + } + /** + * Set the poster image for a video + * @param {input} - the URL for the new poster image + */ + + }, { + key: "poster", + set: function set(input) { + if (!this.isVideo) { + this.debug.warn('Poster can only be set for video'); + return; + } + + ui.setPoster.call(this, input, false).catch(function () {}); + } + /** + * Get the current poster image + */ + , + get: function get() { + if (!this.isVideo) { + return null; + } + + return this.media.getAttribute('poster'); + } + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ + + }, { + key: "autoplay", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } + /** + * Get the current autoplay state + */ + , + get: function get() { + return Boolean(this.config.autoplay); + } + }, { + key: "currentTrack", + set: function set(input) { + captions.set.call(this, input, false); + } + /** + * Get the current caption track index (-1 if disabled) + */ + , + get: function get() { + var _this$captions = this.captions, + toggled = _this$captions.toggled, + currentTrack = _this$captions.currentTrack; + return toggled ? currentTrack : -1; + } + /** + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ + + }, { + key: "language", + set: function set(input) { + captions.setLanguage.call(this, input, false); + } + /** + * Get the current track's language + */ + , + get: function get() { + return (captions.getCurrentTrack.call(this) || {}).language; + } + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ + + }, { + key: "pip", + set: function set(input) { + // Bail if no support + if (!support.pip) { + return; + } // Toggle based on current state if not passed + + + var toggle = is.boolean(input) ? input : !this.pip; // Toggle based on current state + // Safari + + if (is.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } // Chrome + + + if (is.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } + } + } + /** + * Get the current picture-in-picture state + */ + , + get: function get() { + if (!support.pip) { + return null; + } // Safari + + + if (!is.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } // Chrome + + + return this.media === document.pictureInPictureElement; + } + }], [{ + key: "supported", + value: function supported(type, provider, inline) { + return support.check(type, provider, inline); + } + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ + + }, { + key: "loadSprite", + value: function loadSprite$$1(url, id) { + return loadSprite(url, id); + } + /** + * Setup multiple instances + * @param {*} selector + * @param {object} options + */ + + }, { + key: "setup", + value: function setup(selector) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var targets = null; + + if (is.string(selector)) { + targets = Array.from(document.querySelectorAll(selector)); + } else if (is.nodeList(selector)) { + targets = Array.from(selector); + } else if (is.array(selector)) { + targets = selector.filter(is.element); + } + + if (is.empty(targets)) { + return null; + } + + return targets.map(function (t) { + return new Plyr(t, options); + }); + } + }]); + + return Plyr; + }(); + + Plyr.defaults = cloneDeep(defaults); + + // ========================================================================== + + (function () { + var host = window.location.host; + var env = { + prod: host === 'plyr.io', + dev: host === 'dev.plyr.io' + }; + document.addEventListener('DOMContentLoaded', function () { + singleton.context(function () { + var selector = '#player'; + var container = document.getElementById('container'); + + if (window.shr) { + window.shr.setup({ + count: { + classname: 'button__count' + } + }); + } // Setup tab focus + + + var tabClassName = 'tab-focus'; // Remove class on blur + + document.addEventListener('focusout', function (event) { + if (!event.target.classList || container.contains(event.target)) { + return; + } + + event.target.classList.remove(tabClassName); + }); // Add classname to tabbed elements + + document.addEventListener('keydown', function (event) { + if (event.keyCode !== 9) { + return; + } // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + + + setTimeout(function () { + var focused = document.activeElement; + + if (!focused || !focused.classList || container.contains(focused)) { + return; + } + + focused.classList.add(tabClassName); + }, 10); + }); // Setup the player + + var player = new Plyr(selector, { + debug: true, + title: 'View From A Blue Moon', + iconUrl: 'dist/plyr.svg', + keyboard: { + global: true + }, + tooltips: { + controls: true + }, + captions: { + active: true + }, + keys: { + google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c' + }, + ads: { + enabled: env.prod || env.dev, + publisherId: '918848828995742' + }, + previewThumbnails: { + enabled: true, + src: ['https://cdn.plyr.io/static/demo/thumbs/100p.vtt', 'https://cdn.plyr.io/static/demo/thumbs/240p.vtt'] + } + }); // Expose for tinkering in the console + + window.player = player; // Setup type toggle + + var buttons = document.querySelectorAll('[data-source]'); + var types = { + video: 'video', + audio: 'audio', + youtube: 'youtube', + vimeo: 'vimeo' + }; + var currentType = window.location.hash.replace('#', ''); + var historySupport = window.history && window.history.pushState; // Toggle class on an element + + function toggleClass(element, className, state) { + if (element) { + element.classList[state ? 'add' : 'remove'](className); + } + } // Set a new source + + + function newSource(type, init) { + // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video + if (!(type in types) || !init && type === currentType || !currentType.length && type === types.video) { + return; + } + + switch (type) { + case types.video: + player.source = { + type: 'video', + title: 'View From A Blue Moon', + sources: [{ + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4', + type: 'video/mp4', + size: 576 + }, { + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4', + type: 'video/mp4', + size: 720 + }, { + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4', + type: 'video/mp4', + size: 1080 + }, { + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4', + type: 'video/mp4', + size: 1440 + }], + poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', + tracks: [{ + kind: 'captions', + label: 'English', + srclang: 'en', + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + default: true + }, { + kind: 'captions', + label: 'French', + srclang: 'fr', + src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt' + }] + }; + break; + + case types.audio: + player.source = { + type: 'audio', + title: 'Kishi Bashi – “It All Began With A Burst”', + sources: [{ + src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3', + type: 'audio/mp3' + }, { + src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg', + type: 'audio/ogg' + }] + }; + break; + + case types.youtube: + player.source = { + type: 'video', + sources: [{ + src: 'https://youtube.com/watch?v=bTqVqk7FSmY', + provider: 'youtube' + }] + }; + break; + + case types.vimeo: + player.source = { + type: 'video', + sources: [{ + src: 'https://vimeo.com/76979871', + provider: 'vimeo' + }] + }; + break; + + default: + break; + } // Set the current type for next time + + + currentType = type; // Remove active classes + + Array.from(buttons).forEach(function (button) { + return toggleClass(button.parentElement, 'active', false); + }); // Set active on parent + + toggleClass(document.querySelector("[data-source=\"".concat(type, "\"]")), 'active', true); // Show cite + + Array.from(document.querySelectorAll('.plyr__cite')).forEach(function (cite) { + cite.setAttribute('hidden', ''); + }); + document.querySelector(".plyr__cite--".concat(type)).removeAttribute('hidden'); + } // Bind to each button + + + Array.from(buttons).forEach(function (button) { + button.addEventListener('click', function () { + var type = button.getAttribute('data-source'); + newSource(type); + + if (historySupport) { + window.history.pushState({ + type: type + }, '', "#".concat(type)); + } + }); + }); // List for backwards/forwards + + window.addEventListener('popstate', function (event) { + if (event.state && 'type' in event.state) { + newSource(event.state.type); + } + }); // On load + + if (historySupport) { + var video = !currentType.length; // If there's no current type set, assume video + + if (video) { + currentType = types.video; + } // Replace current history state + + + if (currentType in types) { + window.history.replaceState({ + type: currentType + }, '', video ? '' : "#".concat(currentType)); + } // If it's not video, load the source + + + if (currentType !== types.video) { + newSource(currentType, true); + } + } + }); + }); // Raven / Sentry + // For demo site (https://plyr.io) only + + if (env.prod) { + singleton.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install(); + } + })(); + +}()); diff --git a/demo/dist/demo.js.map b/demo/dist/demo.js.map deleted file mode 100644 index fe867317..00000000 --- a/demo/dist/demo.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../../node_modules/raven-js/vendor/json-stringify-safe/stringify.js","../../../node_modules/raven-js/src/utils.js","../../../node_modules/raven-js/vendor/TraceKit/tracekit.js","../../../node_modules/raven-js/vendor/md5/md5.js","../../../node_modules/raven-js/src/configError.js","../../../node_modules/raven-js/src/console.js","../../../node_modules/raven-js/src/raven.js","../../../node_modules/raven-js/src/singleton.js","demo.js"],"names":["global","stringify","_window","isError","isObject","isPlainObject","isErrorEvent","isUndefined","isFunction","isString","isArray","isEmptyObject","each","objectMerge","truncate","objectFrozen","hasKey","joinRegExp","urlencode","uuid4","htmlTreeAsString","isSameException","isSameStacktrace","parseUrl","fill","supportsFetch","supportsReferrerPolicy","serializeKeysForMessage","serializeException","sanitize","require$$0","TraceKit","md5","RavenConfigError","Raven","RavenConstructor","isLive","window","location","host","config","install","addEventListener","context","shr","setup","tabClassName","target","classList","remove","event","keyCode","activeElement","add","player","Plyr","buttons","document","querySelectorAll","types","currentType","hash","replace","historySupport","history","pushState","toggleClass","element","className","state","newSource","type","init","length","video","source","audio","youtube","vimeo","from","forEach","button","parentElement","querySelector","setAttribute","removeAttribute","getAttribute","replaceState","i","s","o","g","r","a","m","GoogleAnalyticsObject","q","push","arguments","l","Date","createElement","getElementsByTagName","async","src","parentNode","insertBefore","ga"],"mappings":"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","file":"demo.js","sourcesContent":["/*\n json-stringify-safe\n Like JSON.stringify, but doesn't throw on circular references.\n\n Originally forked from https://github.com/isaacs/json-stringify-safe\n version 5.0.1 on 3/8/2017 and modified to handle Errors serialization\n and IE8 compatibility. Tests for this are in test/vendor.\n\n ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE\n*/\n\nexports = module.exports = stringify;\nexports.getSerialize = serializer;\n\nfunction indexOf(haystack, needle) {\n for (var i = 0; i < haystack.length; ++i) {\n if (haystack[i] === needle) return i;\n }\n return -1;\n}\n\nfunction stringify(obj, replacer, spaces, cycleReplacer) {\n return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);\n}\n\n// https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106\nfunction stringifyError(value) {\n var err = {\n // These properties are implemented as magical getters and don't show up in for in\n stack: value.stack,\n message: value.message,\n name: value.name\n };\n\n for (var i in value) {\n if (Object.prototype.hasOwnProperty.call(value, i)) {\n err[i] = value[i];\n }\n }\n\n return err;\n}\n\nfunction serializer(replacer, cycleReplacer) {\n var stack = [];\n var keys = [];\n\n if (cycleReplacer == null) {\n cycleReplacer = function(key, value) {\n if (stack[0] === value) {\n return '[Circular ~]';\n }\n return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']';\n };\n }\n\n return function(key, value) {\n if (stack.length > 0) {\n var thisPos = indexOf(stack, this);\n ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);\n ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);\n\n if (~indexOf(stack, value)) {\n value = cycleReplacer.call(this, key, value);\n }\n } else {\n stack.push(value);\n }\n\n return replacer == null\n ? value instanceof Error ? stringifyError(value) : value\n : replacer.call(this, key, value);\n };\n}\n","var stringify = require('../vendor/json-stringify-safe/stringify');\n\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\nfunction isObject(what) {\n return typeof what === 'object' && what !== null;\n}\n\n// Yanked from https://git.io/vS8DV re-used under CC0\n// with some tiny modifications\nfunction isError(value) {\n switch ({}.toString.call(value)) {\n case '[object Error]':\n return true;\n case '[object Exception]':\n return true;\n case '[object DOMException]':\n return true;\n default:\n return value instanceof Error;\n }\n}\n\nfunction isErrorEvent(value) {\n return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]';\n}\n\nfunction isUndefined(what) {\n return what === void 0;\n}\n\nfunction isFunction(what) {\n return typeof what === 'function';\n}\n\nfunction isPlainObject(what) {\n return Object.prototype.toString.call(what) === '[object Object]';\n}\n\nfunction isString(what) {\n return Object.prototype.toString.call(what) === '[object String]';\n}\n\nfunction isArray(what) {\n return Object.prototype.toString.call(what) === '[object Array]';\n}\n\nfunction isEmptyObject(what) {\n if (!isPlainObject(what)) return false;\n\n for (var _ in what) {\n if (what.hasOwnProperty(_)) {\n return false;\n }\n }\n return true;\n}\n\nfunction supportsErrorEvent() {\n try {\n new ErrorEvent(''); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsFetch() {\n if (!('fetch' in _window)) return false;\n\n try {\n new Headers(); // eslint-disable-line no-new\n new Request(''); // eslint-disable-line no-new\n new Response(); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\n// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n// https://caniuse.com/#feat=referrer-policy\n// It doesn't. And it throw exception instead of ignoring this parameter...\n// REF: https://github.com/getsentry/raven-js/issues/1233\nfunction supportsReferrerPolicy() {\n if (!supportsFetch()) return false;\n\n try {\n // eslint-disable-next-line no-new\n new Request('pickleRick', {\n referrerPolicy: 'origin'\n });\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsPromiseRejectionEvent() {\n return typeof PromiseRejectionEvent === 'function';\n}\n\nfunction wrappedCallback(callback) {\n function dataCallback(data, original) {\n var normalizedData = callback(data) || data;\n if (original) {\n return original(normalizedData) || normalizedData;\n }\n return normalizedData;\n }\n\n return dataCallback;\n}\n\nfunction each(obj, callback) {\n var i, j;\n\n if (isUndefined(obj.length)) {\n for (i in obj) {\n if (hasKey(obj, i)) {\n callback.call(null, i, obj[i]);\n }\n }\n } else {\n j = obj.length;\n if (j) {\n for (i = 0; i < j; i++) {\n callback.call(null, i, obj[i]);\n }\n }\n }\n}\n\nfunction objectMerge(obj1, obj2) {\n if (!obj2) {\n return obj1;\n }\n each(obj2, function(key, value) {\n obj1[key] = value;\n });\n return obj1;\n}\n\n/**\n * This function is only used for react-native.\n * react-native freezes object that have already been sent over the\n * js bridge. We need this function in order to check if the object is frozen.\n * So it's ok that objectFrozen returns false if Object.isFrozen is not\n * supported because it's not relevant for other \"platforms\". See related issue:\n * https://github.com/getsentry/react-native-sentry/issues/57\n */\nfunction objectFrozen(obj) {\n if (!Object.isFrozen) {\n return false;\n }\n return Object.isFrozen(obj);\n}\n\nfunction truncate(str, max) {\n if (typeof max !== 'number') {\n throw new Error('2nd argument to `truncate` function should be a number');\n }\n if (typeof str !== 'string' || max === 0) {\n return str;\n }\n return str.length <= max ? str : str.substr(0, max) + '\\u2026';\n}\n\n/**\n * hasKey, a better form of hasOwnProperty\n * Example: hasKey(MainHostObject, property) === true/false\n *\n * @param {Object} host object to check property\n * @param {string} key to check\n */\nfunction hasKey(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\nfunction joinRegExp(patterns) {\n // Combine an array of regular expressions and strings into one large regexp\n // Be mad.\n var sources = [],\n i = 0,\n len = patterns.length,\n pattern;\n\n for (; i < len; i++) {\n pattern = patterns[i];\n if (isString(pattern)) {\n // If it's a string, we need to escape it\n // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n sources.push(pattern.replace(/([.*+?^=!:${}()|\\[\\]\\/\\\\])/g, '\\\\$1'));\n } else if (pattern && pattern.source) {\n // If it's a regexp already, we want to extract the source\n sources.push(pattern.source);\n }\n // Intentionally skip other cases\n }\n return new RegExp(sources.join('|'), 'i');\n}\n\nfunction urlencode(o) {\n var pairs = [];\n each(o, function(key, value) {\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n });\n return pairs.join('&');\n}\n\n// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B\n// intentionally using regex and not <a/> href parsing trick because React Native and other\n// environments where DOM might not be available\nfunction parseUrl(url) {\n if (typeof url !== 'string') return {};\n var match = url.match(/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$/);\n\n // coerce to undefined values to empty string so we don't get 'undefined'\n var query = match[6] || '';\n var fragment = match[8] || '';\n return {\n protocol: match[2],\n host: match[4],\n path: match[5],\n relative: match[5] + query + fragment // everything minus origin\n };\n}\nfunction uuid4() {\n var crypto = _window.crypto || _window.msCrypto;\n\n if (!isUndefined(crypto) && crypto.getRandomValues) {\n // Use window.crypto API if available\n // eslint-disable-next-line no-undef\n var arr = new Uint16Array(8);\n crypto.getRandomValues(arr);\n\n // set 4 in byte 7\n arr[3] = (arr[3] & 0xfff) | 0x4000;\n // set 2 most significant bits of byte 9 to '10'\n arr[4] = (arr[4] & 0x3fff) | 0x8000;\n\n var pad = function(num) {\n var v = num.toString(16);\n while (v.length < 4) {\n v = '0' + v;\n }\n return v;\n };\n\n return (\n pad(arr[0]) +\n pad(arr[1]) +\n pad(arr[2]) +\n pad(arr[3]) +\n pad(arr[4]) +\n pad(arr[5]) +\n pad(arr[6]) +\n pad(arr[7])\n );\n } else {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523\n return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (Math.random() * 16) | 0,\n v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @param elem\n * @returns {string}\n */\nfunction htmlTreeAsString(elem) {\n /* eslint no-extra-parens:0*/\n var MAX_TRAVERSE_HEIGHT = 5,\n MAX_OUTPUT_LEN = 80,\n out = [],\n height = 0,\n len = 0,\n separator = ' > ',\n sepLength = separator.length,\n nextStr;\n\n while (elem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = htmlElementAsString(elem);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds MAX_OUTPUT_LEN\n // (ignore this limit if we are on the first iteration)\n if (\n nextStr === 'html' ||\n (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)\n ) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n elem = elem.parentNode;\n }\n\n return out.reverse().join(separator);\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @param HTMLElement\n * @returns {string}\n */\nfunction htmlElementAsString(elem) {\n var out = [],\n className,\n classes,\n key,\n attr,\n i;\n\n if (!elem || !elem.tagName) {\n return '';\n }\n\n out.push(elem.tagName.toLowerCase());\n if (elem.id) {\n out.push('#' + elem.id);\n }\n\n className = elem.className;\n if (className && isString(className)) {\n classes = className.split(/\\s+/);\n for (i = 0; i < classes.length; i++) {\n out.push('.' + classes[i]);\n }\n }\n var attrWhitelist = ['type', 'name', 'title', 'alt'];\n for (i = 0; i < attrWhitelist.length; i++) {\n key = attrWhitelist[i];\n attr = elem.getAttribute(key);\n if (attr) {\n out.push('[' + key + '=\"' + attr + '\"]');\n }\n }\n return out.join('');\n}\n\n/**\n * Returns true if either a OR b is truthy, but not both\n */\nfunction isOnlyOneTruthy(a, b) {\n return !!(!!a ^ !!b);\n}\n\n/**\n * Returns true if both parameters are undefined\n */\nfunction isBothUndefined(a, b) {\n return isUndefined(a) && isUndefined(b);\n}\n\n/**\n * Returns true if the two input exception interfaces have the same content\n */\nfunction isSameException(ex1, ex2) {\n if (isOnlyOneTruthy(ex1, ex2)) return false;\n\n ex1 = ex1.values[0];\n ex2 = ex2.values[0];\n\n if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false;\n\n // in case both stacktraces are undefined, we can't decide so default to false\n if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false;\n\n return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);\n}\n\n/**\n * Returns true if the two input stack trace interfaces have the same content\n */\nfunction isSameStacktrace(stack1, stack2) {\n if (isOnlyOneTruthy(stack1, stack2)) return false;\n\n var frames1 = stack1.frames;\n var frames2 = stack2.frames;\n\n // Exit early if frame count differs\n if (frames1.length !== frames2.length) return false;\n\n // Iterate through every frame; bail out if anything differs\n var a, b;\n for (var i = 0; i < frames1.length; i++) {\n a = frames1[i];\n b = frames2[i];\n if (\n a.filename !== b.filename ||\n a.lineno !== b.lineno ||\n a.colno !== b.colno ||\n a['function'] !== b['function']\n )\n return false;\n }\n return true;\n}\n\n/**\n * Polyfill a method\n * @param obj object e.g. `document`\n * @param name method name present on object e.g. `addEventListener`\n * @param replacement replacement function\n * @param track {optional} record instrumentation to an array\n */\nfunction fill(obj, name, replacement, track) {\n if (obj == null) return;\n var orig = obj[name];\n obj[name] = replacement(orig);\n obj[name].__raven__ = true;\n obj[name].__orig__ = orig;\n if (track) {\n track.push([obj, name, orig]);\n }\n}\n\n/**\n * Join values in array\n * @param input array of values to be joined together\n * @param delimiter string to be placed in-between values\n * @returns {string}\n */\nfunction safeJoin(input, delimiter) {\n if (!isArray(input)) return '';\n\n var output = [];\n\n for (var i = 0; i < input.length; i++) {\n try {\n output.push(String(input[i]));\n } catch (e) {\n output.push('[value cannot be serialized]');\n }\n }\n\n return output.join(delimiter);\n}\n\n// Default Node.js REPL depth\nvar MAX_SERIALIZE_EXCEPTION_DEPTH = 3;\n// 50kB, as 100kB is max payload size, so half sounds reasonable\nvar MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024;\nvar MAX_SERIALIZE_KEYS_LENGTH = 40;\n\nfunction utf8Length(value) {\n return ~-encodeURI(value).split(/%..|./).length;\n}\n\nfunction jsonSize(value) {\n return utf8Length(JSON.stringify(value));\n}\n\nfunction serializeValue(value) {\n if (typeof value === 'string') {\n var maxLength = 40;\n return truncate(value, maxLength);\n } else if (\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'undefined'\n ) {\n return value;\n }\n\n var type = Object.prototype.toString.call(value);\n\n // Node.js REPL notation\n if (type === '[object Object]') return '[Object]';\n if (type === '[object Array]') return '[Array]';\n if (type === '[object Function]')\n return value.name ? '[Function: ' + value.name + ']' : '[Function]';\n\n return value;\n}\n\nfunction serializeObject(value, depth) {\n if (depth === 0) return serializeValue(value);\n\n if (isPlainObject(value)) {\n return Object.keys(value).reduce(function(acc, key) {\n acc[key] = serializeObject(value[key], depth - 1);\n return acc;\n }, {});\n } else if (Array.isArray(value)) {\n return value.map(function(val) {\n return serializeObject(val, depth - 1);\n });\n }\n\n return serializeValue(value);\n}\n\nfunction serializeException(ex, depth, maxSize) {\n if (!isPlainObject(ex)) return ex;\n\n depth = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_DEPTH : depth;\n maxSize = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_SIZE : maxSize;\n\n var serialized = serializeObject(ex, depth);\n\n if (jsonSize(stringify(serialized)) > maxSize) {\n return serializeException(ex, depth - 1);\n }\n\n return serialized;\n}\n\nfunction serializeKeysForMessage(keys, maxLength) {\n if (typeof keys === 'number' || typeof keys === 'string') return keys.toString();\n if (!Array.isArray(keys)) return '';\n\n keys = keys.filter(function(key) {\n return typeof key === 'string';\n });\n if (keys.length === 0) return '[object has no keys]';\n\n maxLength = typeof maxLength !== 'number' ? MAX_SERIALIZE_KEYS_LENGTH : maxLength;\n if (keys[0].length >= maxLength) return keys[0];\n\n for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) {\n var serialized = keys.slice(0, usedKeys).join(', ');\n if (serialized.length > maxLength) continue;\n if (usedKeys === keys.length) return serialized;\n return serialized + '\\u2026';\n }\n\n return '';\n}\n\nfunction sanitize(input, sanitizeKeys) {\n if (!isArray(sanitizeKeys) || (isArray(sanitizeKeys) && sanitizeKeys.length === 0))\n return input;\n\n var sanitizeRegExp = joinRegExp(sanitizeKeys);\n var sanitizeMask = '********';\n var safeInput;\n\n try {\n safeInput = JSON.parse(stringify(input));\n } catch (o_O) {\n return input;\n }\n\n function sanitizeWorker(workerInput) {\n if (isArray(workerInput)) {\n return workerInput.map(function(val) {\n return sanitizeWorker(val);\n });\n }\n\n if (isPlainObject(workerInput)) {\n return Object.keys(workerInput).reduce(function(acc, k) {\n if (sanitizeRegExp.test(k)) {\n acc[k] = sanitizeMask;\n } else {\n acc[k] = sanitizeWorker(workerInput[k]);\n }\n return acc;\n }, {});\n }\n\n return workerInput;\n }\n\n return sanitizeWorker(safeInput);\n}\n\nmodule.exports = {\n isObject: isObject,\n isError: isError,\n isErrorEvent: isErrorEvent,\n isUndefined: isUndefined,\n isFunction: isFunction,\n isPlainObject: isPlainObject,\n isString: isString,\n isArray: isArray,\n isEmptyObject: isEmptyObject,\n supportsErrorEvent: supportsErrorEvent,\n supportsFetch: supportsFetch,\n supportsReferrerPolicy: supportsReferrerPolicy,\n supportsPromiseRejectionEvent: supportsPromiseRejectionEvent,\n wrappedCallback: wrappedCallback,\n each: each,\n objectMerge: objectMerge,\n truncate: truncate,\n objectFrozen: objectFrozen,\n hasKey: hasKey,\n joinRegExp: joinRegExp,\n urlencode: urlencode,\n uuid4: uuid4,\n htmlTreeAsString: htmlTreeAsString,\n htmlElementAsString: htmlElementAsString,\n isSameException: isSameException,\n isSameStacktrace: isSameStacktrace,\n parseUrl: parseUrl,\n fill: fill,\n safeJoin: safeJoin,\n serializeException: serializeException,\n serializeKeysForMessage: serializeKeysForMessage,\n sanitize: sanitize\n};\n","var utils = require('../../src/utils');\n\n/*\n TraceKit - Cross brower stack traces\n\n This was originally forked from github.com/occ/TraceKit, but has since been\n largely re-written and is now maintained as part of raven-js. Tests for\n this are in test/vendor.\n\n MIT license\n*/\n\nvar TraceKit = {\n collectWindowErrors: true,\n debug: false\n};\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n// global reference to slice\nvar _slice = [].slice;\nvar UNKNOWN_FUNCTION = '?';\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types\nvar ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;\n\nfunction getLocationHref() {\n if (typeof document === 'undefined' || document.location == null) return '';\n\n return document.location.href;\n}\n\n/**\n * TraceKit.report: cross-browser processing of unhandled exceptions\n *\n * Syntax:\n * TraceKit.report.subscribe(function(stackInfo) { ... })\n * TraceKit.report.unsubscribe(function(stackInfo) { ... })\n * TraceKit.report(exception)\n * try { ...code... } catch(ex) { TraceKit.report(ex); }\n *\n * Supports:\n * - Firefox: full stack trace with line numbers, plus column number\n * on top frame; column number is not guaranteed\n * - Opera: full stack trace with line and column numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n * - IE: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n *\n * In theory, TraceKit should work on all of the following versions:\n * - IE5.5+ (only 8.0 tested)\n * - Firefox 0.9+ (only 3.5+ tested)\n * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require\n * Exceptions Have Stacktrace to be enabled in opera:config)\n * - Safari 3+ (only 4+ tested)\n * - Chrome 1+ (only 5+ tested)\n * - Konqueror 3.5+ (untested)\n *\n * Requires TraceKit.computeStackTrace.\n *\n * Tries to catch all unhandled exceptions and report them to the\n * subscribed handlers. Please note that TraceKit.report will rethrow the\n * exception. This is REQUIRED in order to get a useful stack trace in IE.\n * If the exception does not reach the top of the browser, you will only\n * get a stack trace from the point where TraceKit.report was called.\n *\n * Handlers receive a stackInfo object as described in the\n * TraceKit.computeStackTrace docs.\n */\nTraceKit.report = (function reportModuleWrapper() {\n var handlers = [],\n lastArgs = null,\n lastException = null,\n lastExceptionStack = null;\n\n /**\n * Add a crash handler.\n * @param {Function} handler\n */\n function subscribe(handler) {\n installGlobalHandler();\n handlers.push(handler);\n }\n\n /**\n * Remove a crash handler.\n * @param {Function} handler\n */\n function unsubscribe(handler) {\n for (var i = handlers.length - 1; i >= 0; --i) {\n if (handlers[i] === handler) {\n handlers.splice(i, 1);\n }\n }\n }\n\n /**\n * Remove all crash handlers.\n */\n function unsubscribeAll() {\n uninstallGlobalHandler();\n handlers = [];\n }\n\n /**\n * Dispatch stack information to all handlers.\n * @param {Object.<string, *>} stack\n */\n function notifyHandlers(stack, isWindowError) {\n var exception = null;\n if (isWindowError && !TraceKit.collectWindowErrors) {\n return;\n }\n for (var i in handlers) {\n if (handlers.hasOwnProperty(i)) {\n try {\n handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));\n } catch (inner) {\n exception = inner;\n }\n }\n }\n\n if (exception) {\n throw exception;\n }\n }\n\n var _oldOnerrorHandler, _onErrorHandlerInstalled;\n\n /**\n * Ensures all global unhandled exceptions are recorded.\n * Supported by Gecko and IE.\n * @param {string} msg Error message.\n * @param {string} url URL of script that generated the exception.\n * @param {(number|string)} lineNo The line number at which the error\n * occurred.\n * @param {?(number|string)} colNo The column number at which the error\n * occurred.\n * @param {?Error} ex The actual Error object.\n */\n function traceKitWindowOnError(msg, url, lineNo, colNo, ex) {\n var stack = null;\n // If 'ex' is ErrorEvent, get real Error from inside\n var exception = utils.isErrorEvent(ex) ? ex.error : ex;\n // If 'msg' is ErrorEvent, get real message from inside\n var message = utils.isErrorEvent(msg) ? msg.message : msg;\n\n if (lastExceptionStack) {\n TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(\n lastExceptionStack,\n url,\n lineNo,\n message\n );\n processLastException();\n } else if (exception && utils.isError(exception)) {\n // non-string `exception` arg; attempt to extract stack trace\n\n // New chrome and blink send along a real error object\n // Let's just report that like a normal error.\n // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror\n stack = TraceKit.computeStackTrace(exception);\n notifyHandlers(stack, true);\n } else {\n var location = {\n url: url,\n line: lineNo,\n column: colNo\n };\n\n var name = undefined;\n var groups;\n\n if ({}.toString.call(message) === '[object String]') {\n var groups = message.match(ERROR_TYPES_RE);\n if (groups) {\n name = groups[1];\n message = groups[2];\n }\n }\n\n location.func = UNKNOWN_FUNCTION;\n\n stack = {\n name: name,\n message: message,\n url: getLocationHref(),\n stack: [location]\n };\n notifyHandlers(stack, true);\n }\n\n if (_oldOnerrorHandler) {\n return _oldOnerrorHandler.apply(this, arguments);\n }\n\n return false;\n }\n\n function installGlobalHandler() {\n if (_onErrorHandlerInstalled) {\n return;\n }\n _oldOnerrorHandler = _window.onerror;\n _window.onerror = traceKitWindowOnError;\n _onErrorHandlerInstalled = true;\n }\n\n function uninstallGlobalHandler() {\n if (!_onErrorHandlerInstalled) {\n return;\n }\n _window.onerror = _oldOnerrorHandler;\n _onErrorHandlerInstalled = false;\n _oldOnerrorHandler = undefined;\n }\n\n function processLastException() {\n var _lastExceptionStack = lastExceptionStack,\n _lastArgs = lastArgs;\n lastArgs = null;\n lastExceptionStack = null;\n lastException = null;\n notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));\n }\n\n /**\n * Reports an unhandled Error to TraceKit.\n * @param {Error} ex\n * @param {?boolean} rethrow If false, do not re-throw the exception.\n * Only used for window.onerror to not cause an infinite loop of\n * rethrowing.\n */\n function report(ex, rethrow) {\n var args = _slice.call(arguments, 1);\n if (lastExceptionStack) {\n if (lastException === ex) {\n return; // already caught by an inner catch block, ignore\n } else {\n processLastException();\n }\n }\n\n var stack = TraceKit.computeStackTrace(ex);\n lastExceptionStack = stack;\n lastException = ex;\n lastArgs = args;\n\n // If the stack trace is incomplete, wait for 2 seconds for\n // slow slow IE to see if onerror occurs or not before reporting\n // this exception; otherwise, we will end up with an incomplete\n // stack trace\n setTimeout(function() {\n if (lastException === ex) {\n processLastException();\n }\n }, stack.incomplete ? 2000 : 0);\n\n if (rethrow !== false) {\n throw ex; // re-throw to propagate to the top level (and cause window.onerror)\n }\n }\n\n report.subscribe = subscribe;\n report.unsubscribe = unsubscribe;\n report.uninstall = unsubscribeAll;\n return report;\n})();\n\n/**\n * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript\n *\n * Syntax:\n * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)\n * Returns:\n * s.name - exception name\n * s.message - exception message\n * s.stack[i].url - JavaScript or HTML file URL\n * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)\n * s.stack[i].args - arguments passed to the function, if known\n * s.stack[i].line - line number, if known\n * s.stack[i].column - column number, if known\n *\n * Supports:\n * - Firefox: full stack trace with line numbers and unreliable column\n * number on top frame\n * - Opera 10: full stack trace with line and column numbers\n * - Opera 9-: full stack trace with line numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the topmost stacktrace element\n * only\n * - IE: no line numbers whatsoever\n *\n * Tries to guess names of anonymous functions by looking for assignments\n * in the source code. In IE and Safari, we have to guess source file names\n * by searching for function bodies inside all page scripts. This will not\n * work for scripts that are loaded cross-domain.\n * Here be dragons: some function names may be guessed incorrectly, and\n * duplicate functions may be mismatched.\n *\n * TraceKit.computeStackTrace should only be used for tracing purposes.\n * Logging of unhandled exceptions should be done with TraceKit.report,\n * which builds on top of TraceKit.computeStackTrace and provides better\n * IE support by utilizing the window.onerror event to retrieve information\n * about the top of the stack.\n *\n * Note: In IE and Safari, no stack trace is recorded on the Error object,\n * so computeStackTrace instead walks its *own* chain of callers.\n * This means that:\n * * in Safari, some methods may be missing from the stack trace;\n * * in IE, the topmost function in the stack trace will always be the\n * caller of computeStackTrace.\n *\n * This is okay for tracing (because you are likely to be calling\n * computeStackTrace from the function you want to be the topmost element\n * of the stack trace anyway), but not okay for logging unhandled\n * exceptions (because your catch block will likely be far away from the\n * inner function that actually caused the exception).\n *\n */\nTraceKit.computeStackTrace = (function computeStackTraceWrapper() {\n // Contents of Exception in various browsers.\n //\n // SAFARI:\n // ex.message = Can't find variable: qq\n // ex.line = 59\n // ex.sourceId = 580238192\n // ex.sourceURL = http://...\n // ex.expressionBeginOffset = 96\n // ex.expressionCaretOffset = 98\n // ex.expressionEndOffset = 98\n // ex.name = ReferenceError\n //\n // FIREFOX:\n // ex.message = qq is not defined\n // ex.fileName = http://...\n // ex.lineNumber = 59\n // ex.columnNumber = 69\n // ex.stack = ...stack trace... (see the example below)\n // ex.name = ReferenceError\n //\n // CHROME:\n // ex.message = qq is not defined\n // ex.name = ReferenceError\n // ex.type = not_defined\n // ex.arguments = ['aa']\n // ex.stack = ...stack trace...\n //\n // INTERNET EXPLORER:\n // ex.message = ...\n // ex.name = ReferenceError\n //\n // OPERA:\n // ex.message = ...message... (see the example below)\n // ex.name = ReferenceError\n // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)\n // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'\n\n /**\n * Computes stack trace information from the stack property.\n * Chrome and Gecko use this property.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceFromStackProp(ex) {\n if (typeof ex.stack === 'undefined' || !ex.stack) return;\n\n var chrome = /^\\s*at (?:(.*?) ?\\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\\/).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i;\n var winjs = /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i;\n // NOTE: blob urls are now supposed to always have an origin, therefore it's format\n // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\\/` as well\n var gecko = /^\\s*(.*?)(?:\\((.*?)\\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\\/.*?|\\[native code\\]|[^@]*bundle)(?::(\\d+))?(?::(\\d+))?\\s*$/i;\n // Used to additionally parse URL/line/column from eval frames\n var geckoEval = /(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i;\n var chromeEval = /\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/;\n var lines = ex.stack.split('\\n');\n var stack = [];\n var submatch;\n var parts;\n var element;\n var reference = /^(.*) is undefined$/.exec(ex.message);\n\n for (var i = 0, j = lines.length; i < j; ++i) {\n if ((parts = chrome.exec(lines[i]))) {\n var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line\n var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line\n if (isEval && (submatch = chromeEval.exec(parts[2]))) {\n // throw out eval line/column and use top-most line/column number\n parts[2] = submatch[1]; // url\n parts[3] = submatch[2]; // line\n parts[4] = submatch[3]; // column\n }\n element = {\n url: !isNative ? parts[2] : null,\n func: parts[1] || UNKNOWN_FUNCTION,\n args: isNative ? [parts[2]] : [],\n line: parts[3] ? +parts[3] : null,\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = winjs.exec(lines[i]))) {\n element = {\n url: parts[2],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: [],\n line: +parts[3],\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = gecko.exec(lines[i]))) {\n var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;\n if (isEval && (submatch = geckoEval.exec(parts[3]))) {\n // throw out eval line/column and use top-most line number\n parts[3] = submatch[1];\n parts[4] = submatch[2];\n parts[5] = null; // no column when eval\n } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {\n // FireFox uses this awesome columnNumber property for its top frame\n // Also note, Firefox's column number is 0-based and everything else expects 1-based,\n // so adding 1\n // NOTE: this hack doesn't work if top-most frame is eval\n stack[0].column = ex.columnNumber + 1;\n }\n element = {\n url: parts[3],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: parts[2] ? parts[2].split(',') : [],\n line: parts[4] ? +parts[4] : null,\n column: parts[5] ? +parts[5] : null\n };\n } else {\n continue;\n }\n\n if (!element.func && element.line) {\n element.func = UNKNOWN_FUNCTION;\n }\n\n stack.push(element);\n }\n\n if (!stack.length) {\n return null;\n }\n\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n }\n\n /**\n * Adds information about the first frame to incomplete stack traces.\n * Safari and IE require this to get complete data on the first frame.\n * @param {Object.<string, *>} stackInfo Stack trace information from\n * one of the compute* methods.\n * @param {string} url The URL of the script that caused an error.\n * @param {(number|string)} lineNo The line number of the script that\n * caused an error.\n * @param {string=} message The error generated by the browser, which\n * hopefully contains the name of the object that caused the error.\n * @return {boolean} Whether or not the stack information was\n * augmented.\n */\n function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {\n var initial = {\n url: url,\n line: lineNo\n };\n\n if (initial.url && initial.line) {\n stackInfo.incomplete = false;\n\n if (!initial.func) {\n initial.func = UNKNOWN_FUNCTION;\n }\n\n if (stackInfo.stack.length > 0) {\n if (stackInfo.stack[0].url === initial.url) {\n if (stackInfo.stack[0].line === initial.line) {\n return false; // already in stack trace\n } else if (\n !stackInfo.stack[0].line &&\n stackInfo.stack[0].func === initial.func\n ) {\n stackInfo.stack[0].line = initial.line;\n return false;\n }\n }\n }\n\n stackInfo.stack.unshift(initial);\n stackInfo.partial = true;\n return true;\n } else {\n stackInfo.incomplete = true;\n }\n\n return false;\n }\n\n /**\n * Computes stack trace information by walking the arguments.caller\n * chain at the time the exception occurred. This will cause earlier\n * frames to be missed but is the only way to get any stack trace in\n * Safari and IE. The top frame is restored by\n * {@link augmentStackTraceWithInitialElement}.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceByWalkingCallerChain(ex, depth) {\n var functionName = /function\\s+([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*)?\\s*\\(/i,\n stack = [],\n funcs = {},\n recursion = false,\n parts,\n item,\n source;\n\n for (\n var curr = computeStackTraceByWalkingCallerChain.caller;\n curr && !recursion;\n curr = curr.caller\n ) {\n if (curr === computeStackTrace || curr === TraceKit.report) {\n // console.log('skipping internal function');\n continue;\n }\n\n item = {\n url: null,\n func: UNKNOWN_FUNCTION,\n line: null,\n column: null\n };\n\n if (curr.name) {\n item.func = curr.name;\n } else if ((parts = functionName.exec(curr.toString()))) {\n item.func = parts[1];\n }\n\n if (typeof item.func === 'undefined') {\n try {\n item.func = parts.input.substring(0, parts.input.indexOf('{'));\n } catch (e) {}\n }\n\n if (funcs['' + curr]) {\n recursion = true;\n } else {\n funcs['' + curr] = true;\n }\n\n stack.push(item);\n }\n\n if (depth) {\n // console.log('depth is ' + depth);\n // console.log('stack is ' + stack.length);\n stack.splice(0, depth);\n }\n\n var result = {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n augmentStackTraceWithInitialElement(\n result,\n ex.sourceURL || ex.fileName,\n ex.line || ex.lineNumber,\n ex.message || ex.description\n );\n return result;\n }\n\n /**\n * Computes a stack trace for an exception.\n * @param {Error} ex\n * @param {(string|number)=} depth\n */\n function computeStackTrace(ex, depth) {\n var stack = null;\n depth = depth == null ? 0 : +depth;\n\n try {\n stack = computeStackTraceFromStackProp(ex);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n\n try {\n stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref()\n };\n }\n\n computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;\n computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp;\n\n return computeStackTrace;\n})();\n\nmodule.exports = TraceKit;\n","/*\n * JavaScript MD5\n * https://github.com/blueimp/JavaScript-MD5\n *\n * Copyright 2011, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * https://opensource.org/licenses/MIT\n *\n * Based on\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for more info.\n */\n\n/*\n* Add integers, wrapping at 2^32. This uses 16-bit operations internally\n* to work around bugs in some JS interpreters.\n*/\nfunction safeAdd(x, y) {\n var lsw = (x & 0xffff) + (y & 0xffff);\n var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n}\n\n/*\n* Bitwise rotate a 32-bit number to the left.\n*/\nfunction bitRotateLeft(num, cnt) {\n return (num << cnt) | (num >>> (32 - cnt));\n}\n\n/*\n* These functions implement the four basic operations the algorithm uses.\n*/\nfunction md5cmn(q, a, b, x, s, t) {\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n}\nfunction md5ff(a, b, c, d, x, s, t) {\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\n}\nfunction md5gg(a, b, c, d, x, s, t) {\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\n}\nfunction md5hh(a, b, c, d, x, s, t) {\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\n}\nfunction md5ii(a, b, c, d, x, s, t) {\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\n/*\n* Calculate the MD5 of an array of little-endian words, and a bit length.\n*/\nfunction binlMD5(x, len) {\n /* append padding */\n x[len >> 5] |= 0x80 << (len % 32);\n x[(((len + 64) >>> 9) << 4) + 14] = len;\n\n var i;\n var olda;\n var oldb;\n var oldc;\n var oldd;\n var a = 1732584193;\n var b = -271733879;\n var c = -1732584194;\n var d = 271733878;\n\n for (i = 0; i < x.length; i += 16) {\n olda = a;\n oldb = b;\n oldc = c;\n oldd = d;\n\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\n\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\n\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\n\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\n\n a = safeAdd(a, olda);\n b = safeAdd(b, oldb);\n c = safeAdd(c, oldc);\n d = safeAdd(d, oldd);\n }\n return [a, b, c, d];\n}\n\n/*\n* Convert an array of little-endian words to a string\n*/\nfunction binl2rstr(input) {\n var i;\n var output = '';\n var length32 = input.length * 32;\n for (i = 0; i < length32; i += 8) {\n output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff);\n }\n return output;\n}\n\n/*\n* Convert a raw string to an array of little-endian words\n* Characters >255 have their high-byte silently ignored.\n*/\nfunction rstr2binl(input) {\n var i;\n var output = [];\n output[(input.length >> 2) - 1] = undefined;\n for (i = 0; i < output.length; i += 1) {\n output[i] = 0;\n }\n var length8 = input.length * 8;\n for (i = 0; i < length8; i += 8) {\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32);\n }\n return output;\n}\n\n/*\n* Calculate the MD5 of a raw string\n*/\nfunction rstrMD5(s) {\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\n}\n\n/*\n* Calculate the HMAC-MD5, of a key and some data (raw strings)\n*/\nfunction rstrHMACMD5(key, data) {\n var i;\n var bkey = rstr2binl(key);\n var ipad = [];\n var opad = [];\n var hash;\n ipad[15] = opad[15] = undefined;\n if (bkey.length > 16) {\n bkey = binlMD5(bkey, key.length * 8);\n }\n for (i = 0; i < 16; i += 1) {\n ipad[i] = bkey[i] ^ 0x36363636;\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\n }\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\n}\n\n/*\n* Convert a raw string to a hex string\n*/\nfunction rstr2hex(input) {\n var hexTab = '0123456789abcdef';\n var output = '';\n var x;\n var i;\n for (i = 0; i < input.length; i += 1) {\n x = input.charCodeAt(i);\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\n }\n return output;\n}\n\n/*\n* Encode a string as utf-8\n*/\nfunction str2rstrUTF8(input) {\n return unescape(encodeURIComponent(input));\n}\n\n/*\n* Take string arguments and return either raw or hex encoded strings\n*/\nfunction rawMD5(s) {\n return rstrMD5(str2rstrUTF8(s));\n}\nfunction hexMD5(s) {\n return rstr2hex(rawMD5(s));\n}\nfunction rawHMACMD5(k, d) {\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\n}\nfunction hexHMACMD5(k, d) {\n return rstr2hex(rawHMACMD5(k, d));\n}\n\nfunction md5(string, key, raw) {\n if (!key) {\n if (!raw) {\n return hexMD5(string);\n }\n return rawMD5(string);\n }\n if (!raw) {\n return hexHMACMD5(key, string);\n }\n return rawHMACMD5(key, string);\n}\n\nmodule.exports = md5;\n","function RavenConfigError(message) {\n this.name = 'RavenConfigError';\n this.message = message;\n}\nRavenConfigError.prototype = new Error();\nRavenConfigError.prototype.constructor = RavenConfigError;\n\nmodule.exports = RavenConfigError;\n","var utils = require('./utils');\n\nvar wrapMethod = function(console, level, callback) {\n var originalConsoleLevel = console[level];\n var originalConsole = console;\n\n if (!(level in console)) {\n return;\n }\n\n var sentryLevel = level === 'warn' ? 'warning' : level;\n\n console[level] = function() {\n var args = [].slice.call(arguments);\n\n var msg = utils.safeJoin(args, ' ');\n var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}};\n\n if (level === 'assert') {\n if (args[0] === false) {\n // Default browsers message\n msg =\n 'Assertion failed: ' + (utils.safeJoin(args.slice(1), ' ') || 'console.assert');\n data.extra.arguments = args.slice(1);\n callback && callback(msg, data);\n }\n } else {\n callback && callback(msg, data);\n }\n\n // this fails for some browsers. :(\n if (originalConsoleLevel) {\n // IE9 doesn't allow calling apply on console functions directly\n // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193\n Function.prototype.apply.call(originalConsoleLevel, originalConsole, args);\n }\n };\n};\n\nmodule.exports = {\n wrapMethod: wrapMethod\n};\n","/*global XDomainRequest:false */\n\nvar TraceKit = require('../vendor/TraceKit/tracekit');\nvar stringify = require('../vendor/json-stringify-safe/stringify');\nvar md5 = require('../vendor/md5/md5');\nvar RavenConfigError = require('./configError');\n\nvar utils = require('./utils');\nvar isError = utils.isError;\nvar isObject = utils.isObject;\nvar isPlainObject = utils.isPlainObject;\nvar isErrorEvent = utils.isErrorEvent;\nvar isUndefined = utils.isUndefined;\nvar isFunction = utils.isFunction;\nvar isString = utils.isString;\nvar isArray = utils.isArray;\nvar isEmptyObject = utils.isEmptyObject;\nvar each = utils.each;\nvar objectMerge = utils.objectMerge;\nvar truncate = utils.truncate;\nvar objectFrozen = utils.objectFrozen;\nvar hasKey = utils.hasKey;\nvar joinRegExp = utils.joinRegExp;\nvar urlencode = utils.urlencode;\nvar uuid4 = utils.uuid4;\nvar htmlTreeAsString = utils.htmlTreeAsString;\nvar isSameException = utils.isSameException;\nvar isSameStacktrace = utils.isSameStacktrace;\nvar parseUrl = utils.parseUrl;\nvar fill = utils.fill;\nvar supportsFetch = utils.supportsFetch;\nvar supportsReferrerPolicy = utils.supportsReferrerPolicy;\nvar serializeKeysForMessage = utils.serializeKeysForMessage;\nvar serializeException = utils.serializeException;\nvar sanitize = utils.sanitize;\n\nvar wrapConsoleMethod = require('./console').wrapMethod;\n\nvar dsnKeys = 'source protocol user pass host port path'.split(' '),\n dsnPattern = /^(?:(\\w+):)?\\/\\/(?:(\\w+)(:\\w+)?@)?([\\w\\.-]+)(?::(\\d+))?(\\/.*)/;\n\nfunction now() {\n return +new Date();\n}\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _document = _window.document;\nvar _navigator = _window.navigator;\n\nfunction keepOriginalCallback(original, callback) {\n return isFunction(callback)\n ? function(data) {\n return callback(data, original);\n }\n : callback;\n}\n\n// First, check for JSON support\n// If there is no JSON, we no-op the core features of Raven\n// since JSON is required to encode the payload\nfunction Raven() {\n this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify);\n // Raven can run in contexts where there's no document (react-native)\n this._hasDocument = !isUndefined(_document);\n this._hasNavigator = !isUndefined(_navigator);\n this._lastCapturedException = null;\n this._lastData = null;\n this._lastEventId = null;\n this._globalServer = null;\n this._globalKey = null;\n this._globalProject = null;\n this._globalContext = {};\n this._globalOptions = {\n // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin\n release: _window.SENTRY_RELEASE && _window.SENTRY_RELEASE.id,\n logger: 'javascript',\n ignoreErrors: [],\n ignoreUrls: [],\n whitelistUrls: [],\n includePaths: [],\n headers: null,\n collectWindowErrors: true,\n captureUnhandledRejections: true,\n maxMessageLength: 0,\n // By default, truncates URL values to 250 chars\n maxUrlLength: 250,\n stackTraceLimit: 50,\n autoBreadcrumbs: true,\n instrument: true,\n sampleRate: 1,\n sanitizeKeys: []\n };\n this._fetchDefaults = {\n method: 'POST',\n keepalive: true,\n // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n // https://caniuse.com/#feat=referrer-policy\n // It doesn't. And it throw exception instead of ignoring this parameter...\n // REF: https://github.com/getsentry/raven-js/issues/1233\n referrerPolicy: supportsReferrerPolicy() ? 'origin' : ''\n };\n this._ignoreOnError = 0;\n this._isRavenInstalled = false;\n this._originalErrorStackTraceLimit = Error.stackTraceLimit;\n // capture references to window.console *and* all its methods first\n // before the console plugin has a chance to monkey patch\n this._originalConsole = _window.console || {};\n this._originalConsoleMethods = {};\n this._plugins = [];\n this._startTime = now();\n this._wrappedBuiltIns = [];\n this._breadcrumbs = [];\n this._lastCapturedEvent = null;\n this._keypressTimeout;\n this._location = _window.location;\n this._lastHref = this._location && this._location.href;\n this._resetBackoff();\n\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsole) {\n this._originalConsoleMethods[method] = this._originalConsole[method];\n }\n}\n\n/*\n * The core Raven singleton\n *\n * @this {Raven}\n */\n\nRaven.prototype = {\n // Hardcode version string so that raven source can be loaded directly via\n // webpack (using a build step causes webpack #1617). Grunt verifies that\n // this value matches package.json during build.\n // See: https://github.com/getsentry/raven-js/issues/465\n VERSION: '3.24.2',\n\n debug: false,\n\n TraceKit: TraceKit, // alias to TraceKit\n\n /*\n * Configure Raven with a DSN and extra options\n *\n * @param {string} dsn The public Sentry DSN\n * @param {object} options Set of global options [optional]\n * @return {Raven}\n */\n config: function(dsn, options) {\n var self = this;\n\n if (self._globalServer) {\n this._logDebug('error', 'Error: Raven has already been configured');\n return self;\n }\n if (!dsn) return self;\n\n var globalOptions = self._globalOptions;\n\n // merge in options\n if (options) {\n each(options, function(key, value) {\n // tags and extra are special and need to be put into context\n if (key === 'tags' || key === 'extra' || key === 'user') {\n self._globalContext[key] = value;\n } else {\n globalOptions[key] = value;\n }\n });\n }\n\n self.setDSN(dsn);\n\n // \"Script error.\" is hard coded into browsers for errors that it can't read.\n // this is the result of a script being pulled in from an external domain and CORS.\n globalOptions.ignoreErrors.push(/^Script error\\.?$/);\n globalOptions.ignoreErrors.push(/^Javascript error: Script error\\.? on line 0$/);\n\n // join regexp rules into one big rule\n globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);\n globalOptions.ignoreUrls = globalOptions.ignoreUrls.length\n ? joinRegExp(globalOptions.ignoreUrls)\n : false;\n globalOptions.whitelistUrls = globalOptions.whitelistUrls.length\n ? joinRegExp(globalOptions.whitelistUrls)\n : false;\n globalOptions.includePaths = joinRegExp(globalOptions.includePaths);\n globalOptions.maxBreadcrumbs = Math.max(\n 0,\n Math.min(globalOptions.maxBreadcrumbs || 100, 100)\n ); // default and hard limit is 100\n\n var autoBreadcrumbDefaults = {\n xhr: true,\n console: true,\n dom: true,\n location: true,\n sentry: true\n };\n\n var autoBreadcrumbs = globalOptions.autoBreadcrumbs;\n if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {\n autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);\n } else if (autoBreadcrumbs !== false) {\n autoBreadcrumbs = autoBreadcrumbDefaults;\n }\n globalOptions.autoBreadcrumbs = autoBreadcrumbs;\n\n var instrumentDefaults = {\n tryCatch: true\n };\n\n var instrument = globalOptions.instrument;\n if ({}.toString.call(instrument) === '[object Object]') {\n instrument = objectMerge(instrumentDefaults, instrument);\n } else if (instrument !== false) {\n instrument = instrumentDefaults;\n }\n globalOptions.instrument = instrument;\n\n TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;\n\n // return for chaining\n return self;\n },\n\n /*\n * Installs a global window.onerror error handler\n * to capture and report uncaught exceptions.\n * At this point, install() is required to be called due\n * to the way TraceKit is set up.\n *\n * @return {Raven}\n */\n install: function() {\n var self = this;\n if (self.isSetup() && !self._isRavenInstalled) {\n TraceKit.report.subscribe(function() {\n self._handleOnErrorStackInfo.apply(self, arguments);\n });\n\n if (self._globalOptions.captureUnhandledRejections) {\n self._attachPromiseRejectionHandler();\n }\n\n self._patchFunctionToString();\n\n if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) {\n self._instrumentTryCatch();\n }\n\n if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs();\n\n // Install all of the plugins\n self._drainPlugins();\n\n self._isRavenInstalled = true;\n }\n\n Error.stackTraceLimit = self._globalOptions.stackTraceLimit;\n return this;\n },\n\n /*\n * Set the DSN (can be called multiple time unlike config)\n *\n * @param {string} dsn The public Sentry DSN\n */\n setDSN: function(dsn) {\n var self = this,\n uri = self._parseDSN(dsn),\n lastSlash = uri.path.lastIndexOf('/'),\n path = uri.path.substr(1, lastSlash);\n\n self._dsn = dsn;\n self._globalKey = uri.user;\n self._globalSecret = uri.pass && uri.pass.substr(1);\n self._globalProject = uri.path.substr(lastSlash + 1);\n\n self._globalServer = self._getGlobalServer(uri);\n\n self._globalEndpoint =\n self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/';\n\n // Reset backoff state since we may be pointing at a\n // new project/server\n this._resetBackoff();\n },\n\n /*\n * Wrap code within a context so Raven can capture errors\n * reliably across domains that is executed immediately.\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The callback to be immediately executed within the context\n * @param {array} args An array of arguments to be called with the callback [optional]\n */\n context: function(options, func, args) {\n if (isFunction(options)) {\n args = func || [];\n func = options;\n options = undefined;\n }\n\n return this.wrap(options, func).apply(this, args);\n },\n\n /*\n * Wrap code within a context and returns back a new function to be executed\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The function to be wrapped in a new context\n * @param {function} func A function to call before the try/catch wrapper [optional, private]\n * @return {function} The newly wrapped functions with a context\n */\n wrap: function(options, func, _before) {\n var self = this;\n // 1 argument has been passed, and it's not a function\n // so just return it\n if (isUndefined(func) && !isFunction(options)) {\n return options;\n }\n\n // options is optional\n if (isFunction(options)) {\n func = options;\n options = undefined;\n }\n\n // At this point, we've passed along 2 arguments, and the second one\n // is not a function either, so we'll just return the second argument.\n if (!isFunction(func)) {\n return func;\n }\n\n // We don't wanna wrap it twice!\n try {\n if (func.__raven__) {\n return func;\n }\n\n // If this has already been wrapped in the past, return that\n if (func.__raven_wrapper__) {\n return func.__raven_wrapper__;\n }\n } catch (e) {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return func;\n }\n\n function wrapped() {\n var args = [],\n i = arguments.length,\n deep = !options || (options && options.deep !== false);\n\n if (_before && isFunction(_before)) {\n _before.apply(this, arguments);\n }\n\n // Recursively wrap all of a function's arguments that are\n // functions themselves.\n while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i];\n\n try {\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means Raven caught an error invoking your application code. This is\n // expected behavior and NOT indicative of a bug with Raven.js.\n return func.apply(this, args);\n } catch (e) {\n self._ignoreNextOnError();\n self.captureException(e, options);\n throw e;\n }\n }\n\n // copy over properties of the old function\n for (var property in func) {\n if (hasKey(func, property)) {\n wrapped[property] = func[property];\n }\n }\n wrapped.prototype = func.prototype;\n\n func.__raven_wrapper__ = wrapped;\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n wrapped.__raven__ = true;\n wrapped.__orig__ = func;\n\n return wrapped;\n },\n\n /**\n * Uninstalls the global error handler.\n *\n * @return {Raven}\n */\n uninstall: function() {\n TraceKit.report.uninstall();\n\n this._detachPromiseRejectionHandler();\n this._unpatchFunctionToString();\n this._restoreBuiltIns();\n this._restoreConsole();\n\n Error.stackTraceLimit = this._originalErrorStackTraceLimit;\n this._isRavenInstalled = false;\n\n return this;\n },\n\n /**\n * Callback used for `unhandledrejection` event\n *\n * @param {PromiseRejectionEvent} event An object containing\n * promise: the Promise that was rejected\n * reason: the value with which the Promise was rejected\n * @return void\n */\n _promiseRejectionHandler: function(event) {\n this._logDebug('debug', 'Raven caught unhandled promise rejection:', event);\n this.captureException(event.reason, {\n extra: {\n unhandledPromiseRejection: true\n }\n });\n },\n\n /**\n * Installs the global promise rejection handler.\n *\n * @return {raven}\n */\n _attachPromiseRejectionHandler: function() {\n this._promiseRejectionHandler = this._promiseRejectionHandler.bind(this);\n _window.addEventListener &&\n _window.addEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Uninstalls the global promise rejection handler.\n *\n * @return {raven}\n */\n _detachPromiseRejectionHandler: function() {\n _window.removeEventListener &&\n _window.removeEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Manually capture an exception and send it over to Sentry\n *\n * @param {error} ex An exception to be logged\n * @param {object} options A specific set of options for this error [optional]\n * @return {Raven}\n */\n captureException: function(ex, options) {\n options = objectMerge({trimHeadFrames: 0}, options ? options : {});\n\n if (isErrorEvent(ex) && ex.error) {\n // If it is an ErrorEvent with `error` property, extract it to get actual Error\n ex = ex.error;\n } else if (isError(ex)) {\n // we have a real Error object\n ex = ex;\n } else if (isPlainObject(ex)) {\n // If it is plain Object, serialize it manually and extract options\n // This will allow us to group events based on top-level keys\n // which is much better than creating new group when any key/value change\n options = this._getCaptureExceptionOptionsFromPlainObject(options, ex);\n ex = new Error(options.message);\n } else {\n // If none of previous checks were valid, then it means that\n // it's not a plain Object\n // it's not a valid ErrorEvent (one with an error property)\n // it's not an Error\n // So bail out and capture it as a simple message:\n return this.captureMessage(\n ex,\n objectMerge(options, {\n stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace\n trimHeadFrames: options.trimHeadFrames + 1\n })\n );\n }\n\n // Store the raw exception object for potential debugging and introspection\n this._lastCapturedException = ex;\n\n // TraceKit.report will re-raise any exception passed to it,\n // which means you have to wrap it in try/catch. Instead, we\n // can wrap it here and only re-raise if TraceKit.report\n // raises an exception different from the one we asked to\n // report on.\n try {\n var stack = TraceKit.computeStackTrace(ex);\n this._handleStackInfo(stack, options);\n } catch (ex1) {\n if (ex !== ex1) {\n throw ex1;\n }\n }\n\n return this;\n },\n\n _getCaptureExceptionOptionsFromPlainObject: function(currentOptions, ex) {\n var exKeys = Object.keys(ex).sort();\n var options = objectMerge(currentOptions, {\n message:\n 'Non-Error exception captured with keys: ' + serializeKeysForMessage(exKeys),\n fingerprint: [md5(exKeys)],\n extra: currentOptions.extra || {}\n });\n options.extra.__serialized__ = serializeException(ex);\n\n return options;\n },\n\n /*\n * Manually send a message to Sentry\n *\n * @param {string} msg A plain message to be captured in Sentry\n * @param {object} options A specific set of options for this message [optional]\n * @return {Raven}\n */\n captureMessage: function(msg, options) {\n // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an\n // early call; we'll error on the side of logging anything called before configuration since it's\n // probably something you should see:\n if (\n !!this._globalOptions.ignoreErrors.test &&\n this._globalOptions.ignoreErrors.test(msg)\n ) {\n return;\n }\n\n options = options || {};\n msg = msg + ''; // Make sure it's actually a string\n\n var data = objectMerge(\n {\n message: msg\n },\n options\n );\n\n var ex;\n // Generate a \"synthetic\" stack trace from this point.\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative\n // of a bug with Raven.js. Sentry generates synthetic traces either by configuration,\n // or if it catches a thrown object without a \"stack\" property.\n try {\n throw new Error(msg);\n } catch (ex1) {\n ex = ex1;\n }\n\n // null exception name so `Error` isn't prefixed to msg\n ex.name = null;\n var stack = TraceKit.computeStackTrace(ex);\n\n // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]\n var initialCall = isArray(stack.stack) && stack.stack[1];\n\n // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call\n // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd\n // initialCall => captureException(string) => captureMessage(string)\n if (initialCall && initialCall.func === 'Raven.captureException') {\n initialCall = stack.stack[2];\n }\n\n var fileurl = (initialCall && initialCall.url) || '';\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n if (this._globalOptions.stacktrace || (options && options.stacktrace)) {\n // fingerprint on msg, not stack trace (legacy behavior, could be revisited)\n data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;\n\n options = objectMerge(\n {\n trimHeadFrames: 0\n },\n options\n );\n // Since we know this is a synthetic trace, the top frame (this function call)\n // MUST be from Raven.js, so mark it for trimming\n // We add to the trim counter so that callers can choose to trim extra frames, such\n // as utility functions.\n options.trimHeadFrames += 1;\n\n var frames = this._prepareFrames(stack, options);\n data.stacktrace = {\n // Sentry expects frames oldest to newest\n frames: frames.reverse()\n };\n }\n\n // Make sure that fingerprint is always wrapped in an array\n if (data.fingerprint) {\n data.fingerprint = isArray(data.fingerprint)\n ? data.fingerprint\n : [data.fingerprint];\n }\n\n // Fire away!\n this._send(data);\n\n return this;\n },\n\n captureBreadcrumb: function(obj) {\n var crumb = objectMerge(\n {\n timestamp: now() / 1000\n },\n obj\n );\n\n if (isFunction(this._globalOptions.breadcrumbCallback)) {\n var result = this._globalOptions.breadcrumbCallback(crumb);\n\n if (isObject(result) && !isEmptyObject(result)) {\n crumb = result;\n } else if (result === false) {\n return this;\n }\n }\n\n this._breadcrumbs.push(crumb);\n if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {\n this._breadcrumbs.shift();\n }\n return this;\n },\n\n addPlugin: function(plugin /*arg1, arg2, ... argN*/) {\n var pluginArgs = [].slice.call(arguments, 1);\n\n this._plugins.push([plugin, pluginArgs]);\n if (this._isRavenInstalled) {\n this._drainPlugins();\n }\n\n return this;\n },\n\n /*\n * Set/clear a user to be sent along with the payload.\n *\n * @param {object} user An object representing user data [optional]\n * @return {Raven}\n */\n setUserContext: function(user) {\n // Intentionally do not merge here since that's an unexpected behavior.\n this._globalContext.user = user;\n\n return this;\n },\n\n /*\n * Merge extra attributes to be sent along with the payload.\n *\n * @param {object} extra An object representing extra data [optional]\n * @return {Raven}\n */\n setExtraContext: function(extra) {\n this._mergeContext('extra', extra);\n\n return this;\n },\n\n /*\n * Merge tags to be sent along with the payload.\n *\n * @param {object} tags An object representing tags [optional]\n * @return {Raven}\n */\n setTagsContext: function(tags) {\n this._mergeContext('tags', tags);\n\n return this;\n },\n\n /*\n * Clear all of the context.\n *\n * @return {Raven}\n */\n clearContext: function() {\n this._globalContext = {};\n\n return this;\n },\n\n /*\n * Get a copy of the current context. This cannot be mutated.\n *\n * @return {object} copy of context\n */\n getContext: function() {\n // lol javascript\n return JSON.parse(stringify(this._globalContext));\n },\n\n /*\n * Set environment of application\n *\n * @param {string} environment Typically something like 'production'.\n * @return {Raven}\n */\n setEnvironment: function(environment) {\n this._globalOptions.environment = environment;\n\n return this;\n },\n\n /*\n * Set release version of application\n *\n * @param {string} release Typically something like a git SHA to identify version\n * @return {Raven}\n */\n setRelease: function(release) {\n this._globalOptions.release = release;\n\n return this;\n },\n\n /*\n * Set the dataCallback option\n *\n * @param {function} callback The callback to run which allows the\n * data blob to be mutated before sending\n * @return {Raven}\n */\n setDataCallback: function(callback) {\n var original = this._globalOptions.dataCallback;\n this._globalOptions.dataCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the breadcrumbCallback option\n *\n * @param {function} callback The callback to run which allows filtering\n * or mutating breadcrumbs\n * @return {Raven}\n */\n setBreadcrumbCallback: function(callback) {\n var original = this._globalOptions.breadcrumbCallback;\n this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the shouldSendCallback option\n *\n * @param {function} callback The callback to run which allows\n * introspecting the blob before sending\n * @return {Raven}\n */\n setShouldSendCallback: function(callback) {\n var original = this._globalOptions.shouldSendCallback;\n this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /**\n * Override the default HTTP transport mechanism that transmits data\n * to the Sentry server.\n *\n * @param {function} transport Function invoked instead of the default\n * `makeRequest` handler.\n *\n * @return {Raven}\n */\n setTransport: function(transport) {\n this._globalOptions.transport = transport;\n\n return this;\n },\n\n /*\n * Get the latest raw exception that was captured by Raven.\n *\n * @return {error}\n */\n lastException: function() {\n return this._lastCapturedException;\n },\n\n /*\n * Get the last event id\n *\n * @return {string}\n */\n lastEventId: function() {\n return this._lastEventId;\n },\n\n /*\n * Determine if Raven is setup and ready to go.\n *\n * @return {boolean}\n */\n isSetup: function() {\n if (!this._hasJSON) return false; // needs JSON support\n if (!this._globalServer) {\n if (!this.ravenNotConfiguredError) {\n this.ravenNotConfiguredError = true;\n this._logDebug('error', 'Error: Raven has not been configured.');\n }\n return false;\n }\n return true;\n },\n\n afterLoad: function() {\n // TODO: remove window dependence?\n\n // Attempt to initialize Raven on load\n var RavenConfig = _window.RavenConfig;\n if (RavenConfig) {\n this.config(RavenConfig.dsn, RavenConfig.config).install();\n }\n },\n\n showReportDialog: function(options) {\n if (\n !_document // doesn't work without a document (React native)\n )\n return;\n\n options = options || {};\n\n var lastEventId = options.eventId || this.lastEventId();\n if (!lastEventId) {\n throw new RavenConfigError('Missing eventId');\n }\n\n var dsn = options.dsn || this._dsn;\n if (!dsn) {\n throw new RavenConfigError('Missing DSN');\n }\n\n var encode = encodeURIComponent;\n var qs = '';\n qs += '?eventId=' + encode(lastEventId);\n qs += '&dsn=' + encode(dsn);\n\n var user = options.user || this._globalContext.user;\n if (user) {\n if (user.name) qs += '&name=' + encode(user.name);\n if (user.email) qs += '&email=' + encode(user.email);\n }\n\n var globalServer = this._getGlobalServer(this._parseDSN(dsn));\n\n var script = _document.createElement('script');\n script.async = true;\n script.src = globalServer + '/api/embed/error-page/' + qs;\n (_document.head || _document.body).appendChild(script);\n },\n\n /**** Private functions ****/\n _ignoreNextOnError: function() {\n var self = this;\n this._ignoreOnError += 1;\n setTimeout(function() {\n // onerror should trigger before setTimeout\n self._ignoreOnError -= 1;\n });\n },\n\n _triggerEvent: function(eventType, options) {\n // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it\n var evt, key;\n\n if (!this._hasDocument) return;\n\n options = options || {};\n\n eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1);\n\n if (_document.createEvent) {\n evt = _document.createEvent('HTMLEvents');\n evt.initEvent(eventType, true, true);\n } else {\n evt = _document.createEventObject();\n evt.eventType = eventType;\n }\n\n for (key in options)\n if (hasKey(options, key)) {\n evt[key] = options[key];\n }\n\n if (_document.createEvent) {\n // IE9 if standards\n _document.dispatchEvent(evt);\n } else {\n // IE8 regardless of Quirks or Standards\n // IE9 if quirks\n try {\n _document.fireEvent('on' + evt.eventType.toLowerCase(), evt);\n } catch (e) {\n // Do nothing\n }\n }\n },\n\n /**\n * Wraps addEventListener to capture UI breadcrumbs\n * @param evtName the event name (e.g. \"click\")\n * @returns {Function}\n * @private\n */\n _breadcrumbEventHandler: function(evtName) {\n var self = this;\n return function(evt) {\n // reset keypress timeout; e.g. triggering a 'click' after\n // a 'keypress' will reset the keypress debounce so that a new\n // set of keypresses can be recorded\n self._keypressTimeout = null;\n\n // It's possible this handler might trigger multiple times for the same\n // event (e.g. event propagation through node ancestors). Ignore if we've\n // already captured the event.\n if (self._lastCapturedEvent === evt) return;\n\n self._lastCapturedEvent = evt;\n\n // try/catch both:\n // - accessing evt.target (see getsentry/raven-js#838, #768)\n // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly\n // can throw an exception in some circumstances.\n var target;\n try {\n target = htmlTreeAsString(evt.target);\n } catch (e) {\n target = '<unknown>';\n }\n\n self.captureBreadcrumb({\n category: 'ui.' + evtName, // e.g. ui.click, ui.input\n message: target\n });\n };\n },\n\n /**\n * Wraps addEventListener to capture keypress UI events\n * @returns {Function}\n * @private\n */\n _keypressEventHandler: function() {\n var self = this,\n debounceDuration = 1000; // milliseconds\n\n // TODO: if somehow user switches keypress target before\n // debounce timeout is triggered, we will only capture\n // a single breadcrumb from the FIRST target (acceptable?)\n return function(evt) {\n var target;\n try {\n target = evt.target;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n var tagName = target && target.tagName;\n\n // only consider keypress events on actual input elements\n // this will disregard keypresses targeting body (e.g. tabbing\n // through elements, hotkeys, etc)\n if (\n !tagName ||\n (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)\n )\n return;\n\n // record first keypress in a series, but ignore subsequent\n // keypresses until debounce clears\n var timeout = self._keypressTimeout;\n if (!timeout) {\n self._breadcrumbEventHandler('input')(evt);\n }\n clearTimeout(timeout);\n self._keypressTimeout = setTimeout(function() {\n self._keypressTimeout = null;\n }, debounceDuration);\n };\n },\n\n /**\n * Captures a breadcrumb of type \"navigation\", normalizing input URLs\n * @param to the originating URL\n * @param from the target URL\n * @private\n */\n _captureUrlChange: function(from, to) {\n var parsedLoc = parseUrl(this._location.href);\n var parsedTo = parseUrl(to);\n var parsedFrom = parseUrl(from);\n\n // because onpopstate only tells you the \"new\" (to) value of location.href, and\n // not the previous (from) value, we need to track the value of the current URL\n // state ourselves\n this._lastHref = to;\n\n // Use only the path component of the URL if the URL matches the current\n // document (almost all the time when using pushState)\n if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host)\n to = parsedTo.relative;\n if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host)\n from = parsedFrom.relative;\n\n this.captureBreadcrumb({\n category: 'navigation',\n data: {\n to: to,\n from: from\n }\n });\n },\n\n _patchFunctionToString: function() {\n var self = this;\n self._originalFunctionToString = Function.prototype.toString;\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = function() {\n if (typeof this === 'function' && this.__raven__) {\n return self._originalFunctionToString.apply(this.__orig__, arguments);\n }\n return self._originalFunctionToString.apply(this, arguments);\n };\n },\n\n _unpatchFunctionToString: function() {\n if (this._originalFunctionToString) {\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = this._originalFunctionToString;\n }\n },\n\n /**\n * Wrap timer functions and event targets to catch errors and provide\n * better metadata.\n */\n _instrumentTryCatch: function() {\n var self = this;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapTimeFn(orig) {\n return function(fn, t) {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n var originalCallback = args[0];\n if (isFunction(originalCallback)) {\n args[0] = self.wrap(originalCallback);\n }\n\n // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it\n // also supports only two arguments and doesn't care what this is, so we\n // can just call the original function directly.\n if (orig.apply) {\n return orig.apply(this, args);\n } else {\n return orig(args[0], args[1]);\n }\n };\n }\n\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n function wrapEventTarget(global) {\n var proto = _window[global] && _window[global].prototype;\n if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {\n fill(\n proto,\n 'addEventListener',\n function(orig) {\n return function(evtName, fn, capture, secure) {\n // preserve arity\n try {\n if (fn && fn.handleEvent) {\n fn.handleEvent = self.wrap(fn.handleEvent);\n }\n } catch (err) {\n // can sometimes get 'Permission denied to access property \"handle Event'\n }\n\n // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`\n // so that we don't have more than one wrapper function\n var before, clickHandler, keypressHandler;\n\n if (\n autoBreadcrumbs &&\n autoBreadcrumbs.dom &&\n (global === 'EventTarget' || global === 'Node')\n ) {\n // NOTE: generating multiple handlers per addEventListener invocation, should\n // revisit and verify we can just use one (almost certainly)\n clickHandler = self._breadcrumbEventHandler('click');\n keypressHandler = self._keypressEventHandler();\n before = function(evt) {\n // need to intercept every DOM event in `before` argument, in case that\n // same wrapped method is re-used for different events (e.g. mousemove THEN click)\n // see #724\n if (!evt) return;\n\n var eventType;\n try {\n eventType = evt.type;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n if (eventType === 'click') return clickHandler(evt);\n else if (eventType === 'keypress') return keypressHandler(evt);\n };\n }\n return orig.call(\n this,\n evtName,\n self.wrap(fn, undefined, before),\n capture,\n secure\n );\n };\n },\n wrappedBuiltIns\n );\n fill(\n proto,\n 'removeEventListener',\n function(orig) {\n return function(evt, fn, capture, secure) {\n try {\n fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn);\n } catch (e) {\n // ignore, accessing __raven_wrapper__ will throw in some Selenium environments\n }\n return orig.call(this, evt, fn, capture, secure);\n };\n },\n wrappedBuiltIns\n );\n }\n }\n\n fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);\n fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns);\n if (_window.requestAnimationFrame) {\n fill(\n _window,\n 'requestAnimationFrame',\n function(orig) {\n return function(cb) {\n return orig(self.wrap(cb));\n };\n },\n wrappedBuiltIns\n );\n }\n\n // event targets borrowed from bugsnag-js:\n // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666\n var eventTargets = [\n 'EventTarget',\n 'Window',\n 'Node',\n 'ApplicationCache',\n 'AudioTrackList',\n 'ChannelMergerNode',\n 'CryptoOperation',\n 'EventSource',\n 'FileReader',\n 'HTMLUnknownElement',\n 'IDBDatabase',\n 'IDBRequest',\n 'IDBTransaction',\n 'KeyOperation',\n 'MediaController',\n 'MessagePort',\n 'ModalWindow',\n 'Notification',\n 'SVGElementInstance',\n 'Screen',\n 'TextTrack',\n 'TextTrackCue',\n 'TextTrackList',\n 'WebSocket',\n 'WebSocketWorker',\n 'Worker',\n 'XMLHttpRequest',\n 'XMLHttpRequestEventTarget',\n 'XMLHttpRequestUpload'\n ];\n for (var i = 0; i < eventTargets.length; i++) {\n wrapEventTarget(eventTargets[i]);\n }\n },\n\n /**\n * Instrument browser built-ins w/ breadcrumb capturing\n * - XMLHttpRequests\n * - DOM interactions (click/typing)\n * - window.location changes\n * - console\n *\n * Can be disabled or individually configured via the `autoBreadcrumbs` config option\n */\n _instrumentBreadcrumbs: function() {\n var self = this;\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapProp(prop, xhr) {\n if (prop in xhr && isFunction(xhr[prop])) {\n fill(xhr, prop, function(orig) {\n return self.wrap(orig);\n }); // intentionally don't track filled methods on XHR instances\n }\n }\n\n if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) {\n var xhrproto = _window.XMLHttpRequest && _window.XMLHttpRequest.prototype;\n fill(\n xhrproto,\n 'open',\n function(origOpen) {\n return function(method, url) {\n // preserve arity\n\n // if Sentry key appears in URL, don't capture\n if (isString(url) && url.indexOf(self._globalKey) === -1) {\n this.__raven_xhr = {\n method: method,\n url: url,\n status_code: null\n };\n }\n\n return origOpen.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n\n fill(\n xhrproto,\n 'send',\n function(origSend) {\n return function() {\n // preserve arity\n var xhr = this;\n\n function onreadystatechangeHandler() {\n if (xhr.__raven_xhr && xhr.readyState === 4) {\n try {\n // touching statusCode in some platforms throws\n // an exception\n xhr.__raven_xhr.status_code = xhr.status;\n } catch (e) {\n /* do nothing */\n }\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'xhr',\n data: xhr.__raven_xhr\n });\n }\n }\n\n var props = ['onload', 'onerror', 'onprogress'];\n for (var j = 0; j < props.length; j++) {\n wrapProp(props[j], xhr);\n }\n\n if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {\n fill(\n xhr,\n 'onreadystatechange',\n function(orig) {\n return self.wrap(orig, undefined, onreadystatechangeHandler);\n } /* intentionally don't track this instrumentation */\n );\n } else {\n // if onreadystatechange wasn't actually set by the page on this xhr, we\n // are free to set our own and capture the breadcrumb\n xhr.onreadystatechange = onreadystatechangeHandler;\n }\n\n return origSend.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n }\n\n if (autoBreadcrumbs.xhr && supportsFetch()) {\n fill(\n _window,\n 'fetch',\n function(origFetch) {\n return function() {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n\n var fetchInput = args[0];\n var method = 'GET';\n var url;\n\n if (typeof fetchInput === 'string') {\n url = fetchInput;\n } else if ('Request' in _window && fetchInput instanceof _window.Request) {\n url = fetchInput.url;\n if (fetchInput.method) {\n method = fetchInput.method;\n }\n } else {\n url = '' + fetchInput;\n }\n\n // if Sentry key appears in URL, don't capture, as it's our own request\n if (url.indexOf(self._globalKey) !== -1) {\n return origFetch.apply(this, args);\n }\n\n if (args[1] && args[1].method) {\n method = args[1].method;\n }\n\n var fetchData = {\n method: method,\n url: url,\n status_code: null\n };\n\n return origFetch\n .apply(this, args)\n .then(function(response) {\n fetchData.status_code = response.status;\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData\n });\n\n return response;\n })\n ['catch'](function(err) {\n // if there is an error performing the request\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData,\n level: 'error'\n });\n\n throw err;\n });\n };\n },\n wrappedBuiltIns\n );\n }\n\n // Capture breadcrumbs from any click that is unhandled / bubbled up all the way\n // to the document. Do this before we instrument addEventListener.\n if (autoBreadcrumbs.dom && this._hasDocument) {\n if (_document.addEventListener) {\n _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);\n _document.addEventListener('keypress', self._keypressEventHandler(), false);\n } else if (_document.attachEvent) {\n // IE8 Compatibility\n _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));\n _document.attachEvent('onkeypress', self._keypressEventHandler());\n }\n }\n\n // record navigation (URL) changes\n // NOTE: in Chrome App environment, touching history.pushState, *even inside\n // a try/catch block*, will cause Chrome to output an error to console.error\n // borrowed from: https://github.com/angular/angular.js/pull/13945/files\n var chrome = _window.chrome;\n var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;\n var hasPushAndReplaceState =\n !isChromePackagedApp &&\n _window.history &&\n history.pushState &&\n history.replaceState;\n if (autoBreadcrumbs.location && hasPushAndReplaceState) {\n // TODO: remove onpopstate handler on uninstall()\n var oldOnPopState = _window.onpopstate;\n _window.onpopstate = function() {\n var currentHref = self._location.href;\n self._captureUrlChange(self._lastHref, currentHref);\n\n if (oldOnPopState) {\n return oldOnPopState.apply(this, arguments);\n }\n };\n\n var historyReplacementFunction = function(origHistFunction) {\n // note history.pushState.length is 0; intentionally not declaring\n // params to preserve 0 arity\n return function(/* state, title, url */) {\n var url = arguments.length > 2 ? arguments[2] : undefined;\n\n // url argument is optional\n if (url) {\n // coerce to string (this is what pushState does)\n self._captureUrlChange(self._lastHref, url + '');\n }\n\n return origHistFunction.apply(this, arguments);\n };\n };\n\n fill(history, 'pushState', historyReplacementFunction, wrappedBuiltIns);\n fill(history, 'replaceState', historyReplacementFunction, wrappedBuiltIns);\n }\n\n if (autoBreadcrumbs.console && 'console' in _window && console.log) {\n // console\n var consoleMethodCallback = function(msg, data) {\n self.captureBreadcrumb({\n message: msg,\n level: data.level,\n category: 'console'\n });\n };\n\n each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) {\n wrapConsoleMethod(console, level, consoleMethodCallback);\n });\n }\n },\n\n _restoreBuiltIns: function() {\n // restore any wrapped builtins\n var builtin;\n while (this._wrappedBuiltIns.length) {\n builtin = this._wrappedBuiltIns.shift();\n\n var obj = builtin[0],\n name = builtin[1],\n orig = builtin[2];\n\n obj[name] = orig;\n }\n },\n\n _restoreConsole: function() {\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsoleMethods) {\n this._originalConsole[method] = this._originalConsoleMethods[method];\n }\n },\n\n _drainPlugins: function() {\n var self = this;\n\n // FIX ME TODO\n each(this._plugins, function(_, plugin) {\n var installer = plugin[0];\n var args = plugin[1];\n installer.apply(self, [self].concat(args));\n });\n },\n\n _parseDSN: function(str) {\n var m = dsnPattern.exec(str),\n dsn = {},\n i = 7;\n\n try {\n while (i--) dsn[dsnKeys[i]] = m[i] || '';\n } catch (e) {\n throw new RavenConfigError('Invalid DSN: ' + str);\n }\n\n if (dsn.pass && !this._globalOptions.allowSecretKey) {\n throw new RavenConfigError(\n 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key'\n );\n }\n\n return dsn;\n },\n\n _getGlobalServer: function(uri) {\n // assemble the endpoint from the uri pieces\n var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : '');\n\n if (uri.protocol) {\n globalServer = uri.protocol + ':' + globalServer;\n }\n return globalServer;\n },\n\n _handleOnErrorStackInfo: function() {\n // if we are intentionally ignoring errors via onerror, bail out\n if (!this._ignoreOnError) {\n this._handleStackInfo.apply(this, arguments);\n }\n },\n\n _handleStackInfo: function(stackInfo, options) {\n var frames = this._prepareFrames(stackInfo, options);\n\n this._triggerEvent('handle', {\n stackInfo: stackInfo,\n options: options\n });\n\n this._processException(\n stackInfo.name,\n stackInfo.message,\n stackInfo.url,\n stackInfo.lineno,\n frames,\n options\n );\n },\n\n _prepareFrames: function(stackInfo, options) {\n var self = this;\n var frames = [];\n if (stackInfo.stack && stackInfo.stack.length) {\n each(stackInfo.stack, function(i, stack) {\n var frame = self._normalizeFrame(stack, stackInfo.url);\n if (frame) {\n frames.push(frame);\n }\n });\n\n // e.g. frames captured via captureMessage throw\n if (options && options.trimHeadFrames) {\n for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) {\n frames[j].in_app = false;\n }\n }\n }\n frames = frames.slice(0, this._globalOptions.stackTraceLimit);\n return frames;\n },\n\n _normalizeFrame: function(frame, stackInfoUrl) {\n // normalize the frames data\n var normalized = {\n filename: frame.url,\n lineno: frame.line,\n colno: frame.column,\n function: frame.func || '?'\n };\n\n // Case when we don't have any information about the error\n // E.g. throwing a string or raw object, instead of an `Error` in Firefox\n // Generating synthetic error doesn't add any value here\n //\n // We should probably somehow let a user know that they should fix their code\n if (!frame.url) {\n normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler\n }\n\n normalized.in_app = !// determine if an exception came from outside of our app\n // first we check the global includePaths list.\n (\n (!!this._globalOptions.includePaths.test &&\n !this._globalOptions.includePaths.test(normalized.filename)) ||\n // Now we check for fun, if the function name is Raven or TraceKit\n /(Raven|TraceKit)\\./.test(normalized['function']) ||\n // finally, we do a last ditch effort and check for raven.min.js\n /raven\\.(min\\.)?js$/.test(normalized.filename)\n );\n\n return normalized;\n },\n\n _processException: function(type, message, fileurl, lineno, frames, options) {\n var prefixedMessage = (type ? type + ': ' : '') + (message || '');\n if (\n !!this._globalOptions.ignoreErrors.test &&\n (this._globalOptions.ignoreErrors.test(message) ||\n this._globalOptions.ignoreErrors.test(prefixedMessage))\n ) {\n return;\n }\n\n var stacktrace;\n\n if (frames && frames.length) {\n fileurl = frames[0].filename || fileurl;\n // Sentry expects frames oldest to newest\n // and JS sends them as newest to oldest\n frames.reverse();\n stacktrace = {frames: frames};\n } else if (fileurl) {\n stacktrace = {\n frames: [\n {\n filename: fileurl,\n lineno: lineno,\n in_app: true\n }\n ]\n };\n }\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n var data = objectMerge(\n {\n // sentry.interfaces.Exception\n exception: {\n values: [\n {\n type: type,\n value: message,\n stacktrace: stacktrace\n }\n ]\n },\n culprit: fileurl\n },\n options\n );\n\n // Fire away!\n this._send(data);\n },\n\n _trimPacket: function(data) {\n // For now, we only want to truncate the two different messages\n // but this could/should be expanded to just trim everything\n var max = this._globalOptions.maxMessageLength;\n if (data.message) {\n data.message = truncate(data.message, max);\n }\n if (data.exception) {\n var exception = data.exception.values[0];\n exception.value = truncate(exception.value, max);\n }\n\n var request = data.request;\n if (request) {\n if (request.url) {\n request.url = truncate(request.url, this._globalOptions.maxUrlLength);\n }\n if (request.Referer) {\n request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);\n }\n }\n\n if (data.breadcrumbs && data.breadcrumbs.values)\n this._trimBreadcrumbs(data.breadcrumbs);\n\n return data;\n },\n\n /**\n * Truncate breadcrumb values (right now just URLs)\n */\n _trimBreadcrumbs: function(breadcrumbs) {\n // known breadcrumb properties with urls\n // TODO: also consider arbitrary prop values that start with (https?)?://\n var urlProps = ['to', 'from', 'url'],\n urlProp,\n crumb,\n data;\n\n for (var i = 0; i < breadcrumbs.values.length; ++i) {\n crumb = breadcrumbs.values[i];\n if (\n !crumb.hasOwnProperty('data') ||\n !isObject(crumb.data) ||\n objectFrozen(crumb.data)\n )\n continue;\n\n data = objectMerge({}, crumb.data);\n for (var j = 0; j < urlProps.length; ++j) {\n urlProp = urlProps[j];\n if (data.hasOwnProperty(urlProp) && data[urlProp]) {\n data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength);\n }\n }\n breadcrumbs.values[i].data = data;\n }\n },\n\n _getHttpData: function() {\n if (!this._hasNavigator && !this._hasDocument) return;\n var httpData = {};\n\n if (this._hasNavigator && _navigator.userAgent) {\n httpData.headers = {\n 'User-Agent': navigator.userAgent\n };\n }\n\n // Check in `window` instead of `document`, as we may be in ServiceWorker environment\n if (_window.location && _window.location.href) {\n httpData.url = _window.location.href;\n }\n\n if (this._hasDocument && _document.referrer) {\n if (!httpData.headers) httpData.headers = {};\n httpData.headers.Referer = _document.referrer;\n }\n\n return httpData;\n },\n\n _resetBackoff: function() {\n this._backoffDuration = 0;\n this._backoffStart = null;\n },\n\n _shouldBackoff: function() {\n return this._backoffDuration && now() - this._backoffStart < this._backoffDuration;\n },\n\n /**\n * Returns true if the in-process data payload matches the signature\n * of the previously-sent data\n *\n * NOTE: This has to be done at this level because TraceKit can generate\n * data from window.onerror WITHOUT an exception object (IE8, IE9,\n * other old browsers). This can take the form of an \"exception\"\n * data object with a single frame (derived from the onerror args).\n */\n _isRepeatData: function(current) {\n var last = this._lastData;\n\n if (\n !last ||\n current.message !== last.message || // defined for captureMessage\n current.culprit !== last.culprit // defined for captureException/onerror\n )\n return false;\n\n // Stacktrace interface (i.e. from captureMessage)\n if (current.stacktrace || last.stacktrace) {\n return isSameStacktrace(current.stacktrace, last.stacktrace);\n } else if (current.exception || last.exception) {\n // Exception interface (i.e. from captureException/onerror)\n return isSameException(current.exception, last.exception);\n }\n\n return true;\n },\n\n _setBackoffState: function(request) {\n // If we are already in a backoff state, don't change anything\n if (this._shouldBackoff()) {\n return;\n }\n\n var status = request.status;\n\n // 400 - project_id doesn't exist or some other fatal\n // 401 - invalid/revoked dsn\n // 429 - too many requests\n if (!(status === 400 || status === 401 || status === 429)) return;\n\n var retry;\n try {\n // If Retry-After is not in Access-Control-Expose-Headers, most\n // browsers will throw an exception trying to access it\n if (supportsFetch()) {\n retry = request.headers.get('Retry-After');\n } else {\n retry = request.getResponseHeader('Retry-After');\n }\n\n // Retry-After is returned in seconds\n retry = parseInt(retry, 10) * 1000;\n } catch (e) {\n /* eslint no-empty:0 */\n }\n\n this._backoffDuration = retry\n ? // If Sentry server returned a Retry-After value, use it\n retry\n : // Otherwise, double the last backoff duration (starts at 1 sec)\n this._backoffDuration * 2 || 1000;\n\n this._backoffStart = now();\n },\n\n _send: function(data) {\n var globalOptions = this._globalOptions;\n\n var baseData = {\n project: this._globalProject,\n logger: globalOptions.logger,\n platform: 'javascript'\n },\n httpData = this._getHttpData();\n\n if (httpData) {\n baseData.request = httpData;\n }\n\n // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload\n if (data.trimHeadFrames) delete data.trimHeadFrames;\n\n data = objectMerge(baseData, data);\n\n // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge\n data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags);\n data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra);\n\n // Send along our own collected metadata with extra\n data.extra['session:duration'] = now() - this._startTime;\n\n if (this._breadcrumbs && this._breadcrumbs.length > 0) {\n // intentionally make shallow copy so that additions\n // to breadcrumbs aren't accidentally sent in this request\n data.breadcrumbs = {\n values: [].slice.call(this._breadcrumbs, 0)\n };\n }\n\n if (this._globalContext.user) {\n // sentry.interfaces.User\n data.user = this._globalContext.user;\n }\n\n // Include the environment if it's defined in globalOptions\n if (globalOptions.environment) data.environment = globalOptions.environment;\n\n // Include the release if it's defined in globalOptions\n if (globalOptions.release) data.release = globalOptions.release;\n\n // Include server_name if it's defined in globalOptions\n if (globalOptions.serverName) data.server_name = globalOptions.serverName;\n\n data = this._sanitizeData(data);\n\n // Cleanup empty properties before sending them to the server\n Object.keys(data).forEach(function(key) {\n if (data[key] == null || data[key] === '' || isEmptyObject(data[key])) {\n delete data[key];\n }\n });\n\n if (isFunction(globalOptions.dataCallback)) {\n data = globalOptions.dataCallback(data) || data;\n }\n\n // Why??????????\n if (!data || isEmptyObject(data)) {\n return;\n }\n\n // Check if the request should be filtered or not\n if (\n isFunction(globalOptions.shouldSendCallback) &&\n !globalOptions.shouldSendCallback(data)\n ) {\n return;\n }\n\n // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests),\n // so drop requests until \"cool-off\" period has elapsed.\n if (this._shouldBackoff()) {\n this._logDebug('warn', 'Raven dropped error due to backoff: ', data);\n return;\n }\n\n if (typeof globalOptions.sampleRate === 'number') {\n if (Math.random() < globalOptions.sampleRate) {\n this._sendProcessedPayload(data);\n }\n } else {\n this._sendProcessedPayload(data);\n }\n },\n\n _sanitizeData: function(data) {\n return sanitize(data, this._globalOptions.sanitizeKeys);\n },\n\n _getUuid: function() {\n return uuid4();\n },\n\n _sendProcessedPayload: function(data, callback) {\n var self = this;\n var globalOptions = this._globalOptions;\n\n if (!this.isSetup()) return;\n\n // Try and clean up the packet before sending by truncating long values\n data = this._trimPacket(data);\n\n // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,\n // but this would require copying an un-truncated copy of the data packet, which can be\n // arbitrarily deep (extra_data) -- could be worthwhile? will revisit\n if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) {\n this._logDebug('warn', 'Raven dropped repeat event: ', data);\n return;\n }\n\n // Send along an event_id if not explicitly passed.\n // This event_id can be used to reference the error within Sentry itself.\n // Set lastEventId after we know the error should actually be sent\n this._lastEventId = data.event_id || (data.event_id = this._getUuid());\n\n // Store outbound payload after trim\n this._lastData = data;\n\n this._logDebug('debug', 'Raven about to send:', data);\n\n var auth = {\n sentry_version: '7',\n sentry_client: 'raven-js/' + this.VERSION,\n sentry_key: this._globalKey\n };\n\n if (this._globalSecret) {\n auth.sentry_secret = this._globalSecret;\n }\n\n var exception = data.exception && data.exception.values[0];\n\n // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy\n if (\n this._globalOptions.autoBreadcrumbs &&\n this._globalOptions.autoBreadcrumbs.sentry\n ) {\n this.captureBreadcrumb({\n category: 'sentry',\n message: exception\n ? (exception.type ? exception.type + ': ' : '') + exception.value\n : data.message,\n event_id: data.event_id,\n level: data.level || 'error' // presume error unless specified\n });\n }\n\n var url = this._globalEndpoint;\n (globalOptions.transport || this._makeRequest).call(this, {\n url: url,\n auth: auth,\n data: data,\n options: globalOptions,\n onSuccess: function success() {\n self._resetBackoff();\n\n self._triggerEvent('success', {\n data: data,\n src: url\n });\n callback && callback();\n },\n onError: function failure(error) {\n self._logDebug('error', 'Raven transport failed to send: ', error);\n\n if (error.request) {\n self._setBackoffState(error.request);\n }\n\n self._triggerEvent('failure', {\n data: data,\n src: url\n });\n error = error || new Error('Raven send failed (no additional details provided)');\n callback && callback(error);\n }\n });\n },\n\n _makeRequest: function(opts) {\n // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests\n var url = opts.url + '?' + urlencode(opts.auth);\n\n var evaluatedHeaders = null;\n var evaluatedFetchParameters = {};\n\n if (opts.options.headers) {\n evaluatedHeaders = this._evaluateHash(opts.options.headers);\n }\n\n if (opts.options.fetchParameters) {\n evaluatedFetchParameters = this._evaluateHash(opts.options.fetchParameters);\n }\n\n if (supportsFetch()) {\n evaluatedFetchParameters.body = stringify(opts.data);\n\n var defaultFetchOptions = objectMerge({}, this._fetchDefaults);\n var fetchOptions = objectMerge(defaultFetchOptions, evaluatedFetchParameters);\n\n if (evaluatedHeaders) {\n fetchOptions.headers = evaluatedHeaders;\n }\n\n return _window\n .fetch(url, fetchOptions)\n .then(function(response) {\n if (response.ok) {\n opts.onSuccess && opts.onSuccess();\n } else {\n var error = new Error('Sentry error code: ' + response.status);\n // It's called request only to keep compatibility with XHR interface\n // and not add more redundant checks in setBackoffState method\n error.request = response;\n opts.onError && opts.onError(error);\n }\n })\n ['catch'](function() {\n opts.onError &&\n opts.onError(new Error('Sentry error code: network unavailable'));\n });\n }\n\n var request = _window.XMLHttpRequest && new _window.XMLHttpRequest();\n if (!request) return;\n\n // if browser doesn't support CORS (e.g. IE7), we are out of luck\n var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined';\n\n if (!hasCORS) return;\n\n if ('withCredentials' in request) {\n request.onreadystatechange = function() {\n if (request.readyState !== 4) {\n return;\n } else if (request.status === 200) {\n opts.onSuccess && opts.onSuccess();\n } else if (opts.onError) {\n var err = new Error('Sentry error code: ' + request.status);\n err.request = request;\n opts.onError(err);\n }\n };\n } else {\n request = new XDomainRequest();\n // xdomainrequest cannot go http -> https (or vice versa),\n // so always use protocol relative\n url = url.replace(/^https?:/, '');\n\n // onreadystatechange not supported by XDomainRequest\n if (opts.onSuccess) {\n request.onload = opts.onSuccess;\n }\n if (opts.onError) {\n request.onerror = function() {\n var err = new Error('Sentry error code: XDomainRequest');\n err.request = request;\n opts.onError(err);\n };\n }\n }\n\n request.open('POST', url);\n\n if (evaluatedHeaders) {\n each(evaluatedHeaders, function(key, value) {\n request.setRequestHeader(key, value);\n });\n }\n\n request.send(stringify(opts.data));\n },\n\n _evaluateHash: function(hash) {\n var evaluated = {};\n\n for (var key in hash) {\n if (hash.hasOwnProperty(key)) {\n var value = hash[key];\n evaluated[key] = typeof value === 'function' ? value() : value;\n }\n }\n\n return evaluated;\n },\n\n _logDebug: function(level) {\n // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change\n if (\n this._originalConsoleMethods[level] &&\n (this.debug || this._globalOptions.debug)\n ) {\n // In IE<10 console methods do not have their own 'apply' method\n Function.prototype.apply.call(\n this._originalConsoleMethods[level],\n this._originalConsole,\n [].slice.call(arguments, 1)\n );\n }\n },\n\n _mergeContext: function(key, context) {\n if (isUndefined(context)) {\n delete this._globalContext[key];\n } else {\n this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context);\n }\n }\n};\n\n// Deprecations\nRaven.prototype.setUser = Raven.prototype.setUserContext;\nRaven.prototype.setReleaseContext = Raven.prototype.setRelease;\n\nmodule.exports = Raven;\n","/**\n * Enforces a single instance of the Raven client, and the\n * main entry point for Raven. If you are a consumer of the\n * Raven library, you SHOULD load this file (vs raven.js).\n **/\n\nvar RavenConstructor = require('./raven');\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _Raven = _window.Raven;\n\nvar Raven = new RavenConstructor();\n\n/*\n * Allow multiple versions of Raven to be installed.\n * Strip Raven from the global context and returns the instance.\n *\n * @return {Raven}\n */\nRaven.noConflict = function() {\n _window.Raven = _Raven;\n return Raven;\n};\n\nRaven.afterLoad();\n\nmodule.exports = Raven;\n\n/**\n * DISCLAIMER:\n *\n * Expose `Client` constructor for cases where user want to track multiple \"sub-applications\" in one larger app.\n * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it.\n * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug.\n *\n * It's called `Client' to be in-line with Raven Node implementation.\n *\n * HOWTO:\n *\n * import Raven from 'raven-js';\n *\n * const someAppReporter = new Raven.Client();\n * const someOtherAppReporter = new Raven.Client();\n *\n * someAppReporter.config('__DSN__', {\n * ...config goes here\n * });\n *\n * someOtherAppReporter.config('__OTHER_DSN__', {\n * ...config goes here\n * });\n *\n * someAppReporter.captureMessage(...);\n * someAppReporter.captureException(...);\n * someAppReporter.captureBreadcrumb(...);\n *\n * someOtherAppReporter.captureMessage(...);\n * someOtherAppReporter.captureException(...);\n * someOtherAppReporter.captureBreadcrumb(...);\n *\n * It should \"just work\".\n */\nmodule.exports.Client = RavenConstructor;\n","// ==========================================================================\n// Plyr.io demo\n// This code is purely for the https://plyr.io website\n// Please see readme.md in the root or github.com/sampotts/plyr\n// ==========================================================================\n\nimport Raven from 'raven-js';\n\n(() => {\n const isLive = window.location.host === 'plyr.io';\n\n // Raven / Sentry\n // For demo site (https://plyr.io) only\n if (isLive) {\n Raven.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install();\n }\n\n document.addEventListener('DOMContentLoaded', () => {\n Raven.context(() => {\n if (window.shr) {\n window.shr.setup({\n count: {\n classname: 'button__count',\n },\n });\n }\n\n // Setup tab focus\n const tabClassName = 'tab-focus';\n\n // Remove class on blur\n document.addEventListener('focusout', event => {\n event.target.classList.remove(tabClassName);\n });\n\n // Add classname to tabbed elements\n document.addEventListener('keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n document.activeElement.classList.add(tabClassName);\n }, 0);\n });\n\n // Setup the player\n const player = new Plyr('#player', {\n debug: true,\n title: 'View From A Blue Moon',\n iconUrl: '../dist/plyr.svg',\n keyboard: {\n global: true,\n },\n tooltips: {\n controls: true,\n },\n /* controls: [\n 'play-large',\n 'restart',\n 'rewind',\n 'play',\n 'fast-forward',\n 'progress',\n 'current-time',\n 'duration',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ], */\n /* i18n: {\n restart: '重新開始',\n rewind: '快退{seektime}秒',\n play: '播放',\n pause: '暫停',\n fastForward: '快進{seektime}秒',\n seek: '尋求',\n played: '發揮',\n buffered: '緩衝的',\n currentTime: '當前時間戳',\n duration: '長短',\n volume: '音量',\n mute: '靜音',\n unmute: '取消靜音',\n enableCaptions: '開啟字幕',\n disableCaptions: '關閉字幕',\n enterFullscreen: '進入全螢幕',\n exitFullscreen: '退出全螢幕',\n frameTitle: '球員為{title}',\n captions: '字幕',\n settings: '設定',\n speed: '速度',\n normal: '正常',\n quality: '質量',\n loop: '循環',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: '重啟',\n disabled: '殘',\n enabled: '啟用',\n advertisement: '廣告',\n }, */\n captions: {\n active: true,\n },\n keys: {\n google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c',\n },\n ads: {\n enabled: true,\n publisherId: '918848828995742',\n },\n });\n\n // Expose for tinkering in the console\n window.player = player;\n\n // Setup type toggle\n const buttons = document.querySelectorAll('[data-source]');\n const types = {\n video: 'video',\n audio: 'audio',\n youtube: 'youtube',\n vimeo: 'vimeo',\n };\n let currentType = window.location.hash.replace('#', '');\n const historySupport = window.history && window.history.pushState;\n\n // Toggle class on an element\n function toggleClass(element, className, state) {\n if (element) {\n element.classList[state ? 'add' : 'remove'](className);\n }\n }\n\n // Set a new source\n function newSource(type, init) {\n // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video\n if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) {\n return;\n }\n\n switch (type) {\n case types.video:\n player.source = {\n type: 'video',\n title: 'View From A Blue Moon',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',\n type: 'video/mp4',\n size: 576,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4',\n type: 'video/mp4',\n size: 720,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4',\n type: 'video/mp4',\n size: 1080,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4',\n type: 'video/mp4',\n size: 1440,\n },\n ],\n poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg',\n tracks: [\n {\n kind: 'captions',\n label: 'English',\n srclang: 'en',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n default: true,\n },\n {\n kind: 'captions',\n label: 'French',\n srclang: 'fr',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',\n },\n ],\n };\n\n break;\n\n case types.audio:\n player.source = {\n type: 'audio',\n title: 'Kishi Bashi – “It All Began With A Burst”',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',\n type: 'audio/mp3',\n },\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',\n type: 'audio/ogg',\n },\n ],\n };\n\n break;\n\n case types.youtube:\n player.source = {\n type: 'video',\n sources: [{\n src: 'https://youtube.com/watch?v=bTqVqk7FSmY',\n provider: 'youtube',\n }],\n };\n\n break;\n\n case types.vimeo:\n player.source = {\n type: 'video',\n sources: [{\n src: 'https://vimeo.com/76979871',\n provider: 'vimeo',\n }],\n };\n\n break;\n\n default:\n break;\n }\n\n // Set the current type for next time\n currentType = type;\n\n // Remove active classes\n Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));\n\n // Set active on parent\n toggleClass(document.querySelector(`[data-source=\"${type}\"]`), 'active', true);\n\n // Show cite\n Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {\n cite.setAttribute('hidden', '');\n });\n document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden');\n }\n\n // Bind to each button\n Array.from(buttons).forEach(button => {\n button.addEventListener('click', () => {\n const type = button.getAttribute('data-source');\n\n newSource(type);\n\n if (historySupport) {\n window.history.pushState({ type }, '', `#${type}`);\n }\n });\n });\n\n // List for backwards/forwards\n window.addEventListener('popstate', event => {\n if (event.state && 'type' in event.state) {\n newSource(event.state.type);\n }\n });\n\n // On load\n if (historySupport) {\n const video = !currentType.length;\n\n // If there's no current type set, assume video\n if (video) {\n currentType = types.video;\n }\n\n // Replace current history state\n if (currentType in types) {\n window.history.replaceState(\n {\n type: currentType,\n },\n '',\n video ? '' : `#${currentType}`,\n );\n }\n\n // If it's not video, load the source\n if (currentType !== types.video) {\n newSource(currentType, true);\n }\n }\n });\n });\n\n // Google analytics\n // For demo site (https://plyr.io) only\n /* eslint-disable */\n if (isLive) {\n (function(i, s, o, g, r, a, m) {\n i.GoogleAnalyticsObject = r;\n i[r] =\n i[r] ||\n function() {\n (i[r].q = i[r].q || []).push(arguments);\n };\n i[r].l = 1 * new Date();\n a = s.createElement(o);\n m = s.getElementsByTagName(o)[0];\n a.async = 1;\n a.src = g;\n m.parentNode.insertBefore(a, m);\n })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');\n window.ga('create', 'UA-40881672-11', 'auto');\n window.ga('send', 'pageview');\n }\n /* eslint-enable */\n})();\n"]}
\ No newline at end of file diff --git a/demo/dist/demo.min.js b/demo/dist/demo.min.js index f7c75ea2..29abb568 100644 --- a/demo/dist/demo.min.js +++ b/demo/dist/demo.min.js @@ -1,2 +1,2 @@ -!function(){"use strict";var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var t,r=(function(e,t){function r(e,t){for(var r=0;r<e.length;++r)if(e[r]===t)return r;return-1}function n(e,t){var n=[],o=[];return null==t&&(t=function(e,t){return n[0]===t?"[Circular ~]":"[Circular ~."+o.slice(0,r(n,t)).join(".")+"]"}),function(i,a){if(n.length>0){var s=r(n,this);~s?n.splice(s+1):n.push(this),~s?o.splice(s,1/0,i):o.push(i),~r(n,a)&&(a=t.call(this,i,a))}else n.push(a);return null==e?a instanceof Error?function(e){var t={stack:e.stack,message:e.message,name:e.name};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}(a):a:e.call(this,i,a)}}(e.exports=function(e,t,r,o){return JSON.stringify(e,n(t,o),r)}).getSerialize=n}(t={exports:{}},t.exports),t.exports),n=(r.getSerialize,"undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{});function o(e){return void 0===e}function i(e){return"[object Object]"===Object.prototype.toString.call(e)}function a(e){return"[object String]"===Object.prototype.toString.call(e)}function s(e){return"[object Array]"===Object.prototype.toString.call(e)}function c(){try{return new ErrorEvent(""),!0}catch(e){return!1}}function l(){if(!("fetch"in n))return!1;try{return new Headers,new Request(""),new Response,!0}catch(e){return!1}}function u(e,t){var r,n;if(o(e.length))for(r in e)p(e,r)&&t.call(null,r,e[r]);else if(n=e.length)for(r=0;r<n;r++)t.call(null,r,e[r])}function h(e,t){if("number"!=typeof t)throw new Error("2nd argument to `truncate` function should be a number");return"string"!=typeof e||0===t?e:e.length<=t?e:e.substr(0,t)+"…"}function p(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function f(e){for(var t,r=[],n=0,o=e.length;n<o;n++)a(t=e[n])?r.push(t.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")):t&&t.source&&r.push(t.source);return new RegExp(r.join("|"),"i")}function d(e){var t,r,n,o,i,s=[];if(!e||!e.tagName)return"";if(s.push(e.tagName.toLowerCase()),e.id&&s.push("#"+e.id),(t=e.className)&&a(t))for(r=t.split(/\s+/),i=0;i<r.length;i++)s.push("."+r[i]);var c=["type","name","title","alt"];for(i=0;i<c.length;i++)n=c[i],(o=e.getAttribute(n))&&s.push("["+n+'="'+o+'"]');return s.join("")}function g(e,t){return!!(!!e^!!t)}function _(e,t){if(g(e,t))return!1;var r,n,o=e.frames,i=t.frames;if(o.length!==i.length)return!1;for(var a=0;a<o.length;a++)if(r=o[a],n=i[a],r.filename!==n.filename||r.lineno!==n.lineno||r.colno!==n.colno||r.function!==n.function)return!1;return!0}var v=3,m=51200,b=40;function y(e){return function(e){return~-encodeURI(e).split(/%..|./).length}(JSON.stringify(e))}function E(e){if("string"==typeof e){return h(e,40)}if("number"==typeof e||"boolean"==typeof e||void 0===e)return e;var t=Object.prototype.toString.call(e);return"[object Object]"===t?"[Object]":"[object Array]"===t?"[Array]":"[object Function]"===t?e.name?"[Function: "+e.name+"]":"[Function]":e}var w={isObject:function(e){return"object"==typeof e&&null!==e},isError:function(e){switch({}.toString.call(e)){case"[object Error]":case"[object Exception]":case"[object DOMException]":return!0;default:return e instanceof Error}},isErrorEvent:function(e){return c()&&"[object ErrorEvent]"==={}.toString.call(e)},isUndefined:o,isFunction:function(e){return"function"==typeof e},isPlainObject:i,isString:a,isArray:s,isEmptyObject:function(e){if(!i(e))return!1;for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},supportsErrorEvent:c,supportsFetch:l,supportsReferrerPolicy:function(){if(!l())return!1;try{return new Request("pickleRick",{referrerPolicy:"origin"}),!0}catch(e){return!1}},supportsPromiseRejectionEvent:function(){return"function"==typeof PromiseRejectionEvent},wrappedCallback:function(e){return function(t,r){var n=e(t)||t;return r&&r(n)||n}},each:u,objectMerge:function(e,t){return t?(u(t,function(t,r){e[t]=r}),e):e},truncate:h,objectFrozen:function(e){return!!Object.isFrozen&&Object.isFrozen(e)},hasKey:p,joinRegExp:f,urlencode:function(e){var t=[];return u(e,function(e,r){t.push(encodeURIComponent(e)+"="+encodeURIComponent(r))}),t.join("&")},uuid4:function(){var e=n.crypto||n.msCrypto;if(!o(e)&&e.getRandomValues){var t=new Uint16Array(8);e.getRandomValues(t),t[3]=4095&t[3]|16384,t[4]=16383&t[4]|32768;var r=function(e){for(var t=e.toString(16);t.length<4;)t="0"+t;return t};return r(t[0])+r(t[1])+r(t[2])+r(t[3])+r(t[4])+r(t[5])+r(t[6])+r(t[7])}return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})},htmlTreeAsString:function(e){for(var t,r=[],n=0,o=0,i=" > ".length;e&&n++<5&&!("html"===(t=d(e))||n>1&&o+r.length*i+t.length>=80);)r.push(t),o+=t.length,e=e.parentNode;return r.reverse().join(" > ")},htmlElementAsString:d,isSameException:function(e,t){return!g(e,t)&&(e=e.values[0],t=t.values[0],e.type===t.type&&e.value===t.value&&(r=e.stacktrace,n=t.stacktrace,(!o(r)||!o(n))&&_(e.stacktrace,t.stacktrace)));var r,n},isSameStacktrace:_,parseUrl:function(e){if("string"!=typeof e)return{};var t=e.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/),r=t[6]||"",n=t[8]||"";return{protocol:t[2],host:t[4],path:t[5],relative:t[5]+r+n}},fill:function(e,t,r,n){if(null!=e){var o=e[t];e[t]=r(o),e[t].__raven__=!0,e[t].__orig__=o,n&&n.push([e,t,o])}},safeJoin:function(e,t){if(!s(e))return"";for(var r=[],n=0;n<e.length;n++)try{r.push(String(e[n]))}catch(e){r.push("[value cannot be serialized]")}return r.join(t)},serializeException:function e(t,n,o){if(!i(t))return t;o="number"!=typeof(n="number"!=typeof n?v:n)?m:o;var a=function e(t,r){return 0===r?E(t):i(t)?Object.keys(t).reduce(function(n,o){return n[o]=e(t[o],r-1),n},{}):Array.isArray(t)?t.map(function(t){return e(t,r-1)}):E(t)}(t,n);return y(r(a))>o?e(t,n-1):a},serializeKeysForMessage:function(e,t){if("number"==typeof e||"string"==typeof e)return e.toString();if(!Array.isArray(e))return"";if(0===(e=e.filter(function(e){return"string"==typeof e})).length)return"[object has no keys]";if(t="number"!=typeof t?b:t,e[0].length>=t)return e[0];for(var r=e.length;r>0;r--){var n=e.slice(0,r).join(", ");if(!(n.length>t))return r===e.length?n:n+"…"}return""},sanitize:function(e,t){if(!s(t)||s(t)&&0===t.length)return e;var n,o=f(t),a="********";try{n=JSON.parse(r(e))}catch(t){return e}return function e(t){return s(t)?t.map(function(t){return e(t)}):i(t)?Object.keys(t).reduce(function(r,n){return o.test(n)?r[n]=a:r[n]=e(t[n]),r},{}):t}(n)}},k={collectWindowErrors:!0,debug:!1},x="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},S=[].slice,O="?",C=/^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;function R(){return"undefined"==typeof document||null==document.location?"":document.location.href}k.report=function(){var e,t,r=[],n=null,o=null,i=null;function a(e,t){var n=null;if(!t||k.collectWindowErrors){for(var o in r)if(r.hasOwnProperty(o))try{r[o].apply(null,[e].concat(S.call(arguments,2)))}catch(e){n=e}if(n)throw n}}function s(t,r,n,o,s){var l=w.isErrorEvent(s)?s.error:s,u=w.isErrorEvent(t)?t.message:t;if(i)k.computeStackTrace.augmentStackTraceWithInitialElement(i,r,n,u),c();else if(l&&w.isError(l))a(k.computeStackTrace(l),!0);else{var h,p={url:r,line:n,column:o},f=void 0;if("[object String]"==={}.toString.call(u))(h=u.match(C))&&(f=h[1],u=h[2]);p.func=O,a({name:f,message:u,url:R(),stack:[p]},!0)}return!!e&&e.apply(this,arguments)}function c(){var e=i,t=n;n=null,i=null,o=null,a.apply(null,[e,!1].concat(t))}function l(e,t){var r=S.call(arguments,1);if(i){if(o===e)return;c()}var a=k.computeStackTrace(e);if(i=a,o=e,n=r,setTimeout(function(){o===e&&c()},a.incomplete?2e3:0),!1!==t)throw e}return l.subscribe=function(n){t||(e=x.onerror,x.onerror=s,t=!0),r.push(n)},l.unsubscribe=function(e){for(var t=r.length-1;t>=0;--t)r[t]===e&&r.splice(t,1)},l.uninstall=function(){t&&(x.onerror=e,t=!1,e=void 0),r=[]},l}(),k.computeStackTrace=function(){function e(e){if(void 0!==e.stack&&e.stack){for(var t,r,n,o=/^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,i=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,a=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,s=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,c=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=e.stack.split("\n"),u=[],h=(/^(.*) is undefined$/.exec(e.message),0),p=l.length;h<p;++h){if(r=o.exec(l[h])){var f=r[2]&&0===r[2].indexOf("native");r[2]&&0===r[2].indexOf("eval")&&(t=c.exec(r[2]))&&(r[2]=t[1],r[3]=t[2],r[4]=t[3]),n={url:f?null:r[2],func:r[1]||O,args:f?[r[2]]:[],line:r[3]?+r[3]:null,column:r[4]?+r[4]:null}}else if(r=i.exec(l[h]))n={url:r[2],func:r[1]||O,args:[],line:+r[3],column:r[4]?+r[4]:null};else{if(!(r=a.exec(l[h])))continue;r[3]&&r[3].indexOf(" > eval")>-1&&(t=s.exec(r[3]))?(r[3]=t[1],r[4]=t[2],r[5]=null):0!==h||r[5]||void 0===e.columnNumber||(u[0].column=e.columnNumber+1),n={url:r[3],func:r[1]||O,args:r[2]?r[2].split(","):[],line:r[4]?+r[4]:null,column:r[5]?+r[5]:null}}!n.func&&n.line&&(n.func=O),u.push(n)}return u.length?{name:e.name,message:e.message,url:R(),stack:u}:null}}function t(e,t,r,n){var o={url:t,line:r};if(o.url&&o.line){if(e.incomplete=!1,o.func||(o.func=O),e.stack.length>0&&e.stack[0].url===o.url){if(e.stack[0].line===o.line)return!1;if(!e.stack[0].line&&e.stack[0].func===o.func)return e.stack[0].line=o.line,!1}return e.stack.unshift(o),e.partial=!0,!0}return e.incomplete=!0,!1}function r(e,o){for(var i,a,s=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,c=[],l={},u=!1,h=r.caller;h&&!u;h=h.caller)if(h!==n&&h!==k.report){if(a={url:null,func:O,line:null,column:null},h.name?a.func=h.name:(i=s.exec(h.toString()))&&(a.func=i[1]),void 0===a.func)try{a.func=i.input.substring(0,i.input.indexOf("{"))}catch(e){}l[""+h]?u=!0:l[""+h]=!0,c.push(a)}o&&c.splice(0,o);var p={name:e.name,message:e.message,url:R(),stack:c};return t(p,e.sourceURL||e.fileName,e.line||e.lineNumber,e.message||e.description),p}function n(t,n){var o=null;n=null==n?0:+n;try{if(o=e(t))return o}catch(e){if(k.debug)throw e}try{if(o=r(t,n+1))return o}catch(e){if(k.debug)throw e}return{name:t.name,message:t.message,url:R()}}return n.augmentStackTraceWithInitialElement=t,n.computeStackTraceFromStackProp=e,n}();var j=k;function T(e,t){var r=(65535&e)+(65535&t);return(e>>16)+(t>>16)+(r>>16)<<16|65535&r}function F(e,t,r,n,o,i){return T((a=T(T(t,e),T(n,i)))<<(s=o)|a>>>32-s,r);var a,s}function A(e,t,r,n,o,i,a){return F(t&r|~t&n,e,t,o,i,a)}function B(e,t,r,n,o,i,a){return F(t&n|r&~n,e,t,o,i,a)}function D(e,t,r,n,o,i,a){return F(t^r^n,e,t,o,i,a)}function H(e,t,r,n,o,i,a){return F(r^(t|~n),e,t,o,i,a)}function L(e,t){var r,n,o,i,a;e[t>>5]|=128<<t%32,e[14+(t+64>>>9<<4)]=t;var s=1732584193,c=-271733879,l=-1732584194,u=271733878;for(r=0;r<e.length;r+=16)n=s,o=c,i=l,a=u,c=H(c=H(c=H(c=H(c=D(c=D(c=D(c=D(c=B(c=B(c=B(c=B(c=A(c=A(c=A(c=A(c,l=A(l,u=A(u,s=A(s,c,l,u,e[r],7,-680876936),c,l,e[r+1],12,-389564586),s,c,e[r+2],17,606105819),u,s,e[r+3],22,-1044525330),l=A(l,u=A(u,s=A(s,c,l,u,e[r+4],7,-176418897),c,l,e[r+5],12,1200080426),s,c,e[r+6],17,-1473231341),u,s,e[r+7],22,-45705983),l=A(l,u=A(u,s=A(s,c,l,u,e[r+8],7,1770035416),c,l,e[r+9],12,-1958414417),s,c,e[r+10],17,-42063),u,s,e[r+11],22,-1990404162),l=A(l,u=A(u,s=A(s,c,l,u,e[r+12],7,1804603682),c,l,e[r+13],12,-40341101),s,c,e[r+14],17,-1502002290),u,s,e[r+15],22,1236535329),l=B(l,u=B(u,s=B(s,c,l,u,e[r+1],5,-165796510),c,l,e[r+6],9,-1069501632),s,c,e[r+11],14,643717713),u,s,e[r],20,-373897302),l=B(l,u=B(u,s=B(s,c,l,u,e[r+5],5,-701558691),c,l,e[r+10],9,38016083),s,c,e[r+15],14,-660478335),u,s,e[r+4],20,-405537848),l=B(l,u=B(u,s=B(s,c,l,u,e[r+9],5,568446438),c,l,e[r+14],9,-1019803690),s,c,e[r+3],14,-187363961),u,s,e[r+8],20,1163531501),l=B(l,u=B(u,s=B(s,c,l,u,e[r+13],5,-1444681467),c,l,e[r+2],9,-51403784),s,c,e[r+7],14,1735328473),u,s,e[r+12],20,-1926607734),l=D(l,u=D(u,s=D(s,c,l,u,e[r+5],4,-378558),c,l,e[r+8],11,-2022574463),s,c,e[r+11],16,1839030562),u,s,e[r+14],23,-35309556),l=D(l,u=D(u,s=D(s,c,l,u,e[r+1],4,-1530992060),c,l,e[r+4],11,1272893353),s,c,e[r+7],16,-155497632),u,s,e[r+10],23,-1094730640),l=D(l,u=D(u,s=D(s,c,l,u,e[r+13],4,681279174),c,l,e[r],11,-358537222),s,c,e[r+3],16,-722521979),u,s,e[r+6],23,76029189),l=D(l,u=D(u,s=D(s,c,l,u,e[r+9],4,-640364487),c,l,e[r+12],11,-421815835),s,c,e[r+15],16,530742520),u,s,e[r+2],23,-995338651),l=H(l,u=H(u,s=H(s,c,l,u,e[r],6,-198630844),c,l,e[r+7],10,1126891415),s,c,e[r+14],15,-1416354905),u,s,e[r+5],21,-57434055),l=H(l,u=H(u,s=H(s,c,l,u,e[r+12],6,1700485571),c,l,e[r+3],10,-1894986606),s,c,e[r+10],15,-1051523),u,s,e[r+1],21,-2054922799),l=H(l,u=H(u,s=H(s,c,l,u,e[r+8],6,1873313359),c,l,e[r+15],10,-30611744),s,c,e[r+6],15,-1560198380),u,s,e[r+13],21,1309151649),l=H(l,u=H(u,s=H(s,c,l,u,e[r+4],6,-145523070),c,l,e[r+11],10,-1120210379),s,c,e[r+2],15,718787259),u,s,e[r+9],21,-343485551),s=T(s,n),c=T(c,o),l=T(l,i),u=T(u,a);return[s,c,l,u]}function P(e){var t,r="",n=32*e.length;for(t=0;t<n;t+=8)r+=String.fromCharCode(e[t>>5]>>>t%32&255);return r}function I(e){var t,r=[];for(r[(e.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var n=8*e.length;for(t=0;t<n;t+=8)r[t>>5]|=(255&e.charCodeAt(t/8))<<t%32;return r}function U(e){var t,r,n="";for(r=0;r<e.length;r+=1)t=e.charCodeAt(r),n+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return n}function N(e){return unescape(encodeURIComponent(e))}function M(e){return function(e){return P(L(I(e),8*e.length))}(N(e))}function q(e,t){return function(e,t){var r,n,o=I(e),i=[],a=[];for(i[15]=a[15]=void 0,o.length>16&&(o=L(o,8*e.length)),r=0;r<16;r+=1)i[r]=909522486^o[r],a[r]=1549556828^o[r];return n=L(i.concat(I(t)),512+8*t.length),P(L(a.concat(n),640))}(N(e),N(t))}var z=function(e,t,r){return t?r?q(t,e):U(q(t,e)):r?M(e):U(M(e))};function K(e){this.name="RavenConfigError",this.message=e}K.prototype=new Error,K.prototype.constructor=K;var W=K,V=function(e,t,r){var n=e[t],o=e;if(t in e){var i="warn"===t?"warning":t;e[t]=function(){var e=[].slice.call(arguments),a=w.safeJoin(e," "),s={level:i,logger:"console",extra:{arguments:e}};"assert"===t?!1===e[0]&&(a="Assertion failed: "+(w.safeJoin(e.slice(1)," ")||"console.assert"),s.extra.arguments=e.slice(1),r&&r(a,s)):r&&r(a,s),n&&Function.prototype.apply.call(n,o,e)}}},$=w.isError,J=w.isObject,X=w.isPlainObject,G=w.isErrorEvent,Y=w.isUndefined,Z=w.isFunction,Q=w.isString,ee=w.isArray,te=w.isEmptyObject,re=w.each,ne=w.objectMerge,oe=w.truncate,ie=w.objectFrozen,ae=w.hasKey,se=w.joinRegExp,ce=w.urlencode,le=w.uuid4,ue=w.htmlTreeAsString,he=w.isSameException,pe=w.isSameStacktrace,fe=w.parseUrl,de=w.fill,ge=w.supportsFetch,_e=w.supportsReferrerPolicy,ve=w.serializeKeysForMessage,me=w.serializeException,be=w.sanitize,ye=V,Ee="source protocol user pass host port path".split(" "),we=/^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/;function ke(){return+new Date}var xe="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},Se=xe.document,Oe=xe.navigator;function Ce(e,t){return Z(t)?function(r){return t(r,e)}:t}function Re(){for(var e in this._hasJSON=!("object"!=typeof JSON||!JSON.stringify),this._hasDocument=!Y(Se),this._hasNavigator=!Y(Oe),this._lastCapturedException=null,this._lastData=null,this._lastEventId=null,this._globalServer=null,this._globalKey=null,this._globalProject=null,this._globalContext={},this._globalOptions={release:xe.SENTRY_RELEASE&&xe.SENTRY_RELEASE.id,logger:"javascript",ignoreErrors:[],ignoreUrls:[],whitelistUrls:[],includePaths:[],headers:null,collectWindowErrors:!0,captureUnhandledRejections:!0,maxMessageLength:0,maxUrlLength:250,stackTraceLimit:50,autoBreadcrumbs:!0,instrument:!0,sampleRate:1,sanitizeKeys:[]},this._fetchDefaults={method:"POST",keepalive:!0,referrerPolicy:_e()?"origin":""},this._ignoreOnError=0,this._isRavenInstalled=!1,this._originalErrorStackTraceLimit=Error.stackTraceLimit,this._originalConsole=xe.console||{},this._originalConsoleMethods={},this._plugins=[],this._startTime=ke(),this._wrappedBuiltIns=[],this._breadcrumbs=[],this._lastCapturedEvent=null,this._keypressTimeout,this._location=xe.location,this._lastHref=this._location&&this._location.href,this._resetBackoff(),this._originalConsole)this._originalConsoleMethods[e]=this._originalConsole[e]}Re.prototype={VERSION:"3.24.2",debug:!1,TraceKit:j,config:function(e,t){var r=this;if(r._globalServer)return this._logDebug("error","Error: Raven has already been configured"),r;if(!e)return r;var n=r._globalOptions;t&&re(t,function(e,t){"tags"===e||"extra"===e||"user"===e?r._globalContext[e]=t:n[e]=t}),r.setDSN(e),n.ignoreErrors.push(/^Script error\.?$/),n.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/),n.ignoreErrors=se(n.ignoreErrors),n.ignoreUrls=!!n.ignoreUrls.length&&se(n.ignoreUrls),n.whitelistUrls=!!n.whitelistUrls.length&&se(n.whitelistUrls),n.includePaths=se(n.includePaths),n.maxBreadcrumbs=Math.max(0,Math.min(n.maxBreadcrumbs||100,100));var o={xhr:!0,console:!0,dom:!0,location:!0,sentry:!0},i=n.autoBreadcrumbs;"[object Object]"==={}.toString.call(i)?i=ne(o,i):!1!==i&&(i=o),n.autoBreadcrumbs=i;var a={tryCatch:!0},s=n.instrument;return"[object Object]"==={}.toString.call(s)?s=ne(a,s):!1!==s&&(s=a),n.instrument=s,j.collectWindowErrors=!!n.collectWindowErrors,r},install:function(){var e=this;return e.isSetup()&&!e._isRavenInstalled&&(j.report.subscribe(function(){e._handleOnErrorStackInfo.apply(e,arguments)}),e._globalOptions.captureUnhandledRejections&&e._attachPromiseRejectionHandler(),e._patchFunctionToString(),e._globalOptions.instrument&&e._globalOptions.instrument.tryCatch&&e._instrumentTryCatch(),e._globalOptions.autoBreadcrumbs&&e._instrumentBreadcrumbs(),e._drainPlugins(),e._isRavenInstalled=!0),Error.stackTraceLimit=e._globalOptions.stackTraceLimit,this},setDSN:function(e){var t=this._parseDSN(e),r=t.path.lastIndexOf("/"),n=t.path.substr(1,r);this._dsn=e,this._globalKey=t.user,this._globalSecret=t.pass&&t.pass.substr(1),this._globalProject=t.path.substr(r+1),this._globalServer=this._getGlobalServer(t),this._globalEndpoint=this._globalServer+"/"+n+"api/"+this._globalProject+"/store/",this._resetBackoff()},context:function(e,t,r){return Z(e)&&(r=t||[],t=e,e=void 0),this.wrap(e,t).apply(this,r)},wrap:function(e,t,r){var n=this;if(Y(t)&&!Z(e))return e;if(Z(e)&&(t=e,e=void 0),!Z(t))return t;try{if(t.__raven__)return t;if(t.__raven_wrapper__)return t.__raven_wrapper__}catch(e){return t}function o(){var o=[],i=arguments.length,a=!e||e&&!1!==e.deep;for(r&&Z(r)&&r.apply(this,arguments);i--;)o[i]=a?n.wrap(e,arguments[i]):arguments[i];try{return t.apply(this,o)}catch(t){throw n._ignoreNextOnError(),n.captureException(t,e),t}}for(var i in t)ae(t,i)&&(o[i]=t[i]);return o.prototype=t.prototype,t.__raven_wrapper__=o,o.__raven__=!0,o.__orig__=t,o},uninstall:function(){return j.report.uninstall(),this._detachPromiseRejectionHandler(),this._unpatchFunctionToString(),this._restoreBuiltIns(),this._restoreConsole(),Error.stackTraceLimit=this._originalErrorStackTraceLimit,this._isRavenInstalled=!1,this},_promiseRejectionHandler:function(e){this._logDebug("debug","Raven caught unhandled promise rejection:",e),this.captureException(e.reason,{extra:{unhandledPromiseRejection:!0}})},_attachPromiseRejectionHandler:function(){return this._promiseRejectionHandler=this._promiseRejectionHandler.bind(this),xe.addEventListener&&xe.addEventListener("unhandledrejection",this._promiseRejectionHandler),this},_detachPromiseRejectionHandler:function(){return xe.removeEventListener&&xe.removeEventListener("unhandledrejection",this._promiseRejectionHandler),this},captureException:function(e,t){if(t=ne({trimHeadFrames:0},t||{}),G(e)&&e.error)e=e.error;else if($(e))e=e;else{if(!X(e))return this.captureMessage(e,ne(t,{stacktrace:!0,trimHeadFrames:t.trimHeadFrames+1}));t=this._getCaptureExceptionOptionsFromPlainObject(t,e),e=new Error(t.message)}this._lastCapturedException=e;try{var r=j.computeStackTrace(e);this._handleStackInfo(r,t)}catch(t){if(e!==t)throw t}return this},_getCaptureExceptionOptionsFromPlainObject:function(e,t){var r=Object.keys(t).sort(),n=ne(e,{message:"Non-Error exception captured with keys: "+ve(r),fingerprint:[z(r)],extra:e.extra||{}});return n.extra.__serialized__=me(t),n},captureMessage:function(e,t){if(!this._globalOptions.ignoreErrors.test||!this._globalOptions.ignoreErrors.test(e)){var r,n=ne({message:e+=""},t=t||{});try{throw new Error(e)}catch(e){r=e}r.name=null;var o=j.computeStackTrace(r),i=ee(o.stack)&&o.stack[1];i&&"Raven.captureException"===i.func&&(i=o.stack[2]);var a=i&&i.url||"";if((!this._globalOptions.ignoreUrls.test||!this._globalOptions.ignoreUrls.test(a))&&(!this._globalOptions.whitelistUrls.test||this._globalOptions.whitelistUrls.test(a))){if(this._globalOptions.stacktrace||t&&t.stacktrace){n.fingerprint=null==n.fingerprint?e:n.fingerprint,(t=ne({trimHeadFrames:0},t)).trimHeadFrames+=1;var s=this._prepareFrames(o,t);n.stacktrace={frames:s.reverse()}}return n.fingerprint&&(n.fingerprint=ee(n.fingerprint)?n.fingerprint:[n.fingerprint]),this._send(n),this}}},captureBreadcrumb:function(e){var t=ne({timestamp:ke()/1e3},e);if(Z(this._globalOptions.breadcrumbCallback)){var r=this._globalOptions.breadcrumbCallback(t);if(J(r)&&!te(r))t=r;else if(!1===r)return this}return this._breadcrumbs.push(t),this._breadcrumbs.length>this._globalOptions.maxBreadcrumbs&&this._breadcrumbs.shift(),this},addPlugin:function(e){var t=[].slice.call(arguments,1);return this._plugins.push([e,t]),this._isRavenInstalled&&this._drainPlugins(),this},setUserContext:function(e){return this._globalContext.user=e,this},setExtraContext:function(e){return this._mergeContext("extra",e),this},setTagsContext:function(e){return this._mergeContext("tags",e),this},clearContext:function(){return this._globalContext={},this},getContext:function(){return JSON.parse(r(this._globalContext))},setEnvironment:function(e){return this._globalOptions.environment=e,this},setRelease:function(e){return this._globalOptions.release=e,this},setDataCallback:function(e){var t=this._globalOptions.dataCallback;return this._globalOptions.dataCallback=Ce(t,e),this},setBreadcrumbCallback:function(e){var t=this._globalOptions.breadcrumbCallback;return this._globalOptions.breadcrumbCallback=Ce(t,e),this},setShouldSendCallback:function(e){var t=this._globalOptions.shouldSendCallback;return this._globalOptions.shouldSendCallback=Ce(t,e),this},setTransport:function(e){return this._globalOptions.transport=e,this},lastException:function(){return this._lastCapturedException},lastEventId:function(){return this._lastEventId},isSetup:function(){return!!this._hasJSON&&(!!this._globalServer||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this._logDebug("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var e=xe.RavenConfig;e&&this.config(e.dsn,e.config).install()},showReportDialog:function(e){if(Se){var t=(e=e||{}).eventId||this.lastEventId();if(!t)throw new W("Missing eventId");var r=e.dsn||this._dsn;if(!r)throw new W("Missing DSN");var n=encodeURIComponent,o="";o+="?eventId="+n(t),o+="&dsn="+n(r);var i=e.user||this._globalContext.user;i&&(i.name&&(o+="&name="+n(i.name)),i.email&&(o+="&email="+n(i.email)));var a=this._getGlobalServer(this._parseDSN(r)),s=Se.createElement("script");s.async=!0,s.src=a+"/api/embed/error-page/"+o,(Se.head||Se.body).appendChild(s)}},_ignoreNextOnError:function(){var e=this;this._ignoreOnError+=1,setTimeout(function(){e._ignoreOnError-=1})},_triggerEvent:function(e,t){var r,n;if(this._hasDocument){for(n in t=t||{},e="raven"+e.substr(0,1).toUpperCase()+e.substr(1),Se.createEvent?(r=Se.createEvent("HTMLEvents")).initEvent(e,!0,!0):(r=Se.createEventObject()).eventType=e,t)ae(t,n)&&(r[n]=t[n]);if(Se.createEvent)Se.dispatchEvent(r);else try{Se.fireEvent("on"+r.eventType.toLowerCase(),r)}catch(e){}}},_breadcrumbEventHandler:function(e){var t=this;return function(r){if(t._keypressTimeout=null,t._lastCapturedEvent!==r){var n;t._lastCapturedEvent=r;try{n=ue(r.target)}catch(e){n="<unknown>"}t.captureBreadcrumb({category:"ui."+e,message:n})}}},_keypressEventHandler:function(){var e=this;return function(t){var r;try{r=t.target}catch(e){return}var n=r&&r.tagName;if(n&&("INPUT"===n||"TEXTAREA"===n||r.isContentEditable)){var o=e._keypressTimeout;o||e._breadcrumbEventHandler("input")(t),clearTimeout(o),e._keypressTimeout=setTimeout(function(){e._keypressTimeout=null},1e3)}}},_captureUrlChange:function(e,t){var r=fe(this._location.href),n=fe(t),o=fe(e);this._lastHref=t,r.protocol===n.protocol&&r.host===n.host&&(t=n.relative),r.protocol===o.protocol&&r.host===o.host&&(e=o.relative),this.captureBreadcrumb({category:"navigation",data:{to:t,from:e}})},_patchFunctionToString:function(){var e=this;e._originalFunctionToString=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.__raven__?e._originalFunctionToString.apply(this.__orig__,arguments):e._originalFunctionToString.apply(this,arguments)}},_unpatchFunctionToString:function(){this._originalFunctionToString&&(Function.prototype.toString=this._originalFunctionToString)},_instrumentTryCatch:function(){var e=this,t=e._wrappedBuiltIns;function r(t){return function(r,n){for(var o=new Array(arguments.length),i=0;i<o.length;++i)o[i]=arguments[i];var a=o[0];return Z(a)&&(o[0]=e.wrap(a)),t.apply?t.apply(this,o):t(o[0],o[1])}}var n=this._globalOptions.autoBreadcrumbs;function o(r){var o=xe[r]&&xe[r].prototype;o&&o.hasOwnProperty&&o.hasOwnProperty("addEventListener")&&(de(o,"addEventListener",function(t){return function(o,i,a,s){try{i&&i.handleEvent&&(i.handleEvent=e.wrap(i.handleEvent))}catch(e){}var c,l,u;return n&&n.dom&&("EventTarget"===r||"Node"===r)&&(l=e._breadcrumbEventHandler("click"),u=e._keypressEventHandler(),c=function(e){if(e){var t;try{t=e.type}catch(e){return}return"click"===t?l(e):"keypress"===t?u(e):void 0}}),t.call(this,o,e.wrap(i,void 0,c),a,s)}},t),de(o,"removeEventListener",function(e){return function(t,r,n,o){try{r=r&&(r.__raven_wrapper__?r.__raven_wrapper__:r)}catch(e){}return e.call(this,t,r,n,o)}},t))}de(xe,"setTimeout",r,t),de(xe,"setInterval",r,t),xe.requestAnimationFrame&&de(xe,"requestAnimationFrame",function(t){return function(r){return t(e.wrap(r))}},t);for(var i=["EventTarget","Window","Node","ApplicationCache","AudioTrackList","ChannelMergerNode","CryptoOperation","EventSource","FileReader","HTMLUnknownElement","IDBDatabase","IDBRequest","IDBTransaction","KeyOperation","MediaController","MessagePort","ModalWindow","Notification","SVGElementInstance","Screen","TextTrack","TextTrackCue","TextTrackList","WebSocket","WebSocketWorker","Worker","XMLHttpRequest","XMLHttpRequestEventTarget","XMLHttpRequestUpload"],a=0;a<i.length;a++)o(i[a])},_instrumentBreadcrumbs:function(){var e=this,t=this._globalOptions.autoBreadcrumbs,r=e._wrappedBuiltIns;function n(t,r){t in r&&Z(r[t])&&de(r,t,function(t){return e.wrap(t)})}if(t.xhr&&"XMLHttpRequest"in xe){var o=xe.XMLHttpRequest&&xe.XMLHttpRequest.prototype;de(o,"open",function(t){return function(r,n){return Q(n)&&-1===n.indexOf(e._globalKey)&&(this.__raven_xhr={method:r,url:n,status_code:null}),t.apply(this,arguments)}},r),de(o,"send",function(t){return function(){var r=this;function o(){if(r.__raven_xhr&&4===r.readyState){try{r.__raven_xhr.status_code=r.status}catch(e){}e.captureBreadcrumb({type:"http",category:"xhr",data:r.__raven_xhr})}}for(var i=["onload","onerror","onprogress"],a=0;a<i.length;a++)n(i[a],r);return"onreadystatechange"in r&&Z(r.onreadystatechange)?de(r,"onreadystatechange",function(t){return e.wrap(t,void 0,o)}):r.onreadystatechange=o,t.apply(this,arguments)}},r)}t.xhr&&ge()&&de(xe,"fetch",function(t){return function(){for(var r=new Array(arguments.length),n=0;n<r.length;++n)r[n]=arguments[n];var o,i=r[0],a="GET";if("string"==typeof i?o=i:"Request"in xe&&i instanceof xe.Request?(o=i.url,i.method&&(a=i.method)):o=""+i,-1!==o.indexOf(e._globalKey))return t.apply(this,r);r[1]&&r[1].method&&(a=r[1].method);var s={method:a,url:o,status_code:null};return t.apply(this,r).then(function(t){return s.status_code=t.status,e.captureBreadcrumb({type:"http",category:"fetch",data:s}),t}).catch(function(t){throw e.captureBreadcrumb({type:"http",category:"fetch",data:s,level:"error"}),t})}},r),t.dom&&this._hasDocument&&(Se.addEventListener?(Se.addEventListener("click",e._breadcrumbEventHandler("click"),!1),Se.addEventListener("keypress",e._keypressEventHandler(),!1)):Se.attachEvent&&(Se.attachEvent("onclick",e._breadcrumbEventHandler("click")),Se.attachEvent("onkeypress",e._keypressEventHandler())));var i=xe.chrome,a=!(i&&i.app&&i.app.runtime)&&xe.history&&history.pushState&&history.replaceState;if(t.location&&a){var s=xe.onpopstate;xe.onpopstate=function(){var t=e._location.href;if(e._captureUrlChange(e._lastHref,t),s)return s.apply(this,arguments)};var c=function(t){return function(){var r=arguments.length>2?arguments[2]:void 0;return r&&e._captureUrlChange(e._lastHref,r+""),t.apply(this,arguments)}};de(history,"pushState",c,r),de(history,"replaceState",c,r)}if(t.console&&"console"in xe&&console.log){var l=function(t,r){e.captureBreadcrumb({message:t,level:r.level,category:"console"})};re(["debug","info","warn","error","log"],function(e,t){ye(console,t,l)})}},_restoreBuiltIns:function(){for(var e;this._wrappedBuiltIns.length;){var t=(e=this._wrappedBuiltIns.shift())[0],r=e[1],n=e[2];t[r]=n}},_restoreConsole:function(){for(var e in this._originalConsoleMethods)this._originalConsole[e]=this._originalConsoleMethods[e]},_drainPlugins:function(){var e=this;re(this._plugins,function(t,r){var n=r[0],o=r[1];n.apply(e,[e].concat(o))})},_parseDSN:function(e){var t=we.exec(e),r={},n=7;try{for(;n--;)r[Ee[n]]=t[n]||""}catch(t){throw new W("Invalid DSN: "+e)}if(r.pass&&!this._globalOptions.allowSecretKey)throw new W("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return r},_getGlobalServer:function(e){var t="//"+e.host+(e.port?":"+e.port:"");return e.protocol&&(t=e.protocol+":"+t),t},_handleOnErrorStackInfo:function(){this._ignoreOnError||this._handleStackInfo.apply(this,arguments)},_handleStackInfo:function(e,t){var r=this._prepareFrames(e,t);this._triggerEvent("handle",{stackInfo:e,options:t}),this._processException(e.name,e.message,e.url,e.lineno,r,t)},_prepareFrames:function(e,t){var r=this,n=[];if(e.stack&&e.stack.length&&(re(e.stack,function(t,o){var i=r._normalizeFrame(o,e.url);i&&n.push(i)}),t&&t.trimHeadFrames))for(var o=0;o<t.trimHeadFrames&&o<n.length;o++)n[o].in_app=!1;return n=n.slice(0,this._globalOptions.stackTraceLimit)},_normalizeFrame:function(e,t){var r={filename:e.url,lineno:e.line,colno:e.column,function:e.func||"?"};return e.url||(r.filename=t),r.in_app=!(this._globalOptions.includePaths.test&&!this._globalOptions.includePaths.test(r.filename)||/(Raven|TraceKit)\./.test(r.function)||/raven\.(min\.)?js$/.test(r.filename)),r},_processException:function(e,t,r,n,o,i){var a,s=(e?e+": ":"")+(t||"");if((!this._globalOptions.ignoreErrors.test||!this._globalOptions.ignoreErrors.test(t)&&!this._globalOptions.ignoreErrors.test(s))&&(o&&o.length?(r=o[0].filename||r,o.reverse(),a={frames:o}):r&&(a={frames:[{filename:r,lineno:n,in_app:!0}]}),(!this._globalOptions.ignoreUrls.test||!this._globalOptions.ignoreUrls.test(r))&&(!this._globalOptions.whitelistUrls.test||this._globalOptions.whitelistUrls.test(r)))){var c=ne({exception:{values:[{type:e,value:t,stacktrace:a}]},culprit:r},i);this._send(c)}},_trimPacket:function(e){var t=this._globalOptions.maxMessageLength;if(e.message&&(e.message=oe(e.message,t)),e.exception){var r=e.exception.values[0];r.value=oe(r.value,t)}var n=e.request;return n&&(n.url&&(n.url=oe(n.url,this._globalOptions.maxUrlLength)),n.Referer&&(n.Referer=oe(n.Referer,this._globalOptions.maxUrlLength))),e.breadcrumbs&&e.breadcrumbs.values&&this._trimBreadcrumbs(e.breadcrumbs),e},_trimBreadcrumbs:function(e){for(var t,r,n,o=["to","from","url"],i=0;i<e.values.length;++i)if((r=e.values[i]).hasOwnProperty("data")&&J(r.data)&&!ie(r.data)){n=ne({},r.data);for(var a=0;a<o.length;++a)t=o[a],n.hasOwnProperty(t)&&n[t]&&(n[t]=oe(n[t],this._globalOptions.maxUrlLength));e.values[i].data=n}},_getHttpData:function(){if(this._hasNavigator||this._hasDocument){var e={};return this._hasNavigator&&Oe.userAgent&&(e.headers={"User-Agent":navigator.userAgent}),xe.location&&xe.location.href&&(e.url=xe.location.href),this._hasDocument&&Se.referrer&&(e.headers||(e.headers={}),e.headers.Referer=Se.referrer),e}},_resetBackoff:function(){this._backoffDuration=0,this._backoffStart=null},_shouldBackoff:function(){return this._backoffDuration&&ke()-this._backoffStart<this._backoffDuration},_isRepeatData:function(e){var t=this._lastData;return!(!t||e.message!==t.message||e.culprit!==t.culprit)&&(e.stacktrace||t.stacktrace?pe(e.stacktrace,t.stacktrace):!e.exception&&!t.exception||he(e.exception,t.exception))},_setBackoffState:function(e){if(!this._shouldBackoff()){var t=e.status;if(400===t||401===t||429===t){var r;try{r=ge()?e.headers.get("Retry-After"):e.getResponseHeader("Retry-After"),r=1e3*parseInt(r,10)}catch(e){}this._backoffDuration=r||(2*this._backoffDuration||1e3),this._backoffStart=ke()}}},_send:function(e){var t=this._globalOptions,r={project:this._globalProject,logger:t.logger,platform:"javascript"},n=this._getHttpData();n&&(r.request=n),e.trimHeadFrames&&delete e.trimHeadFrames,(e=ne(r,e)).tags=ne(ne({},this._globalContext.tags),e.tags),e.extra=ne(ne({},this._globalContext.extra),e.extra),e.extra["session:duration"]=ke()-this._startTime,this._breadcrumbs&&this._breadcrumbs.length>0&&(e.breadcrumbs={values:[].slice.call(this._breadcrumbs,0)}),this._globalContext.user&&(e.user=this._globalContext.user),t.environment&&(e.environment=t.environment),t.release&&(e.release=t.release),t.serverName&&(e.server_name=t.serverName),e=this._sanitizeData(e),Object.keys(e).forEach(function(t){(null==e[t]||""===e[t]||te(e[t]))&&delete e[t]}),Z(t.dataCallback)&&(e=t.dataCallback(e)||e),e&&!te(e)&&(Z(t.shouldSendCallback)&&!t.shouldSendCallback(e)||(this._shouldBackoff()?this._logDebug("warn","Raven dropped error due to backoff: ",e):"number"==typeof t.sampleRate?Math.random()<t.sampleRate&&this._sendProcessedPayload(e):this._sendProcessedPayload(e)))},_sanitizeData:function(e){return be(e,this._globalOptions.sanitizeKeys)},_getUuid:function(){return le()},_sendProcessedPayload:function(e,t){var r=this,n=this._globalOptions;if(this.isSetup())if(e=this._trimPacket(e),this._globalOptions.allowDuplicates||!this._isRepeatData(e)){this._lastEventId=e.event_id||(e.event_id=this._getUuid()),this._lastData=e,this._logDebug("debug","Raven about to send:",e);var o={sentry_version:"7",sentry_client:"raven-js/"+this.VERSION,sentry_key:this._globalKey};this._globalSecret&&(o.sentry_secret=this._globalSecret);var i=e.exception&&e.exception.values[0];this._globalOptions.autoBreadcrumbs&&this._globalOptions.autoBreadcrumbs.sentry&&this.captureBreadcrumb({category:"sentry",message:i?(i.type?i.type+": ":"")+i.value:e.message,event_id:e.event_id,level:e.level||"error"});var a=this._globalEndpoint;(n.transport||this._makeRequest).call(this,{url:a,auth:o,data:e,options:n,onSuccess:function(){r._resetBackoff(),r._triggerEvent("success",{data:e,src:a}),t&&t()},onError:function(n){r._logDebug("error","Raven transport failed to send: ",n),n.request&&r._setBackoffState(n.request),r._triggerEvent("failure",{data:e,src:a}),n=n||new Error("Raven send failed (no additional details provided)"),t&&t(n)}})}else this._logDebug("warn","Raven dropped repeat event: ",e)},_makeRequest:function(e){var t=e.url+"?"+ce(e.auth),n=null,o={};if(e.options.headers&&(n=this._evaluateHash(e.options.headers)),e.options.fetchParameters&&(o=this._evaluateHash(e.options.fetchParameters)),ge()){o.body=r(e.data);var i=ne({},this._fetchDefaults),a=ne(i,o);return n&&(a.headers=n),xe.fetch(t,a).then(function(t){if(t.ok)e.onSuccess&&e.onSuccess();else{var r=new Error("Sentry error code: "+t.status);r.request=t,e.onError&&e.onError(r)}}).catch(function(){e.onError&&e.onError(new Error("Sentry error code: network unavailable"))})}var s=xe.XMLHttpRequest&&new xe.XMLHttpRequest;s&&(("withCredentials"in s||"undefined"!=typeof XDomainRequest)&&("withCredentials"in s?s.onreadystatechange=function(){if(4===s.readyState)if(200===s.status)e.onSuccess&&e.onSuccess();else if(e.onError){var t=new Error("Sentry error code: "+s.status);t.request=s,e.onError(t)}}:(s=new XDomainRequest,t=t.replace(/^https?:/,""),e.onSuccess&&(s.onload=e.onSuccess),e.onError&&(s.onerror=function(){var t=new Error("Sentry error code: XDomainRequest");t.request=s,e.onError(t)})),s.open("POST",t),n&&re(n,function(e,t){s.setRequestHeader(e,t)}),s.send(r(e.data))))},_evaluateHash:function(e){var t={};for(var r in e)if(e.hasOwnProperty(r)){var n=e[r];t[r]="function"==typeof n?n():n}return t},_logDebug:function(e){this._originalConsoleMethods[e]&&(this.debug||this._globalOptions.debug)&&Function.prototype.apply.call(this._originalConsoleMethods[e],this._originalConsole,[].slice.call(arguments,1))},_mergeContext:function(e,t){Y(t)?delete this._globalContext[e]:this._globalContext[e]=ne(this._globalContext[e]||{},t)}},Re.prototype.setUser=Re.prototype.setUserContext,Re.prototype.setReleaseContext=Re.prototype.setRelease;var je=Re,Te="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},Fe=Te.Raven,Ae=new je;Ae.noConflict=function(){return Te.Raven=Fe,Ae},Ae.afterLoad();var Be,De,He,Le,Pe,Ie,Ue,Ne=Ae,Me=je;Ne.Client=Me,(Ue="plyr.io"===window.location.host)&&Ne.config("https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555").install(),document.addEventListener("DOMContentLoaded",function(){Ne.context(function(){window.shr&&window.shr.setup({count:{classname:"button__count"}}),document.addEventListener("focusout",function(e){e.target.classList.remove("tab-focus")}),document.addEventListener("keydown",function(e){9===e.keyCode&&setTimeout(function(){document.activeElement.classList.add("tab-focus")},0)});var e=new Plyr("#player",{debug:!0,title:"View From A Blue Moon",iconUrl:"../dist/plyr.svg",keyboard:{global:!0},tooltips:{controls:!0},captions:{active:!0},keys:{google:"AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c"},ads:{enabled:!0,publisherId:"918848828995742"}});window.player=e;var t=document.querySelectorAll("[data-source]"),r={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},n=window.location.hash.replace("#",""),o=window.history&&window.history.pushState;function i(e,t,r){e&&e.classList[r?"add":"remove"](t)}function a(o,a){if(o in r&&(a||o!==n)&&(n.length||o!==r.video)){switch(o){case r.video:e.source={type:"video",title:"View From A Blue Moon",sources:[{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4",type:"video/mp4",size:576},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4",type:"video/mp4",size:720},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4",type:"video/mp4",size:1080},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4",type:"video/mp4",size:1440}],poster:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt",default:!0},{kind:"captions",label:"French",srclang:"fr",src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt"}]};break;case r.audio:e.source={type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",sources:[{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]};break;case r.youtube:e.source={type:"video",sources:[{src:"https://youtube.com/watch?v=bTqVqk7FSmY",provider:"youtube"}]};break;case r.vimeo:e.source={type:"video",sources:[{src:"https://vimeo.com/76979871",provider:"vimeo"}]}}n=o,Array.from(t).forEach(function(e){return i(e.parentElement,"active",!1)}),i(document.querySelector('[data-source="'+o+'"]'),"active",!0),Array.from(document.querySelectorAll(".plyr__cite")).forEach(function(e){e.setAttribute("hidden","")}),document.querySelector(".plyr__cite--"+o).removeAttribute("hidden")}}if(Array.from(t).forEach(function(e){e.addEventListener("click",function(){var t=e.getAttribute("data-source");a(t),o&&window.history.pushState({type:t},"","#"+t)})}),window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&a(e.state.type)}),o){var s=!n.length;s&&(n=r.video),n in r&&window.history.replaceState({type:n},"",s?"":"#"+n),n!==r.video&&a(n,!0)}})}),Ue&&(Be=window,De=document,He="script",Le="ga",Be.GoogleAnalyticsObject=Le,Be.ga=Be.ga||function(){(Be.ga.q=Be.ga.q||[]).push(arguments)},Be.ga.l=1*new Date,Pe=De.createElement(He),Ie=De.getElementsByTagName(He)[0],Pe.async=1,Pe.src="https://www.google-analytics.com/analytics.js",Ie.parentNode.insertBefore(Pe,Ie),window.ga("create","UA-40881672-11","auto"),window.ga("send","pageview"))}(); +"object"==typeof navigator&&function(){"use strict";var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e,t){return e(t={exports:{}},t.exports),t.exports}var n=t(function(e,t){function n(e,t){for(var n=0;n<e.length;++n)if(e[n]===t)return n;return-1}function i(e,t){var i=[],r=[];return null==t&&(t=function(e,t){return i[0]===t?"[Circular ~]":"[Circular ~."+r.slice(0,n(i,t)).join(".")+"]"}),function(a,s){if(i.length>0){var o=n(i,this);~o?i.splice(o+1):i.push(this),~o?r.splice(o,1/0,a):r.push(a),~n(i,s)&&(s=t.call(this,a,s))}else i.push(s);return null==e?s instanceof Error?function(e){var t={stack:e.stack,message:e.message,name:e.name};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t}(s):s:e.call(this,a,s)}}(e.exports=function(e,t,n,r){return JSON.stringify(e,i(t,r),n)}).getSerialize=i}),i=(n.getSerialize,"undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{});function r(e){return void 0===e}function a(e){return"[object Object]"===Object.prototype.toString.call(e)}function s(e){return"[object String]"===Object.prototype.toString.call(e)}function o(e){return"[object Array]"===Object.prototype.toString.call(e)}function l(){if(!("fetch"in i))return!1;try{return new Headers,new Request(""),new Response,!0}catch(e){return!1}}function c(e,t){var n,i;if(r(e.length))for(n in e)d(e,n)&&t.call(null,n,e[n]);else if(i=e.length)for(n=0;n<i;n++)t.call(null,n,e[n])}function u(e,t){if("number"!=typeof t)throw new Error("2nd argument to `truncate` function should be a number");return"string"!=typeof e||0===t?e:e.length<=t?e:e.substr(0,t)+"…"}function d(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function h(e){for(var t,n=[],i=0,r=e.length;i<r;i++)s(t=e[i])?n.push(t.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")):t&&t.source&&n.push(t.source);return new RegExp(n.join("|"),"i")}function p(e){var t,n,i,r,a,o=[];if(!e||!e.tagName)return"";if(o.push(e.tagName.toLowerCase()),e.id&&o.push("#"+e.id),(t=e.className)&&s(t))for(n=t.split(/\s+/),a=0;a<n.length;a++)o.push("."+n[a]);var l=["type","name","title","alt"];for(a=0;a<l.length;a++)i=l[a],(r=e.getAttribute(i))&&o.push("["+i+'="'+r+'"]');return o.join("")}function m(e,t){return!!(!!e^!!t)}function f(e,t){if(m(e,t))return!1;var n,i,r=e.frames,a=t.frames;if(void 0===r||void 0===a)return!1;if(r.length!==a.length)return!1;for(var s=0;s<r.length;s++)if(n=r[s],i=a[s],n.filename!==i.filename||n.lineno!==i.lineno||n.colno!==i.colno||n.function!==i.function)return!1;return!0}var g=3,v=51200,y=40;function b(e){return function(e){return~-encodeURI(e).split(/%..|./).length}(JSON.stringify(e))}function k(e){if("string"==typeof e){return u(e,40)}if("number"==typeof e||"boolean"==typeof e||void 0===e)return e;var t=Object.prototype.toString.call(e);return"[object Object]"===t?"[Object]":"[object Array]"===t?"[Array]":"[object Function]"===t?e.name?"[Function: "+e.name+"]":"[Function]":e}var w={isObject:function(e){return"object"==typeof e&&null!==e},isError:function(e){switch(Object.prototype.toString.call(e)){case"[object Error]":case"[object Exception]":case"[object DOMException]":return!0;default:return e instanceof Error}},isErrorEvent:function(e){return"[object ErrorEvent]"===Object.prototype.toString.call(e)},isDOMError:function(e){return"[object DOMError]"===Object.prototype.toString.call(e)},isDOMException:function(e){return"[object DOMException]"===Object.prototype.toString.call(e)},isUndefined:r,isFunction:function(e){return"function"==typeof e},isPlainObject:a,isString:s,isArray:o,isEmptyObject:function(e){if(!a(e))return!1;for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},supportsErrorEvent:function(){try{return new ErrorEvent(""),!0}catch(e){return!1}},supportsDOMError:function(){try{return new DOMError(""),!0}catch(e){return!1}},supportsDOMException:function(){try{return new DOMException(""),!0}catch(e){return!1}},supportsFetch:l,supportsReferrerPolicy:function(){if(!l())return!1;try{return new Request("pickleRick",{referrerPolicy:"origin"}),!0}catch(e){return!1}},supportsPromiseRejectionEvent:function(){return"function"==typeof PromiseRejectionEvent},wrappedCallback:function(e){return function(t,n){var i=e(t)||t;return n&&n(i)||i}},each:c,objectMerge:function(e,t){return t?(c(t,function(t,n){e[t]=n}),e):e},truncate:u,objectFrozen:function(e){return!!Object.isFrozen&&Object.isFrozen(e)},hasKey:d,joinRegExp:h,urlencode:function(e){var t=[];return c(e,function(e,n){t.push(encodeURIComponent(e)+"="+encodeURIComponent(n))}),t.join("&")},uuid4:function(){var e=i.crypto||i.msCrypto;if(!r(e)&&e.getRandomValues){var t=new Uint16Array(8);e.getRandomValues(t),t[3]=4095&t[3]|16384,t[4]=16383&t[4]|32768;var n=function(e){for(var t=e.toString(16);t.length<4;)t="0"+t;return t};return n(t[0])+n(t[1])+n(t[2])+n(t[3])+n(t[4])+n(t[5])+n(t[6])+n(t[7])}return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})},htmlTreeAsString:function(e){for(var t,n=[],i=0,r=0,a=" > ".length;e&&i++<5&&!("html"===(t=p(e))||i>1&&r+n.length*a+t.length>=80);)n.push(t),r+=t.length,e=e.parentNode;return n.reverse().join(" > ")},htmlElementAsString:p,isSameException:function(e,t){return!m(e,t)&&(e=e.values[0],t=t.values[0],e.type===t.type&&e.value===t.value&&(n=e.stacktrace,i=t.stacktrace,(!r(n)||!r(i))&&f(e.stacktrace,t.stacktrace)));var n,i},isSameStacktrace:f,parseUrl:function(e){if("string"!=typeof e)return{};var t=e.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/),n=t[6]||"",i=t[8]||"";return{protocol:t[2],host:t[4],path:t[5],relative:t[5]+n+i}},fill:function(e,t,n,i){if(null!=e){var r=e[t];e[t]=n(r),e[t].__raven__=!0,e[t].__orig__=r,i&&i.push([e,t,r])}},safeJoin:function(e,t){if(!o(e))return"";for(var n=[],i=0;i<e.length;i++)try{n.push(String(e[i]))}catch(e){n.push("[value cannot be serialized]")}return n.join(t)},serializeException:function e(t,i,r){if(!a(t))return t;r="number"!=typeof(i="number"!=typeof i?g:i)?v:r;var s=function e(t,n){return 0===n?k(t):a(t)?Object.keys(t).reduce(function(i,r){return i[r]=e(t[r],n-1),i},{}):Array.isArray(t)?t.map(function(t){return e(t,n-1)}):k(t)}(t,i);return b(n(s))>r?e(t,i-1):s},serializeKeysForMessage:function(e,t){if("number"==typeof e||"string"==typeof e)return e.toString();if(!Array.isArray(e))return"";if(0===(e=e.filter(function(e){return"string"==typeof e})).length)return"[object has no keys]";if(t="number"!=typeof t?y:t,e[0].length>=t)return e[0];for(var n=e.length;n>0;n--){var i=e.slice(0,n).join(", ");if(!(i.length>t))return n===e.length?i:i+"…"}return""},sanitize:function(e,t){if(!o(t)||o(t)&&0===t.length)return e;var i,r=h(t),s="********";try{i=JSON.parse(n(e))}catch(t){return e}return function e(t){return o(t)?t.map(function(t){return e(t)}):a(t)?Object.keys(t).reduce(function(n,i){return r.test(i)?n[i]=s:n[i]=e(t[i]),n},{}):t}(i)}},_={collectWindowErrors:!0,debug:!1},T="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},E=[].slice,C="?",S=/^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;function x(){return"undefined"==typeof document||null==document.location?"":document.location.href}_.report=function(){var e,t,n=[],i=null,r=null,a=null;function s(e,t){var i=null;if(!t||_.collectWindowErrors){for(var r in n)if(n.hasOwnProperty(r))try{n[r].apply(null,[e].concat(E.call(arguments,2)))}catch(e){i=e}if(i)throw i}}function o(t,n,i,r,o){var c=w.isErrorEvent(o)?o.error:o,u=w.isErrorEvent(t)?t.message:t;if(a)_.computeStackTrace.augmentStackTraceWithInitialElement(a,n,i,u),l();else if(c&&w.isError(c))s(_.computeStackTrace(c),!0);else{var d,h={url:n,line:i,column:r},p=void 0;if("[object String]"==={}.toString.call(u))(d=u.match(S))&&(p=d[1],u=d[2]);h.func=C,s({name:p,message:u,url:x(),stack:[h]},!0)}return!!e&&e.apply(this,arguments)}function l(){var e=a,t=i;i=null,a=null,r=null,s.apply(null,[e,!1].concat(t))}function c(e,t){var n=E.call(arguments,1);if(a){if(r===e)return;l()}var s=_.computeStackTrace(e);if(a=s,r=e,i=n,setTimeout(function(){r===e&&l()},s.incomplete?2e3:0),!1!==t)throw e}return c.subscribe=function(i){t||(e=T.onerror,T.onerror=o,t=!0),n.push(i)},c.unsubscribe=function(e){for(var t=n.length-1;t>=0;--t)n[t]===e&&n.splice(t,1)},c.uninstall=function(){t&&(T.onerror=e,t=!1,e=void 0),n=[]},c}(),_.computeStackTrace=function(){function e(e){if(void 0!==e.stack&&e.stack){for(var t,n,i,r=/^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,a=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,s=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,o=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,l=/\((\S*)(?::(\d+))(?::(\d+))\)/,c=e.stack.split("\n"),u=[],d=(/^(.*) is undefined$/.exec(e.message),0),h=c.length;d<h;++d){if(n=r.exec(c[d])){var p=n[2]&&0===n[2].indexOf("native");n[2]&&0===n[2].indexOf("eval")&&(t=l.exec(n[2]))&&(n[2]=t[1],n[3]=t[2],n[4]=t[3]),i={url:p?null:n[2],func:n[1]||C,args:p?[n[2]]:[],line:n[3]?+n[3]:null,column:n[4]?+n[4]:null}}else if(n=a.exec(c[d]))i={url:n[2],func:n[1]||C,args:[],line:+n[3],column:n[4]?+n[4]:null};else{if(!(n=s.exec(c[d])))continue;n[3]&&n[3].indexOf(" > eval")>-1&&(t=o.exec(n[3]))?(n[3]=t[1],n[4]=t[2],n[5]=null):0!==d||n[5]||void 0===e.columnNumber||(u[0].column=e.columnNumber+1),i={url:n[3],func:n[1]||C,args:n[2]?n[2].split(","):[],line:n[4]?+n[4]:null,column:n[5]?+n[5]:null}}if(!i.func&&i.line&&(i.func=C),i.url&&"blob:"===i.url.substr(0,5)){var m=new XMLHttpRequest;if(m.open("GET",i.url,!1),m.send(null),200===m.status){var f=m.responseText||"",g=(f=f.slice(-300)).match(/\/\/# sourceMappingURL=(.*)$/);if(g){var v=g[1];"~"===v.charAt(0)&&(v=("undefined"==typeof document||null==document.location?"":document.location.origin?document.location.origin:document.location.protocol+"//"+document.location.hostname+(document.location.port?":"+document.location.port:""))+v.slice(1)),i.url=v.slice(0,-4)}}}u.push(i)}return u.length?{name:e.name,message:e.message,url:x(),stack:u}:null}}function t(e,t,n,i){var r={url:t,line:n};if(r.url&&r.line){if(e.incomplete=!1,r.func||(r.func=C),e.stack.length>0&&e.stack[0].url===r.url){if(e.stack[0].line===r.line)return!1;if(!e.stack[0].line&&e.stack[0].func===r.func)return e.stack[0].line=r.line,!1}return e.stack.unshift(r),e.partial=!0,!0}return e.incomplete=!0,!1}function n(e,r){for(var a,s,o=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],c={},u=!1,d=n.caller;d&&!u;d=d.caller)if(d!==i&&d!==_.report){if(s={url:null,func:C,line:null,column:null},d.name?s.func=d.name:(a=o.exec(d.toString()))&&(s.func=a[1]),void 0===s.func)try{s.func=a.input.substring(0,a.input.indexOf("{"))}catch(e){}c[""+d]?u=!0:c[""+d]=!0,l.push(s)}r&&l.splice(0,r);var h={name:e.name,message:e.message,url:x(),stack:l};return t(h,e.sourceURL||e.fileName,e.line||e.lineNumber,e.message||e.description),h}function i(t,i){var r=null;i=null==i?0:+i;try{if(r=e(t))return r}catch(e){if(_.debug)throw e}try{if(r=n(t,i+1))return r}catch(e){if(_.debug)throw e}return{name:t.name,message:t.message,url:x()}}return i.augmentStackTraceWithInitialElement=t,i.computeStackTraceFromStackProp=e,i}();var A=_;function P(e,t){var n=(65535&e)+(65535&t);return(e>>16)+(t>>16)+(n>>16)<<16|65535&n}function O(e,t,n,i,r,a){return P((s=P(P(t,e),P(i,a)))<<(o=r)|s>>>32-o,n);var s,o}function M(e,t,n,i,r,a,s){return O(t&n|~t&i,e,t,r,a,s)}function N(e,t,n,i,r,a,s){return O(t&i|n&~i,e,t,r,a,s)}function L(e,t,n,i,r,a,s){return O(t^n^i,e,t,r,a,s)}function I(e,t,n,i,r,a,s){return O(n^(t|~i),e,t,r,a,s)}function j(e,t){var n,i,r,a,s;e[t>>5]|=128<<t%32,e[14+(t+64>>>9<<4)]=t;var o=1732584193,l=-271733879,c=-1732584194,u=271733878;for(n=0;n<e.length;n+=16)i=o,r=l,a=c,s=u,o=M(o,l,c,u,e[n],7,-680876936),u=M(u,o,l,c,e[n+1],12,-389564586),c=M(c,u,o,l,e[n+2],17,606105819),l=M(l,c,u,o,e[n+3],22,-1044525330),o=M(o,l,c,u,e[n+4],7,-176418897),u=M(u,o,l,c,e[n+5],12,1200080426),c=M(c,u,o,l,e[n+6],17,-1473231341),l=M(l,c,u,o,e[n+7],22,-45705983),o=M(o,l,c,u,e[n+8],7,1770035416),u=M(u,o,l,c,e[n+9],12,-1958414417),c=M(c,u,o,l,e[n+10],17,-42063),l=M(l,c,u,o,e[n+11],22,-1990404162),o=M(o,l,c,u,e[n+12],7,1804603682),u=M(u,o,l,c,e[n+13],12,-40341101),c=M(c,u,o,l,e[n+14],17,-1502002290),o=N(o,l=M(l,c,u,o,e[n+15],22,1236535329),c,u,e[n+1],5,-165796510),u=N(u,o,l,c,e[n+6],9,-1069501632),c=N(c,u,o,l,e[n+11],14,643717713),l=N(l,c,u,o,e[n],20,-373897302),o=N(o,l,c,u,e[n+5],5,-701558691),u=N(u,o,l,c,e[n+10],9,38016083),c=N(c,u,o,l,e[n+15],14,-660478335),l=N(l,c,u,o,e[n+4],20,-405537848),o=N(o,l,c,u,e[n+9],5,568446438),u=N(u,o,l,c,e[n+14],9,-1019803690),c=N(c,u,o,l,e[n+3],14,-187363961),l=N(l,c,u,o,e[n+8],20,1163531501),o=N(o,l,c,u,e[n+13],5,-1444681467),u=N(u,o,l,c,e[n+2],9,-51403784),c=N(c,u,o,l,e[n+7],14,1735328473),o=L(o,l=N(l,c,u,o,e[n+12],20,-1926607734),c,u,e[n+5],4,-378558),u=L(u,o,l,c,e[n+8],11,-2022574463),c=L(c,u,o,l,e[n+11],16,1839030562),l=L(l,c,u,o,e[n+14],23,-35309556),o=L(o,l,c,u,e[n+1],4,-1530992060),u=L(u,o,l,c,e[n+4],11,1272893353),c=L(c,u,o,l,e[n+7],16,-155497632),l=L(l,c,u,o,e[n+10],23,-1094730640),o=L(o,l,c,u,e[n+13],4,681279174),u=L(u,o,l,c,e[n],11,-358537222),c=L(c,u,o,l,e[n+3],16,-722521979),l=L(l,c,u,o,e[n+6],23,76029189),o=L(o,l,c,u,e[n+9],4,-640364487),u=L(u,o,l,c,e[n+12],11,-421815835),c=L(c,u,o,l,e[n+15],16,530742520),o=I(o,l=L(l,c,u,o,e[n+2],23,-995338651),c,u,e[n],6,-198630844),u=I(u,o,l,c,e[n+7],10,1126891415),c=I(c,u,o,l,e[n+14],15,-1416354905),l=I(l,c,u,o,e[n+5],21,-57434055),o=I(o,l,c,u,e[n+12],6,1700485571),u=I(u,o,l,c,e[n+3],10,-1894986606),c=I(c,u,o,l,e[n+10],15,-1051523),l=I(l,c,u,o,e[n+1],21,-2054922799),o=I(o,l,c,u,e[n+8],6,1873313359),u=I(u,o,l,c,e[n+15],10,-30611744),c=I(c,u,o,l,e[n+6],15,-1560198380),l=I(l,c,u,o,e[n+13],21,1309151649),o=I(o,l,c,u,e[n+4],6,-145523070),u=I(u,o,l,c,e[n+11],10,-1120210379),c=I(c,u,o,l,e[n+2],15,718787259),l=I(l,c,u,o,e[n+9],21,-343485551),o=P(o,i),l=P(l,r),c=P(c,a),u=P(u,s);return[o,l,c,u]}function R(e){var t,n="",i=32*e.length;for(t=0;t<i;t+=8)n+=String.fromCharCode(e[t>>5]>>>t%32&255);return n}function D(e){var t,n=[];for(n[(e.length>>2)-1]=void 0,t=0;t<n.length;t+=1)n[t]=0;var i=8*e.length;for(t=0;t<i;t+=8)n[t>>5]|=(255&e.charCodeAt(t/8))<<t%32;return n}function F(e){var t,n,i="";for(n=0;n<e.length;n+=1)t=e.charCodeAt(n),i+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return i}function H(e){return unescape(encodeURIComponent(e))}function B(e){return function(e){return R(j(D(e),8*e.length))}(H(e))}function q(e,t){return function(e,t){var n,i,r=D(e),a=[],s=[];for(a[15]=s[15]=void 0,r.length>16&&(r=j(r,8*e.length)),n=0;n<16;n+=1)a[n]=909522486^r[n],s[n]=1549556828^r[n];return i=j(a.concat(D(t)),512+8*t.length),R(j(s.concat(i),640))}(H(e),H(t))}var U=function(e,t,n){return t?n?q(t,e):F(q(t,e)):n?B(e):F(B(e))};function V(e){this.name="RavenConfigError",this.message=e}V.prototype=new Error,V.prototype.constructor=V;var z=V,W=function(e,t,n){var i=e[t],r=e;if(t in e){var a="warn"===t?"warning":t;e[t]=function(){var e=[].slice.call(arguments),s=w.safeJoin(e," "),o={level:a,logger:"console",extra:{arguments:e}};"assert"===t?!1===e[0]&&(s="Assertion failed: "+(w.safeJoin(e.slice(1)," ")||"console.assert"),o.extra.arguments=e.slice(1),n&&n(s,o)):n&&n(s,o),i&&Function.prototype.apply.call(i,r,e)}}},K=w.isErrorEvent,X=w.isDOMError,Y=w.isDOMException,J=w.isError,$=w.isObject,G=w.isPlainObject,Q=w.isUndefined,Z=w.isFunction,ee=w.isString,te=w.isArray,ne=w.isEmptyObject,ie=w.each,re=w.objectMerge,ae=w.truncate,se=w.objectFrozen,oe=w.hasKey,le=w.joinRegExp,ce=w.urlencode,ue=w.uuid4,de=w.htmlTreeAsString,he=w.isSameException,pe=w.isSameStacktrace,me=w.parseUrl,fe=w.fill,ge=w.supportsFetch,ve=w.supportsReferrerPolicy,ye=w.serializeKeysForMessage,be=w.serializeException,ke=w.sanitize,we=W,_e="source protocol user pass host port path".split(" "),Te=/^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/;function Ee(){return+new Date}var Ce="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},Se=Ce.document,xe=Ce.navigator;function Ae(e,t){return Z(t)?function(n){return t(n,e)}:t}function Pe(){for(var e in this._hasJSON=!("object"!=typeof JSON||!JSON.stringify),this._hasDocument=!Q(Se),this._hasNavigator=!Q(xe),this._lastCapturedException=null,this._lastData=null,this._lastEventId=null,this._globalServer=null,this._globalKey=null,this._globalProject=null,this._globalContext={},this._globalOptions={release:Ce.SENTRY_RELEASE&&Ce.SENTRY_RELEASE.id,logger:"javascript",ignoreErrors:[],ignoreUrls:[],whitelistUrls:[],includePaths:[],headers:null,collectWindowErrors:!0,captureUnhandledRejections:!0,maxMessageLength:0,maxUrlLength:250,stackTraceLimit:50,autoBreadcrumbs:!0,instrument:!0,sampleRate:1,sanitizeKeys:[]},this._fetchDefaults={method:"POST",referrerPolicy:ve()?"origin":""},this._ignoreOnError=0,this._isRavenInstalled=!1,this._originalErrorStackTraceLimit=Error.stackTraceLimit,this._originalConsole=Ce.console||{},this._originalConsoleMethods={},this._plugins=[],this._startTime=Ee(),this._wrappedBuiltIns=[],this._breadcrumbs=[],this._lastCapturedEvent=null,this._keypressTimeout,this._location=Ce.location,this._lastHref=this._location&&this._location.href,this._resetBackoff(),this._originalConsole)this._originalConsoleMethods[e]=this._originalConsole[e]}Pe.prototype={VERSION:"3.27.0",debug:!1,TraceKit:A,config:function(e,t){var n=this;if(n._globalServer)return this._logDebug("error","Error: Raven has already been configured"),n;if(!e)return n;var i=n._globalOptions;t&&ie(t,function(e,t){"tags"===e||"extra"===e||"user"===e?n._globalContext[e]=t:i[e]=t}),n.setDSN(e),i.ignoreErrors.push(/^Script error\.?$/),i.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/),i.ignoreErrors=le(i.ignoreErrors),i.ignoreUrls=!!i.ignoreUrls.length&&le(i.ignoreUrls),i.whitelistUrls=!!i.whitelistUrls.length&&le(i.whitelistUrls),i.includePaths=le(i.includePaths),i.maxBreadcrumbs=Math.max(0,Math.min(i.maxBreadcrumbs||100,100));var r={xhr:!0,console:!0,dom:!0,location:!0,sentry:!0},a=i.autoBreadcrumbs;"[object Object]"==={}.toString.call(a)?a=re(r,a):!1!==a&&(a=r),i.autoBreadcrumbs=a;var s={tryCatch:!0},o=i.instrument;return"[object Object]"==={}.toString.call(o)?o=re(s,o):!1!==o&&(o=s),i.instrument=o,A.collectWindowErrors=!!i.collectWindowErrors,n},install:function(){var e=this;return e.isSetup()&&!e._isRavenInstalled&&(A.report.subscribe(function(){e._handleOnErrorStackInfo.apply(e,arguments)}),e._globalOptions.captureUnhandledRejections&&e._attachPromiseRejectionHandler(),e._patchFunctionToString(),e._globalOptions.instrument&&e._globalOptions.instrument.tryCatch&&e._instrumentTryCatch(),e._globalOptions.autoBreadcrumbs&&e._instrumentBreadcrumbs(),e._drainPlugins(),e._isRavenInstalled=!0),Error.stackTraceLimit=e._globalOptions.stackTraceLimit,this},setDSN:function(e){var t=this._parseDSN(e),n=t.path.lastIndexOf("/"),i=t.path.substr(1,n);this._dsn=e,this._globalKey=t.user,this._globalSecret=t.pass&&t.pass.substr(1),this._globalProject=t.path.substr(n+1),this._globalServer=this._getGlobalServer(t),this._globalEndpoint=this._globalServer+"/"+i+"api/"+this._globalProject+"/store/",this._resetBackoff()},context:function(e,t,n){return Z(e)&&(n=t||[],t=e,e={}),this.wrap(e,t).apply(this,n)},wrap:function(e,t,n){var i=this;if(Q(t)&&!Z(e))return e;if(Z(e)&&(t=e,e=void 0),!Z(t))return t;try{if(t.__raven__)return t;if(t.__raven_wrapper__)return t.__raven_wrapper__}catch(e){return t}function r(){var r=[],a=arguments.length,s=!e||e&&!1!==e.deep;for(n&&Z(n)&&n.apply(this,arguments);a--;)r[a]=s?i.wrap(e,arguments[a]):arguments[a];try{return t.apply(this,r)}catch(t){throw i._ignoreNextOnError(),i.captureException(t,e),t}}for(var a in t)oe(t,a)&&(r[a]=t[a]);return r.prototype=t.prototype,t.__raven_wrapper__=r,r.__raven__=!0,r.__orig__=t,r},uninstall:function(){return A.report.uninstall(),this._detachPromiseRejectionHandler(),this._unpatchFunctionToString(),this._restoreBuiltIns(),this._restoreConsole(),Error.stackTraceLimit=this._originalErrorStackTraceLimit,this._isRavenInstalled=!1,this},_promiseRejectionHandler:function(e){this._logDebug("debug","Raven caught unhandled promise rejection:",e),this.captureException(e.reason,{mechanism:{type:"onunhandledrejection",handled:!1}})},_attachPromiseRejectionHandler:function(){return this._promiseRejectionHandler=this._promiseRejectionHandler.bind(this),Ce.addEventListener&&Ce.addEventListener("unhandledrejection",this._promiseRejectionHandler),this},_detachPromiseRejectionHandler:function(){return Ce.removeEventListener&&Ce.removeEventListener("unhandledrejection",this._promiseRejectionHandler),this},captureException:function(e,t){if(t=re({trimHeadFrames:0},t||{}),K(e)&&e.error)e=e.error;else{if(X(e)||Y(e)){var n=e.name||(X(e)?"DOMError":"DOMException"),i=e.message?n+": "+e.message:n;return this.captureMessage(i,re(t,{stacktrace:!0,trimHeadFrames:t.trimHeadFrames+1}))}if(J(e))e=e;else{if(!G(e))return this.captureMessage(e,re(t,{stacktrace:!0,trimHeadFrames:t.trimHeadFrames+1}));t=this._getCaptureExceptionOptionsFromPlainObject(t,e),e=new Error(t.message)}}this._lastCapturedException=e;try{var r=A.computeStackTrace(e);this._handleStackInfo(r,t)}catch(t){if(e!==t)throw t}return this},_getCaptureExceptionOptionsFromPlainObject:function(e,t){var n=Object.keys(t).sort(),i=re(e,{message:"Non-Error exception captured with keys: "+ye(n),fingerprint:[U(n)],extra:e.extra||{}});return i.extra.__serialized__=be(t),i},captureMessage:function(e,t){if(!this._globalOptions.ignoreErrors.test||!this._globalOptions.ignoreErrors.test(e)){var n,i=re({message:e+=""},t=t||{});try{throw new Error(e)}catch(e){n=e}n.name=null;var r=A.computeStackTrace(n),a=te(r.stack)&&r.stack[1];a&&"Raven.captureException"===a.func&&(a=r.stack[2]);var s=a&&a.url||"";if((!this._globalOptions.ignoreUrls.test||!this._globalOptions.ignoreUrls.test(s))&&(!this._globalOptions.whitelistUrls.test||this._globalOptions.whitelistUrls.test(s))){if(this._globalOptions.stacktrace||t.stacktrace||""===i.message){i.fingerprint=null==i.fingerprint?e:i.fingerprint,(t=re({trimHeadFrames:0},t)).trimHeadFrames+=1;var o=this._prepareFrames(r,t);i.stacktrace={frames:o.reverse()}}return i.fingerprint&&(i.fingerprint=te(i.fingerprint)?i.fingerprint:[i.fingerprint]),this._send(i),this}}},captureBreadcrumb:function(e){var t=re({timestamp:Ee()/1e3},e);if(Z(this._globalOptions.breadcrumbCallback)){var n=this._globalOptions.breadcrumbCallback(t);if($(n)&&!ne(n))t=n;else if(!1===n)return this}return this._breadcrumbs.push(t),this._breadcrumbs.length>this._globalOptions.maxBreadcrumbs&&this._breadcrumbs.shift(),this},addPlugin:function(e){var t=[].slice.call(arguments,1);return this._plugins.push([e,t]),this._isRavenInstalled&&this._drainPlugins(),this},setUserContext:function(e){return this._globalContext.user=e,this},setExtraContext:function(e){return this._mergeContext("extra",e),this},setTagsContext:function(e){return this._mergeContext("tags",e),this},clearContext:function(){return this._globalContext={},this},getContext:function(){return JSON.parse(n(this._globalContext))},setEnvironment:function(e){return this._globalOptions.environment=e,this},setRelease:function(e){return this._globalOptions.release=e,this},setDataCallback:function(e){var t=this._globalOptions.dataCallback;return this._globalOptions.dataCallback=Ae(t,e),this},setBreadcrumbCallback:function(e){var t=this._globalOptions.breadcrumbCallback;return this._globalOptions.breadcrumbCallback=Ae(t,e),this},setShouldSendCallback:function(e){var t=this._globalOptions.shouldSendCallback;return this._globalOptions.shouldSendCallback=Ae(t,e),this},setTransport:function(e){return this._globalOptions.transport=e,this},lastException:function(){return this._lastCapturedException},lastEventId:function(){return this._lastEventId},isSetup:function(){return!!this._hasJSON&&(!!this._globalServer||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this._logDebug("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var e=Ce.RavenConfig;e&&this.config(e.dsn,e.config).install()},showReportDialog:function(e){if(Se){if(!(e=re({eventId:this.lastEventId(),dsn:this._dsn,user:this._globalContext.user||{}},e)).eventId)throw new z("Missing eventId");if(!e.dsn)throw new z("Missing DSN");var t=encodeURIComponent,n=[];for(var i in e)if("user"===i){var r=e.user;r.name&&n.push("name="+t(r.name)),r.email&&n.push("email="+t(r.email))}else n.push(t(i)+"="+t(e[i]));var a=this._getGlobalServer(this._parseDSN(e.dsn)),s=Se.createElement("script");s.async=!0,s.src=a+"/api/embed/error-page/?"+n.join("&"),(Se.head||Se.body).appendChild(s)}},_ignoreNextOnError:function(){var e=this;this._ignoreOnError+=1,setTimeout(function(){e._ignoreOnError-=1})},_triggerEvent:function(e,t){var n,i;if(this._hasDocument){for(i in t=t||{},e="raven"+e.substr(0,1).toUpperCase()+e.substr(1),Se.createEvent?(n=Se.createEvent("HTMLEvents")).initEvent(e,!0,!0):(n=Se.createEventObject()).eventType=e,t)oe(t,i)&&(n[i]=t[i]);if(Se.createEvent)Se.dispatchEvent(n);else try{Se.fireEvent("on"+n.eventType.toLowerCase(),n)}catch(e){}}},_breadcrumbEventHandler:function(e){var t=this;return function(n){if(t._keypressTimeout=null,t._lastCapturedEvent!==n){var i;t._lastCapturedEvent=n;try{i=de(n.target)}catch(e){i="<unknown>"}t.captureBreadcrumb({category:"ui."+e,message:i})}}},_keypressEventHandler:function(){var e=this;return function(t){var n;try{n=t.target}catch(e){return}var i=n&&n.tagName;if(i&&("INPUT"===i||"TEXTAREA"===i||n.isContentEditable)){var r=e._keypressTimeout;r||e._breadcrumbEventHandler("input")(t),clearTimeout(r),e._keypressTimeout=setTimeout(function(){e._keypressTimeout=null},1e3)}}},_captureUrlChange:function(e,t){var n=me(this._location.href),i=me(t),r=me(e);this._lastHref=t,n.protocol===i.protocol&&n.host===i.host&&(t=i.relative),n.protocol===r.protocol&&n.host===r.host&&(e=r.relative),this.captureBreadcrumb({category:"navigation",data:{to:t,from:e}})},_patchFunctionToString:function(){var e=this;e._originalFunctionToString=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.__raven__?e._originalFunctionToString.apply(this.__orig__,arguments):e._originalFunctionToString.apply(this,arguments)}},_unpatchFunctionToString:function(){this._originalFunctionToString&&(Function.prototype.toString=this._originalFunctionToString)},_instrumentTryCatch:function(){var e=this,t=e._wrappedBuiltIns;function n(t){return function(n,i){for(var r=new Array(arguments.length),a=0;a<r.length;++a)r[a]=arguments[a];var s=r[0];return Z(s)&&(r[0]=e.wrap({mechanism:{type:"instrument",data:{function:t.name||"<anonymous>"}}},s)),t.apply?t.apply(this,r):t(r[0],r[1])}}var i=this._globalOptions.autoBreadcrumbs;function r(n){var r=Ce[n]&&Ce[n].prototype;r&&r.hasOwnProperty&&r.hasOwnProperty("addEventListener")&&(fe(r,"addEventListener",function(t){return function(r,a,s,o){try{a&&a.handleEvent&&(a.handleEvent=e.wrap({mechanism:{type:"instrument",data:{target:n,function:"handleEvent",handler:a&&a.name||"<anonymous>"}}},a.handleEvent))}catch(e){}var l,c,u;return i&&i.dom&&("EventTarget"===n||"Node"===n)&&(c=e._breadcrumbEventHandler("click"),u=e._keypressEventHandler(),l=function(e){if(e){var t;try{t=e.type}catch(e){return}return"click"===t?c(e):"keypress"===t?u(e):void 0}}),t.call(this,r,e.wrap({mechanism:{type:"instrument",data:{target:n,function:"addEventListener",handler:a&&a.name||"<anonymous>"}}},a,l),s,o)}},t),fe(r,"removeEventListener",function(e){return function(t,n,i,r){try{n=n&&(n.__raven_wrapper__?n.__raven_wrapper__:n)}catch(e){}return e.call(this,t,n,i,r)}},t))}fe(Ce,"setTimeout",n,t),fe(Ce,"setInterval",n,t),Ce.requestAnimationFrame&&fe(Ce,"requestAnimationFrame",function(t){return function(n){return t(e.wrap({mechanism:{type:"instrument",data:{function:"requestAnimationFrame",handler:t&&t.name||"<anonymous>"}}},n))}},t);for(var a=["EventTarget","Window","Node","ApplicationCache","AudioTrackList","ChannelMergerNode","CryptoOperation","EventSource","FileReader","HTMLUnknownElement","IDBDatabase","IDBRequest","IDBTransaction","KeyOperation","MediaController","MessagePort","ModalWindow","Notification","SVGElementInstance","Screen","TextTrack","TextTrackCue","TextTrackList","WebSocket","WebSocketWorker","Worker","XMLHttpRequest","XMLHttpRequestEventTarget","XMLHttpRequestUpload"],s=0;s<a.length;s++)r(a[s])},_instrumentBreadcrumbs:function(){var e=this,t=this._globalOptions.autoBreadcrumbs,n=e._wrappedBuiltIns;function i(t,n){t in n&&Z(n[t])&&fe(n,t,function(n){return e.wrap({mechanism:{type:"instrument",data:{function:t,handler:n&&n.name||"<anonymous>"}}},n)})}if(t.xhr&&"XMLHttpRequest"in Ce){var r=Ce.XMLHttpRequest&&Ce.XMLHttpRequest.prototype;fe(r,"open",function(t){return function(n,i){return ee(i)&&-1===i.indexOf(e._globalKey)&&(this.__raven_xhr={method:n,url:i,status_code:null}),t.apply(this,arguments)}},n),fe(r,"send",function(t){return function(){var n=this;function r(){if(n.__raven_xhr&&4===n.readyState){try{n.__raven_xhr.status_code=n.status}catch(e){}e.captureBreadcrumb({type:"http",category:"xhr",data:n.__raven_xhr})}}for(var a=["onload","onerror","onprogress"],s=0;s<a.length;s++)i(a[s],n);return"onreadystatechange"in n&&Z(n.onreadystatechange)?fe(n,"onreadystatechange",function(t){return e.wrap({mechanism:{type:"instrument",data:{function:"onreadystatechange",handler:t&&t.name||"<anonymous>"}}},t,r)}):n.onreadystatechange=r,t.apply(this,arguments)}},n)}t.xhr&&ge()&&fe(Ce,"fetch",function(t){return function(){for(var n=new Array(arguments.length),i=0;i<n.length;++i)n[i]=arguments[i];var r,a=n[0],s="GET";if("string"==typeof a?r=a:"Request"in Ce&&a instanceof Ce.Request?(r=a.url,a.method&&(s=a.method)):r=""+a,-1!==r.indexOf(e._globalKey))return t.apply(this,n);n[1]&&n[1].method&&(s=n[1].method);var o={method:s,url:r,status_code:null};return t.apply(this,n).then(function(t){return o.status_code=t.status,e.captureBreadcrumb({type:"http",category:"fetch",data:o}),t}).catch(function(t){throw e.captureBreadcrumb({type:"http",category:"fetch",data:o,level:"error"}),t})}},n),t.dom&&this._hasDocument&&(Se.addEventListener?(Se.addEventListener("click",e._breadcrumbEventHandler("click"),!1),Se.addEventListener("keypress",e._keypressEventHandler(),!1)):Se.attachEvent&&(Se.attachEvent("onclick",e._breadcrumbEventHandler("click")),Se.attachEvent("onkeypress",e._keypressEventHandler())));var a=Ce.chrome,s=!(a&&a.app&&a.app.runtime)&&Ce.history&&Ce.history.pushState&&Ce.history.replaceState;if(t.location&&s){var o=Ce.onpopstate;Ce.onpopstate=function(){var t=e._location.href;if(e._captureUrlChange(e._lastHref,t),o)return o.apply(this,arguments)};var l=function(t){return function(){var n=arguments.length>2?arguments[2]:void 0;return n&&e._captureUrlChange(e._lastHref,n+""),t.apply(this,arguments)}};fe(Ce.history,"pushState",l,n),fe(Ce.history,"replaceState",l,n)}if(t.console&&"console"in Ce&&console.log){var c=function(t,n){e.captureBreadcrumb({message:t,level:n.level,category:"console"})};ie(["debug","info","warn","error","log"],function(e,t){we(console,t,c)})}},_restoreBuiltIns:function(){for(var e;this._wrappedBuiltIns.length;){var t=(e=this._wrappedBuiltIns.shift())[0],n=e[1],i=e[2];t[n]=i}},_restoreConsole:function(){for(var e in this._originalConsoleMethods)this._originalConsole[e]=this._originalConsoleMethods[e]},_drainPlugins:function(){var e=this;ie(this._plugins,function(t,n){var i=n[0],r=n[1];i.apply(e,[e].concat(r))})},_parseDSN:function(e){var t=Te.exec(e),n={},i=7;try{for(;i--;)n[_e[i]]=t[i]||""}catch(t){throw new z("Invalid DSN: "+e)}if(n.pass&&!this._globalOptions.allowSecretKey)throw new z("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return n},_getGlobalServer:function(e){var t="//"+e.host+(e.port?":"+e.port:"");return e.protocol&&(t=e.protocol+":"+t),t},_handleOnErrorStackInfo:function(e,t){(t=t||{}).mechanism=t.mechanism||{type:"onerror",handled:!1},this._ignoreOnError||this._handleStackInfo(e,t)},_handleStackInfo:function(e,t){var n=this._prepareFrames(e,t);this._triggerEvent("handle",{stackInfo:e,options:t}),this._processException(e.name,e.message,e.url,e.lineno,n,t)},_prepareFrames:function(e,t){var n=this,i=[];if(e.stack&&e.stack.length&&(ie(e.stack,function(t,r){var a=n._normalizeFrame(r,e.url);a&&i.push(a)}),t&&t.trimHeadFrames))for(var r=0;r<t.trimHeadFrames&&r<i.length;r++)i[r].in_app=!1;return i=i.slice(0,this._globalOptions.stackTraceLimit)},_normalizeFrame:function(e,t){var n={filename:e.url,lineno:e.line,colno:e.column,function:e.func||"?"};return e.url||(n.filename=t),n.in_app=!(this._globalOptions.includePaths.test&&!this._globalOptions.includePaths.test(n.filename)||/(Raven|TraceKit)\./.test(n.function)||/raven\.(min\.)?js$/.test(n.filename)),n},_processException:function(e,t,n,i,r,a){var s,o=(e?e+": ":"")+(t||"");if((!this._globalOptions.ignoreErrors.test||!this._globalOptions.ignoreErrors.test(t)&&!this._globalOptions.ignoreErrors.test(o))&&(r&&r.length?(n=r[0].filename||n,r.reverse(),s={frames:r}):n&&(s={frames:[{filename:n,lineno:i,in_app:!0}]}),(!this._globalOptions.ignoreUrls.test||!this._globalOptions.ignoreUrls.test(n))&&(!this._globalOptions.whitelistUrls.test||this._globalOptions.whitelistUrls.test(n)))){var l=re({exception:{values:[{type:e,value:t,stacktrace:s}]},transaction:n},a),c=l.exception.values[0];null==c.type&&""===c.value&&(c.value="Unrecoverable error caught"),!l.exception.mechanism&&l.mechanism&&(l.exception.mechanism=l.mechanism,delete l.mechanism),l.exception.mechanism=re({type:"generic",handled:!0},l.exception.mechanism||{}),this._send(l)}},_trimPacket:function(e){var t=this._globalOptions.maxMessageLength;if(e.message&&(e.message=ae(e.message,t)),e.exception){var n=e.exception.values[0];n.value=ae(n.value,t)}var i=e.request;return i&&(i.url&&(i.url=ae(i.url,this._globalOptions.maxUrlLength)),i.Referer&&(i.Referer=ae(i.Referer,this._globalOptions.maxUrlLength))),e.breadcrumbs&&e.breadcrumbs.values&&this._trimBreadcrumbs(e.breadcrumbs),e},_trimBreadcrumbs:function(e){for(var t,n,i,r=["to","from","url"],a=0;a<e.values.length;++a)if((n=e.values[a]).hasOwnProperty("data")&&$(n.data)&&!se(n.data)){i=re({},n.data);for(var s=0;s<r.length;++s)t=r[s],i.hasOwnProperty(t)&&i[t]&&(i[t]=ae(i[t],this._globalOptions.maxUrlLength));e.values[a].data=i}},_getHttpData:function(){if(this._hasNavigator||this._hasDocument){var e={};return this._hasNavigator&&xe.userAgent&&(e.headers={"User-Agent":xe.userAgent}),Ce.location&&Ce.location.href&&(e.url=Ce.location.href),this._hasDocument&&Se.referrer&&(e.headers||(e.headers={}),e.headers.Referer=Se.referrer),e}},_resetBackoff:function(){this._backoffDuration=0,this._backoffStart=null},_shouldBackoff:function(){return this._backoffDuration&&Ee()-this._backoffStart<this._backoffDuration},_isRepeatData:function(e){var t=this._lastData;return!(!t||e.message!==t.message||e.transaction!==t.transaction)&&(e.stacktrace||t.stacktrace?pe(e.stacktrace,t.stacktrace):!e.exception&&!t.exception||he(e.exception,t.exception))},_setBackoffState:function(e){if(!this._shouldBackoff()){var t=e.status;if(400===t||401===t||429===t){var n;try{n=ge()?e.headers.get("Retry-After"):e.getResponseHeader("Retry-After"),n=1e3*parseInt(n,10)}catch(e){}this._backoffDuration=n||(2*this._backoffDuration||1e3),this._backoffStart=Ee()}}},_send:function(e){var t=this._globalOptions,n={project:this._globalProject,logger:t.logger,platform:"javascript"},i=this._getHttpData();i&&(n.request=i),e.trimHeadFrames&&delete e.trimHeadFrames,(e=re(n,e)).tags=re(re({},this._globalContext.tags),e.tags),e.extra=re(re({},this._globalContext.extra),e.extra),e.extra["session:duration"]=Ee()-this._startTime,this._breadcrumbs&&this._breadcrumbs.length>0&&(e.breadcrumbs={values:[].slice.call(this._breadcrumbs,0)}),this._globalContext.user&&(e.user=this._globalContext.user),t.environment&&(e.environment=t.environment),t.release&&(e.release=t.release),t.serverName&&(e.server_name=t.serverName),e=this._sanitizeData(e),Object.keys(e).forEach(function(t){(null==e[t]||""===e[t]||ne(e[t]))&&delete e[t]}),Z(t.dataCallback)&&(e=t.dataCallback(e)||e),e&&!ne(e)&&(Z(t.shouldSendCallback)&&!t.shouldSendCallback(e)||(this._shouldBackoff()?this._logDebug("warn","Raven dropped error due to backoff: ",e):"number"==typeof t.sampleRate?Math.random()<t.sampleRate&&this._sendProcessedPayload(e):this._sendProcessedPayload(e)))},_sanitizeData:function(e){return ke(e,this._globalOptions.sanitizeKeys)},_getUuid:function(){return ue()},_sendProcessedPayload:function(e,t){var n=this,i=this._globalOptions;if(this.isSetup())if(e=this._trimPacket(e),this._globalOptions.allowDuplicates||!this._isRepeatData(e)){this._lastEventId=e.event_id||(e.event_id=this._getUuid()),this._lastData=e,this._logDebug("debug","Raven about to send:",e);var r={sentry_version:"7",sentry_client:"raven-js/"+this.VERSION,sentry_key:this._globalKey};this._globalSecret&&(r.sentry_secret=this._globalSecret);var a=e.exception&&e.exception.values[0];this._globalOptions.autoBreadcrumbs&&this._globalOptions.autoBreadcrumbs.sentry&&this.captureBreadcrumb({category:"sentry",message:a?(a.type?a.type+": ":"")+a.value:e.message,event_id:e.event_id,level:e.level||"error"});var s=this._globalEndpoint;(i.transport||this._makeRequest).call(this,{url:s,auth:r,data:e,options:i,onSuccess:function(){n._resetBackoff(),n._triggerEvent("success",{data:e,src:s}),t&&t()},onError:function(i){n._logDebug("error","Raven transport failed to send: ",i),i.request&&n._setBackoffState(i.request),n._triggerEvent("failure",{data:e,src:s}),i=i||new Error("Raven send failed (no additional details provided)"),t&&t(i)}})}else this._logDebug("warn","Raven dropped repeat event: ",e)},_makeRequest:function(e){var t=e.url+"?"+ce(e.auth),i=null,r={};if(e.options.headers&&(i=this._evaluateHash(e.options.headers)),e.options.fetchParameters&&(r=this._evaluateHash(e.options.fetchParameters)),ge()){r.body=n(e.data);var a=re({},this._fetchDefaults),s=re(a,r);return i&&(s.headers=i),Ce.fetch(t,s).then(function(t){if(t.ok)e.onSuccess&&e.onSuccess();else{var n=new Error("Sentry error code: "+t.status);n.request=t,e.onError&&e.onError(n)}}).catch(function(){e.onError&&e.onError(new Error("Sentry error code: network unavailable"))})}var o=Ce.XMLHttpRequest&&new Ce.XMLHttpRequest;o&&(("withCredentials"in o||"undefined"!=typeof XDomainRequest)&&("withCredentials"in o?o.onreadystatechange=function(){if(4===o.readyState)if(200===o.status)e.onSuccess&&e.onSuccess();else if(e.onError){var t=new Error("Sentry error code: "+o.status);t.request=o,e.onError(t)}}:(o=new XDomainRequest,t=t.replace(/^https?:/,""),e.onSuccess&&(o.onload=e.onSuccess),e.onError&&(o.onerror=function(){var t=new Error("Sentry error code: XDomainRequest");t.request=o,e.onError(t)})),o.open("POST",t),i&&ie(i,function(e,t){o.setRequestHeader(e,t)}),o.send(n(e.data))))},_evaluateHash:function(e){var t={};for(var n in e)if(e.hasOwnProperty(n)){var i=e[n];t[n]="function"==typeof i?i():i}return t},_logDebug:function(e){this._originalConsoleMethods[e]&&(this.debug||this._globalOptions.debug)&&Function.prototype.apply.call(this._originalConsoleMethods[e],this._originalConsole,[].slice.call(arguments,1))},_mergeContext:function(e,t){Q(t)?delete this._globalContext[e]:this._globalContext[e]=re(this._globalContext[e]||{},t)}},Pe.prototype.setUser=Pe.prototype.setUserContext,Pe.prototype.setReleaseContext=Pe.prototype.setRelease;var Oe=Pe,Me="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},Ne=Me.Raven,Le=new Oe;Le.noConflict=function(){return Me.Raven=Ne,Le},Le.afterLoad();var Ie=Le,je=Oe;function Re(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function De(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function Fe(e,t,n){return t&&De(e.prototype,t),n&&De(e,n),e}function He(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Be(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=[],i=!0,r=!1,a=void 0;try{for(var s,o=e[Symbol.iterator]();!(i=(s=o.next()).done)&&(n.push(s.value),!t||n.length!==t);i=!0);}catch(e){r=!0,a=e}finally{try{i||null==o.return||o.return()}finally{if(r)throw a}}return n}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function qe(e){return function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}Ie.Client=je;var Ue=function(e){return null!=e?e.constructor:null},Ve=function(e,t){return Boolean(e&&t&&e instanceof t)},ze=function(e){return null==e},We=function(e){return Ue(e)===Object},Ke=function(e){return Ue(e)===String},Xe=function(e){return Array.isArray(e)},Ye=function(e){return Ve(e,NodeList)},Je=function(e){return ze(e)||(Ke(e)||Xe(e)||Ye(e))&&!e.length||We(e)&&!Object.keys(e).length},$e={nullOrUndefined:ze,object:We,number:function(e){return Ue(e)===Number&&!Number.isNaN(e)},string:Ke,boolean:function(e){return Ue(e)===Boolean},function:function(e){return Ue(e)===Function},array:Xe,weakMap:function(e){return Ve(e,WeakMap)},nodeList:Ye,element:function(e){return Ve(e,Element)},textNode:function(e){return Ue(e)===Text},event:function(e){return Ve(e,Event)},keyboardEvent:function(e){return Ve(e,KeyboardEvent)},cue:function(e){return Ve(e,window.TextTrackCue)||Ve(e,window.VTTCue)},track:function(e){return Ve(e,TextTrack)||!ze(e)&&Ke(e.kind)},url:function(e){if(Ve(e,window.URL))return!0;if(!Ke(e))return!1;var t=e;e.startsWith("http://")&&e.startsWith("https://")||(t="http://".concat(e));try{return!Je(new URL(t).hostname)}catch(e){return!1}},empty:Je},Ge=function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(e){}return e}();function Qe(e,t,n){var i=this,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(e&&"addEventListener"in e&&!$e.empty(t)&&$e.function(n)){var o=t.split(" "),l=s;Ge&&(l={passive:a,capture:s}),o.forEach(function(t){i&&i.eventListeners&&r&&i.eventListeners.push({element:e,type:t,callback:n,options:l}),e[r?"addEventListener":"removeEventListener"](t,n,l)})}}function Ze(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Qe.call(this,e,t,n,!0,i,r)}function et(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Qe.call(this,e,t,n,!1,i,r)}function tt(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Qe.call(this,e,n,function s(){et(e,n,s,r,a);for(var o=arguments.length,l=new Array(o),c=0;c<o;c++)l[c]=arguments[c];i.apply(t,l)},!0,r,a)}function nt(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if($e.element(e)&&!$e.empty(t)){var r=new CustomEvent(t,{bubbles:n,detail:Object.assign({},i,{plyr:this})});e.dispatchEvent(r)}}function it(e,t){var n=e.length?e:[e];Array.from(n).reverse().forEach(function(e,n){var i=n>0?t.cloneNode(!0):t,r=e.parentNode,a=e.nextSibling;i.appendChild(e),a?r.insertBefore(i,a):r.appendChild(i)})}function rt(e,t){$e.element(e)&&!$e.empty(t)&&Object.entries(t).filter(function(e){var t=Be(e,2)[1];return!$e.nullOrUndefined(t)}).forEach(function(t){var n=Be(t,2),i=n[0],r=n[1];return e.setAttribute(i,r)})}function at(e,t,n){var i=document.createElement(e);return $e.object(t)&&rt(i,t),$e.string(n)&&(i.innerText=n),i}function st(e,t,n,i){$e.element(t)&&t.appendChild(at(e,n,i))}function ot(e){$e.nodeList(e)||$e.array(e)?Array.from(e).forEach(ot):$e.element(e)&&$e.element(e.parentNode)&&e.parentNode.removeChild(e)}function lt(e){if($e.element(e))for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1}function ct(e,t){return $e.element(t)&&$e.element(t.parentNode)&&$e.element(e)?(t.parentNode.replaceChild(e,t),e):null}function ut(e,t){if(!$e.string(e)||$e.empty(e))return{};var n={},i=t;return e.split(",").forEach(function(e){var t=e.trim(),r=t.replace(".",""),a=t.replace(/[[\]]/g,"").split("="),s=a[0],o=a.length>1?a[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":$e.object(i)&&$e.string(i.class)&&(i.class+=" ".concat(r)),n.class=r;break;case"#":n.id=t.replace("#","");break;case"[":n[s]=o}}),n}function dt(e,t){if($e.element(e)){var n=t;$e.boolean(n)||(n=!e.hidden),n?e.setAttribute("hidden",""):e.removeAttribute("hidden")}}function ht(e,t,n){if($e.nodeList(e))return Array.from(e).map(function(e){return ht(e,t,n)});if($e.element(e)){var i="toggle";return void 0!==n&&(i=n?"add":"remove"),e.classList[i](t),e.classList.contains(t)}return!1}function pt(e,t){return $e.element(e)&&e.classList.contains(t)}function mt(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function ft(e){return this.elements.container.querySelectorAll(e)}function gt(e){return this.elements.container.querySelector(e)}function vt(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];$e.element(e)&&(e.focus({preventScroll:!0}),t&&ht(e,this.config.classNames.tabFocus))}var yt,bt,kt,wt=(yt=document.createElement("span"),bt={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},kt=Object.keys(bt).find(function(e){return void 0!==yt.style[e]}),!!$e.string(kt)&&bt[kt]);function _t(e){setTimeout(function(){try{dt(e,!0),e.offsetHeight,dt(e,!1)}catch(e){}},0)}var Tt,Et={isIE:!!document.documentMode,isEdge:window.navigator.userAgent.includes("Edge"),isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)},Ct={"audio/ogg":"vorbis","audio/wav":"1","video/webm":"vp8, vorbis","video/mp4":"avc1.42E01E, mp4a.40.2","video/ogg":"theora"},St={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,n){var i=Et.isIPhone&&n&&St.playsinline,r=St[e]||"html5"!==t;return{api:r,ui:r&&St.rangeInput&&("video"!==e||!Et.isIPhone||i)}},pip:!(Et.isIPhone||!$e.function(at("video").webkitSetPresentationMode)&&(!document.pictureInPictureEnabled||at("video").disablePictureInPicture)),airplay:$e.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){if($e.empty(e))return!1;var t=Be(e.split("/"),1)[0],n=e;if(!this.isHTML5||t!==this.type)return!1;Object.keys(Ct).includes(n)&&(n+='; codecs="'.concat(Ct[e],'"'));try{return Boolean(n&&this.media.canPlayType(n).replace(/no/,""))}catch(e){return!1}},textTracks:"textTracks"in document.createElement("video"),rangeInput:(Tt=document.createElement("input"),Tt.type="range","range"===Tt.type),touch:"ontouchstart"in document.documentElement,transitions:!1!==wt,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},xt={getSources:function(){var e=this;return this.isHTML5?Array.from(this.media.querySelectorAll("source")).filter(function(t){var n=t.getAttribute("type");return!!$e.empty(n)||St.mime.call(e,n)}):[]},getQualityOptions:function(){return xt.getSources.call(this).map(function(e){return Number(e.getAttribute("size"))}).filter(Boolean)},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=xt.getSources.call(e).find(function(t){return t.getAttribute("src")===e.source});return t&&Number(t.getAttribute("size"))},set:function(t){var n=xt.getSources.call(e).find(function(e){return Number(e.getAttribute("size"))===t});if(n){var i=e.media,r=i.currentTime,a=i.paused,s=i.preload,o=i.readyState;e.media.src=n.getAttribute("src"),("none"!==s||o)&&(e.once("loadedmetadata",function(){e.currentTime=r,a||e.play()}),e.media.load()),nt.call(e,e.media,"qualitychange",!1,{quality:t})}}})}},cancelRequests:function(){this.isHTML5&&(ot(xt.getSources.call(this)),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}};function At(e){return $e.array(e)?e.filter(function(t,n){return e.indexOf(t)===n}):e}function Pt(e,t){return t.split(".").reduce(function(e,t){return e&&e[t]},e)}function Ot(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];if(!n.length)return e;var r=n.shift();return $e.object(r)?(Object.keys(r).forEach(function(t){$e.object(r[t])?(Object.keys(e).includes(t)||Object.assign(e,He({},t,{})),Ot(e[t],r[t])):Object.assign(e,He({},t,r[t]))}),Ot.apply(void 0,[e].concat(n))):e}function Mt(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];return $e.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return n[t].toString()})}function Nt(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"),n.toString())}function Lt(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}function It(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=Nt(e,"-"," "),e=Nt(e,"_"," "),Nt(e=Lt(e)," ","")}(e)).charAt(0).toLowerCase()+e.slice(1)}function jt(e){var t=document.createElement("div");return t.appendChild(e),t.innerHTML}var Rt={pip:"PIP",airplay:"AirPlay",html5:"HTML5",vimeo:"Vimeo",youtube:"YouTube"},Dt=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if($e.empty(e)||$e.empty(t))return"";var n=Pt(t.i18n,e);if($e.empty(n))return Object.keys(Rt).includes(e)?Rt[e]:"";var i={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(i).forEach(function(e){var t=Be(e,2),i=t[0],r=t[1];n=Nt(n,i,r)}),n},Ft=function(){function e(t){Re(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return Fe(e,[{key:"get",value:function(t){if(!e.supported||!this.enabled)return null;var n=window.localStorage.getItem(this.key);if($e.empty(n))return null;var i=JSON.parse(n);return $e.string(t)&&t.length?i[t]:i}},{key:"set",value:function(t){if(e.supported&&this.enabled&&$e.object(t)){var n=this.get();$e.empty(n)&&(n={}),Ot(n,t),window.localStorage.setItem(this.key,JSON.stringify(n))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();function Ht(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(n,i){try{var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.addEventListener("load",function(){if("text"===t)try{n(JSON.parse(r.responseText))}catch(e){n(r.responseText)}else n(r.response)}),r.addEventListener("error",function(){throw new Error(r.status)}),r.open("GET",e,!0),r.responseType=t,r.send()}catch(e){i(e)}})}function Bt(e,t){if($e.string(e)){var n=$e.string(t),i=function(){return null!==document.getElementById(t)},r=function(e,t){e.innerHTML=t,n&&i()||document.body.insertAdjacentElement("afterbegin",e)};if(!n||!i()){var a=Ft.supported,s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),a){var o=window.localStorage.getItem("".concat("cache","-").concat(t));if(null!==o){var l=JSON.parse(o);r(s,l.content)}}Ht(e).then(function(e){$e.empty(e)||(a&&window.localStorage.setItem("".concat("cache","-").concat(t),JSON.stringify({content:e})),r(s,e))}).catch(function(){})}}}var qt=function(e){return Math.trunc(e/60/60%60,10)},Ut=function(e){return Math.trunc(e/60%60,10)},Vt=function(e){return Math.trunc(e%60,10)};function zt(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!$e.number(e))return zt(null,t,n);var i=function(e){return"0".concat(e).slice(-2)},r=qt(e),a=Ut(e),s=Vt(e);return r=t||r>0?"".concat(r,":"):"","".concat(n&&e>0?"-":"").concat(r).concat(i(a),":").concat(i(s))}var Wt={getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||Et.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=gt.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:ft.call(this,this.config.selectors.buttons.play),pause:gt.call(this,this.config.selectors.buttons.pause),restart:gt.call(this,this.config.selectors.buttons.restart),rewind:gt.call(this,this.config.selectors.buttons.rewind),fastForward:gt.call(this,this.config.selectors.buttons.fastForward),mute:gt.call(this,this.config.selectors.buttons.mute),pip:gt.call(this,this.config.selectors.buttons.pip),airplay:gt.call(this,this.config.selectors.buttons.airplay),settings:gt.call(this,this.config.selectors.buttons.settings),captions:gt.call(this,this.config.selectors.buttons.captions),fullscreen:gt.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=gt.call(this,this.config.selectors.progress),this.elements.inputs={seek:gt.call(this,this.config.selectors.inputs.seek),volume:gt.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:gt.call(this,this.config.selectors.display.buffer),currentTime:gt.call(this,this.config.selectors.display.currentTime),duration:gt.call(this,this.config.selectors.display.duration)},$e.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip))),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var n=Wt.getIconUrl.call(this),i="".concat(n.cors?"":n.url,"#").concat(this.config.iconPrefix),r=document.createElementNS("http://www.w3.org/2000/svg","svg");rt(r,Ot(t,{role:"presentation",focusable:"false"}));var a=document.createElementNS("http://www.w3.org/2000/svg","use"),s="".concat(i,"-").concat(e);return"href"in a&&a.setAttributeNS("http://www.w3.org/1999/xlink","href",s),a.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",s),r.appendChild(a),r},createLabel:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Dt(e,this.config);return at("span",Object.assign({},t,{class:[t.class,this.config.classNames.hidden].filter(Boolean).join(" ")}),n)},createBadge:function(e){if($e.empty(e))return null;var t=at("span",{class:this.config.classNames.menu.value});return t.appendChild(at("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var n=Object.assign({},t),i=It(e),r={element:"button",toggle:!1,label:null,icon:null,labelPressed:null,iconPressed:null};switch(["element","icon","label"].forEach(function(e){Object.keys(n).includes(e)&&(r[e]=n[e],delete n[e])}),"button"!==r.element||Object.keys(n).includes("type")||(n.type="button"),Object.keys(n).includes("class")?n.class.includes(this.config.classNames.control)||(n.class+=" ".concat(this.config.classNames.control)):n.class=this.config.classNames.control,e){case"play":r.toggle=!0,r.label="play",r.labelPressed="pause",r.icon="play",r.iconPressed="pause";break;case"mute":r.toggle=!0,r.label="mute",r.labelPressed="unmute",r.icon="volume",r.iconPressed="muted";break;case"captions":r.toggle=!0,r.label="enableCaptions",r.labelPressed="disableCaptions",r.icon="captions-off",r.iconPressed="captions-on";break;case"fullscreen":r.toggle=!0,r.label="enterFullscreen",r.labelPressed="exitFullscreen",r.icon="enter-fullscreen",r.iconPressed="exit-fullscreen";break;case"play-large":n.class+=" ".concat(this.config.classNames.control,"--overlaid"),i="play",r.label="play",r.icon="play";break;default:$e.empty(r.label)&&(r.label=i),$e.empty(r.icon)&&(r.icon=e)}var a=at(r.element);return r.toggle?(a.appendChild(Wt.createIcon.call(this,r.iconPressed,{class:"icon--pressed"})),a.appendChild(Wt.createIcon.call(this,r.icon,{class:"icon--not-pressed"})),a.appendChild(Wt.createLabel.call(this,r.labelPressed,{class:"label--pressed"})),a.appendChild(Wt.createLabel.call(this,r.label,{class:"label--not-pressed"}))):(a.appendChild(Wt.createIcon.call(this,r.icon)),a.appendChild(Wt.createLabel.call(this,r.label))),Ot(n,ut(this.config.selectors.buttons[i],n)),rt(a,n),"play"===i?($e.array(this.elements.buttons[i])||(this.elements.buttons[i]=[]),this.elements.buttons[i].push(a)):this.elements.buttons[i]=a,a},createRange:function(e,t){var n=at("input",Ot(ut(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-label":Dt(e,this.config),"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=n,Wt.updateRangeFill.call(this,n),n},createProgress:function(e,t){var n=at("progress",Ot(ut(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){n.appendChild(at("span",null,"0"));var i={played:"played",buffer:"buffered"}[e],r=i?Dt(i,this.config):"";n.innerText="% ".concat(r.toLowerCase())}return this.elements.display[e]=n,n},createTime:function(e){var t=ut(this.config.selectors.display[e]),n=at("div",Ot(t,{class:"".concat(this.config.classNames.display.time," ").concat(t.class?t.class:"").trim(),"aria-label":Dt(e,this.config)}),"00:00");return this.elements.display[e]=n,n},bindMenuItemShortcuts:function(e,t){var n=this;Ze(e,"keydown keyup",function(i){if([32,38,39,40].includes(i.which)&&(i.preventDefault(),i.stopPropagation(),"keydown"!==i.type)){var r,a=mt(e,'[role="menuitemradio"]');if(!a&&[32,39].includes(i.which))Wt.showMenuPanel.call(n,t,!0);else 32!==i.which&&(40===i.which||a&&39===i.which?(r=e.nextElementSibling,$e.element(r)||(r=e.parentNode.firstElementChild)):(r=e.previousElementSibling,$e.element(r)||(r=e.parentNode.lastElementChild)),vt.call(n,r,!0))}},!1),Ze(e,"keyup",function(e){13===e.which&&Wt.focusFirstMenuItem.call(n,null,!0)})},createMenuItem:function(e){var t=this,n=e.value,i=e.list,r=e.type,a=e.title,s=e.badge,o=void 0===s?null:s,l=e.checked,c=void 0!==l&&l,u=ut(this.config.selectors.inputs[r]),d=at("button",Ot(u,{type:"button",role:"menuitemradio",class:"".concat(this.config.classNames.control," ").concat(u.class?u.class:"").trim(),"aria-checked":c,value:n})),h=at("span");h.innerHTML=a,$e.element(o)&&h.appendChild(o),d.appendChild(h),Object.defineProperty(d,"checked",{enumerable:!0,get:function(){return"true"===d.getAttribute("aria-checked")},set:function(e){e&&Array.from(d.parentNode.children).filter(function(e){return mt(e,'[role="menuitemradio"]')}).forEach(function(e){return e.setAttribute("aria-checked","false")}),d.setAttribute("aria-checked",e?"true":"false")}}),this.listeners.bind(d,"click keyup",function(e){if(!$e.keyboardEvent(e)||32===e.which){switch(e.preventDefault(),e.stopPropagation(),d.checked=!0,r){case"language":t.currentTrack=Number(n);break;case"quality":t.quality=n;break;case"speed":t.speed=parseFloat(n)}Wt.showMenuPanel.call(t,"home",$e.keyboardEvent(e))}},r,!1),Wt.bindMenuItemShortcuts.call(this,d,r),i.appendChild(d)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return $e.number(e)?zt(e,qt(this.duration)>0,t):e},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];$e.element(e)&&$e.number(t)&&(e.innerText=Wt.formatTime(t,n))},updateVolume:function(){this.supported.ui&&($e.element(this.elements.inputs.volume)&&Wt.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),$e.element(this.elements.buttons.mute)&&(this.elements.buttons.mute.pressed=this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;$e.element(e)&&(e.value=t,Wt.updateRangeFill.call(this,e))},updateProgress:function(e){var t=this;if(this.supported.ui&&$e.event(e)){var n,i,r=0;if(e)switch(e.type){case"timeupdate":case"seeking":case"seeked":n=this.currentTime,i=this.duration,r=0===n||0===i||Number.isNaN(n)||Number.isNaN(i)?0:(n/i*100).toFixed(2),"timeupdate"===e.type&&Wt.setRange.call(this,this.elements.inputs.seek,r);break;case"playing":case"progress":!function(e,n){var i=$e.number(n)?n:0,r=$e.element(e)?e:t.elements.display.buffer;if($e.element(r)){r.value=i;var a=r.getElementsByTagName("span")[0];$e.element(a)&&(a.childNodes[0].nodeValue=i)}}(this.elements.display.buffer,100*this.buffered)}}},updateRangeFill:function(e){var t=$e.event(e)?e.target:e;if($e.element(t)&&"range"===t.getAttribute("type")){if(mt(t,this.config.selectors.inputs.seek)){t.setAttribute("aria-valuenow",this.currentTime);var n=Wt.formatTime(this.currentTime),i=Wt.formatTime(this.duration),r=Dt("seekLabel",this.config);t.setAttribute("aria-valuetext",r.replace("{currentTime}",n).replace("{duration}",i))}else if(mt(t,this.config.selectors.inputs.volume)){var a=100*t.value;t.setAttribute("aria-valuenow",a),t.setAttribute("aria-valuetext","".concat(a.toFixed(1),"%"))}else t.setAttribute("aria-valuenow",t.value);Et.isWebkit&&t.style.setProperty("--value","".concat(t.value/t.max*100,"%"))}},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&$e.element(this.elements.inputs.seek)&&$e.element(this.elements.display.seekTooltip)&&0!==this.duration){var n=0,i=this.elements.progress.getBoundingClientRect(),r="".concat(this.config.classNames.tooltip,"--visible"),a=function(e){ht(t.elements.display.seekTooltip,r,e)};if(this.touch)a(!1);else{if($e.event(e))n=100/i.width*(e.pageX-i.left);else{if(!pt(this.elements.display.seekTooltip,r))return;n=parseFloat(this.elements.display.seekTooltip.style.left,10)}n<0?n=0:n>100&&(n=100),Wt.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*n),this.elements.display.seekTooltip.style.left="".concat(n,"%"),$e.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&a("mouseenter"===e.type)}}},timeUpdate:function(e){var t=!$e.element(this.elements.display.duration)&&this.config.invertTime;Wt.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||Wt.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui&&(this.config.invertTime||!this.currentTime)){if(this.duration>=Math.pow(2,32))return dt(this.elements.display.currentTime,!0),void dt(this.elements.progress,!0);$e.element(this.elements.inputs.seek)&&this.elements.inputs.seek.setAttribute("aria-valuemax",this.duration);var e=$e.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&Wt.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&Wt.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),Wt.updateSeekTooltip.call(this)}},toggleMenuButton:function(e,t){dt(this.elements.settings.buttons[e],!t)},updateSetting:function(e,t,n){var i=this.elements.settings.panels[e],r=null,a=t;if("captions"===e)r=this.currentTrack;else{if(r=$e.empty(n)?this[e]:n,$e.empty(r)&&(r=this.config[e].default),!$e.empty(this.options[e])&&!this.options[e].includes(r))return void this.debug.warn("Unsupported value of '".concat(r,"' for ").concat(e));if(!this.config[e].options.includes(r))return void this.debug.warn("Disabled value of '".concat(r,"' for ").concat(e))}if($e.element(a)||(a=i&&i.querySelector('[role="menu"]')),$e.element(a)){this.elements.settings.buttons[e].querySelector(".".concat(this.config.classNames.menu.value)).innerHTML=Wt.getLabel.call(this,e,r);var s=a&&a.querySelector('[value="'.concat(r,'"]'));$e.element(s)&&(s.checked=!0)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?Dt("normal",this.config):"".concat(t,"×");case"quality":if($e.number(t)){var n=Dt("qualityLabel.".concat(t),this.config);return n.length?n:"".concat(t,"p")}return Lt(t);case"captions":return Yt.getLabel.call(this);default:return null}},setQualityMenu:function(e){var t=this;if($e.element(this.elements.settings.panels.quality)){var n=this.elements.settings.panels.quality.querySelector('[role="menu"]');$e.array(e)&&(this.options.quality=At(e).filter(function(e){return t.config.quality.options.includes(e)}));var i=!$e.empty(this.options.quality)&&this.options.quality.length>1;if(Wt.toggleMenuButton.call(this,"quality",i),lt(n),Wt.checkMenu.call(this),i){var r=function(e){var n=Dt("qualityBadge.".concat(e),t.config);return n.length?Wt.createBadge.call(t,n):null};this.options.quality.sort(function(e,n){var i=t.config.quality.options;return i.indexOf(e)>i.indexOf(n)?1:-1}).forEach(function(e){Wt.createMenuItem.call(t,{value:e,list:n,type:"quality",title:Wt.getLabel.call(t,"quality",e),badge:r(e)})}),Wt.updateSetting.call(this,"quality",n)}}},setCaptionsMenu:function(){var e=this;if($e.element(this.elements.settings.panels.captions)){var t=this.elements.settings.panels.captions.querySelector('[role="menu"]'),n=Yt.getTracks.call(this),i=Boolean(n.length);if(Wt.toggleMenuButton.call(this,"captions",i),lt(t),Wt.checkMenu.call(this),i){var r=n.map(function(n,i){return{value:i,checked:e.captions.toggled&&e.currentTrack===i,title:Yt.getLabel.call(e,n),badge:n.language&&Wt.createBadge.call(e,n.language.toUpperCase()),list:t,type:"language"}});r.unshift({value:-1,checked:!this.captions.toggled,title:Dt("disabled",this.config),list:t,type:"language"}),r.forEach(Wt.createMenuItem.bind(this)),Wt.updateSetting.call(this,"captions",t)}}},setSpeedMenu:function(e){var t=this;if($e.element(this.elements.settings.panels.speed)){var n=this.elements.settings.panels.speed.querySelector('[role="menu"]');$e.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var i=!$e.empty(this.options.speed)&&this.options.speed.length>1;Wt.toggleMenuButton.call(this,"speed",i),lt(n),Wt.checkMenu.call(this),i&&(this.options.speed.forEach(function(e){Wt.createMenuItem.call(t,{value:e,list:n,type:"speed",title:Wt.getLabel.call(t,"speed",e)})}),Wt.updateSetting.call(this,"speed",n))}},checkMenu:function(){var e=this.elements.settings.buttons,t=!$e.empty(e)&&Object.values(e).some(function(e){return!e.hidden});dt(this.elements.settings.menu,!t)},focusFirstMenuItem:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!this.elements.settings.popup.hidden){var n=e;$e.element(n)||(n=Object.values(this.elements.settings.panels).find(function(e){return!e.hidden}));var i=n.querySelector('[role^="menuitem"]');vt.call(this,i,t)}},toggleMenu:function(e){var t=this.elements.settings.popup,n=this.elements.buttons.settings;if($e.element(t)&&$e.element(n)){var i=t.hidden,r=i;if($e.boolean(e))r=e;else if($e.keyboardEvent(e)&&27===e.which)r=!1;else if($e.event(e)){var a=t.contains(e.target);if(a||!a&&e.target!==n&&r)return}n.setAttribute("aria-expanded",r),dt(t,!r),ht(this.elements.container,this.config.classNames.menu.open,r),r&&$e.keyboardEvent(e)?Wt.focusFirstMenuItem.call(this,null,!0):r||i||vt.call(this,n,$e.keyboardEvent(e))}},getMenuSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),e.parentNode.appendChild(t);var n=t.scrollWidth,i=t.scrollHeight;return ot(t),{width:n,height:i}},showMenuPanel:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=document.getElementById("plyr-settings-".concat(this.id,"-").concat(t));if($e.element(i)){var r=i.parentNode,a=Array.from(r.children).find(function(e){return!e.hidden});if(St.transitions&&!St.reducedMotion){r.style.width="".concat(a.scrollWidth,"px"),r.style.height="".concat(a.scrollHeight,"px");var s=Wt.getMenuSize.call(this,i);Ze.call(this,r,wt,function t(n){n.target===r&&["width","height"].includes(n.propertyName)&&(r.style.width="",r.style.height="",et.call(e,r,wt,t))}),r.style.width="".concat(s.width,"px"),r.style.height="".concat(s.height,"px")}dt(a,!0),dt(i,!1),Wt.focusFirstMenuItem.call(this,i,n)}},setDownloadLink:function(){var e=this.elements.buttons.download;$e.element(e)&&e.setAttribute("href",this.download)},create:function(e){var t=this,n=at("div",ut(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&n.appendChild(Wt.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&n.appendChild(Wt.createButton.call(this,"rewind")),this.config.controls.includes("play")&&n.appendChild(Wt.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&n.appendChild(Wt.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var i=at("div",ut(this.config.selectors.progress));if(i.appendChild(Wt.createRange.call(this,"seek",{id:"plyr-seek-".concat(e.id)})),i.appendChild(Wt.createProgress.call(this,"buffer")),this.config.tooltips.seek){var r=at("span",{class:this.config.classNames.tooltip},"00:00");i.appendChild(r),this.elements.display.seekTooltip=r}this.elements.progress=i,n.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&n.appendChild(Wt.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&n.appendChild(Wt.createTime.call(this,"duration")),this.config.controls.includes("mute")||this.config.controls.includes("volume")){var a=at("div",{class:"plyr__volume"});if(this.config.controls.includes("mute")&&a.appendChild(Wt.createButton.call(this,"mute")),this.config.controls.includes("volume")){var s={max:1,step:.05,value:this.config.volume};a.appendChild(Wt.createRange.call(this,"volume",Ot(s,{id:"plyr-volume-".concat(e.id)}))),this.elements.volume=a}n.appendChild(a)}if(this.config.controls.includes("captions")&&n.appendChild(Wt.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!$e.empty(this.config.settings)){var o=at("div",{class:"plyr__menu",hidden:""});o.appendChild(Wt.createButton.call(this,"settings",{"aria-haspopup":!0,"aria-controls":"plyr-settings-".concat(e.id),"aria-expanded":!1}));var l=at("div",{class:"plyr__menu__container",id:"plyr-settings-".concat(e.id),hidden:""}),c=at("div"),u=at("div",{id:"plyr-settings-".concat(e.id,"-home")}),d=at("div",{role:"menu"});u.appendChild(d),c.appendChild(u),this.elements.settings.panels.home=u,this.config.settings.forEach(function(n){var i=at("button",Ot(ut(t.config.selectors.buttons.settings),{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--forward"),role:"menuitem","aria-haspopup":!0,hidden:""}));Wt.bindMenuItemShortcuts.call(t,i,n),Ze(i,"click",function(){Wt.showMenuPanel.call(t,n,!1)});var r=at("span",null,Dt(n,t.config)),a=at("span",{class:t.config.classNames.menu.value});a.innerHTML=e[n],r.appendChild(a),i.appendChild(r),d.appendChild(i);var s=at("div",{id:"plyr-settings-".concat(e.id,"-").concat(n),hidden:""}),o=at("button",{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--back")});o.appendChild(at("span",{"aria-hidden":!0},Dt(n,t.config))),o.appendChild(at("span",{class:t.config.classNames.hidden},Dt("menuBack",t.config))),Ze(s,"keydown",function(e){37===e.which&&(e.preventDefault(),e.stopPropagation(),Wt.showMenuPanel.call(t,"home",!0))},!1),Ze(o,"click",function(){Wt.showMenuPanel.call(t,"home",!1)}),s.appendChild(o),s.appendChild(at("div",{role:"menu"})),c.appendChild(s),t.elements.settings.buttons[n]=i,t.elements.settings.panels[n]=s}),l.appendChild(c),o.appendChild(l),n.appendChild(o),this.elements.settings.popup=l,this.elements.settings.menu=o}if(this.config.controls.includes("pip")&&St.pip&&n.appendChild(Wt.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&St.airplay&&n.appendChild(Wt.createButton.call(this,"airplay")),this.config.controls.includes("download")){var h={element:"a",href:this.download,target:"_blank"},p=this.config.urls.download;!$e.url(p)&&this.isEmbed&&Ot(h,{icon:"logo-".concat(this.provider),label:this.provider}),n.appendChild(Wt.createButton.call(this,"download",h))}return this.config.controls.includes("fullscreen")&&n.appendChild(Wt.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(Wt.createButton.call(this,"play-large")),this.elements.controls=n,this.isHTML5&&Wt.setQualityMenu.call(this,xt.getQualityOptions.call(this)),Wt.setSpeedMenu.call(this),n},inject:function(){var e=this;if(this.config.loadSprite){var t=Wt.getIconUrl.call(this);t.cors&&Bt(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var n=null;this.elements.controls=null;var i={id:this.id,seektime:this.config.seekTime,title:this.config.title},r=!0;$e.function(this.config.controls)&&(this.config.controls=this.config.controls.call(this,i)),this.config.controls||(this.config.controls=[]),$e.element(this.config.controls)||$e.string(this.config.controls)?n=this.config.controls:(n=Wt.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:Yt.getLabel.call(this)}),r=!1);var a,s=function(e){var t=e;return Object.entries(i).forEach(function(e){var n=Be(e,2),i=n[0],r=n[1];t=Nt(t,"{".concat(i,"}"),r)}),t};if(r&&($e.string(this.config.controls)?n=s(n):$e.element(n)&&(n.innerHTML=s(n.innerHTML))),$e.string(this.config.selectors.controls.container)&&(a=document.querySelector(this.config.selectors.controls.container)),$e.element(a)||(a=this.elements.container),a[$e.element(n)?"insertAdjacentElement":"insertAdjacentHTML"]("afterbegin",n),$e.element(this.elements.controls)||Wt.findElements.call(this),!$e.empty(this.elements.buttons)){var o=function(t){var n=e.config.classNames.controlPressed;Object.defineProperty(t,"pressed",{enumerable:!0,get:function(){return pt(t,n)},set:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];ht(t,n,e)}})};Object.values(this.elements.buttons).filter(Boolean).forEach(function(e){$e.array(e)||$e.nodeList(e)?Array.from(e).filter(Boolean).forEach(o):o(e)})}if(Et.isEdge&&_t(a),this.config.tooltips.controls){var l=this.config,c=l.classNames,u=l.selectors,d="".concat(u.controls.wrapper," ").concat(u.labels," .").concat(c.hidden),h=ft.call(this,d);Array.from(h).forEach(function(t){ht(t,e.config.classNames.hidden,!1),ht(t,e.config.classNames.tooltip,!0)})}}};function Kt(e){var t=e;if(!(arguments.length>1&&void 0!==arguments[1])||arguments[1]){var n=document.createElement("a");n.href=t,t=n.href}try{return new URL(t)}catch(e){return null}}function Xt(e){var t=new URLSearchParams;return $e.object(e)&&Object.entries(e).forEach(function(e){var n=Be(e,2),i=n[0],r=n[1];t.set(i,r)}),t}var Yt={setup:function(){if(this.supported.ui)if(!this.isVideo||this.isYouTube||this.isHTML5&&!St.textTracks)$e.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&Wt.setCaptionsMenu.call(this);else{var e,t;if($e.element(this.elements.captions)||(this.elements.captions=at("div",ut(this.config.selectors.captions)),e=this.elements.captions,t=this.elements.wrapper,$e.element(e)&&$e.element(t)&&t.parentNode.insertBefore(e,t.nextSibling)),Et.isIE&&window.URL){var n=this.media.querySelectorAll("track");Array.from(n).forEach(function(e){var t=e.getAttribute("src"),n=Kt(t);null!==n&&n.hostname!==window.location.href.hostname&&["http:","https:"].includes(n.protocol)&&Ht(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){ot(e)})})}var i=At((navigator.languages||[navigator.language||navigator.userLanguage||"en"]).map(function(e){return e.split("-")[0]})),r=(this.storage.get("language")||this.config.captions.language||"auto").toLowerCase();if("auto"===r)r=Be(i,1)[0];var a=this.storage.get("captions");if($e.boolean(a)||(a=this.config.captions.active),Object.assign(this.captions,{toggled:!1,active:a,language:r,languages:i}),this.isHTML5){var s=this.config.captions.update?"addtrack removetrack":"removetrack";Ze.call(this,this.media.textTracks,s,Yt.update.bind(this))}setTimeout(Yt.update.bind(this),0)}},update:function(){var e=this,t=Yt.getTracks.call(this,!0),n=this.captions,i=n.active,r=n.language,a=n.meta,s=n.currentTrackNode,o=Boolean(t.find(function(e){return e.language===r}));this.isHTML5&&this.isVideo&&t.filter(function(e){return!a.get(e)}).forEach(function(t){e.debug.log("Track added",t),a.set(t,{default:"showing"===t.mode}),t.mode="hidden",Ze.call(e,t,"cuechange",function(){return Yt.updateCues.call(e)})}),(o&&this.language!==r||!t.includes(s))&&(Yt.setLanguage.call(this,r),Yt.toggle.call(this,i&&o)),ht(this.elements.container,this.config.classNames.captions.enabled,!$e.empty(t)),(this.config.controls||[]).includes("settings")&&this.config.settings.includes("captions")&&Wt.setCaptionsMenu.call(this)},toggle:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.supported.ui){var n=this.captions.toggled,i=this.config.classNames.captions.active,r=$e.nullOrUndefined(e)?!n:e;if(r!==n){if(t||(this.captions.active=r,this.storage.set({captions:r})),!this.language&&r&&!t){var a=Yt.getTracks.call(this),s=Yt.findTrack.call(this,[this.captions.language].concat(qe(this.captions.languages)),!0);return this.captions.language=s.language,void Yt.set.call(this,a.indexOf(s))}this.elements.buttons.captions&&(this.elements.buttons.captions.pressed=r),ht(this.elements.container,i,r),this.captions.toggled=r,Wt.updateSetting.call(this,"captions"),nt.call(this,this.media,r?"captionsenabled":"captionsdisabled")}}},set:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=Yt.getTracks.call(this);if(-1!==e)if($e.number(e))if(e in n){if(this.captions.currentTrack!==e){this.captions.currentTrack=e;var i=n[e],r=(i||{}).language;this.captions.currentTrackNode=i,Wt.updateSetting.call(this,"captions"),t||(this.captions.language=r,this.storage.set({language:r})),this.isVimeo&&this.embed.enableTextTrack(r),nt.call(this,this.media,"languagechange")}Yt.toggle.call(this,!0,t),this.isHTML5&&this.isVideo&&Yt.updateCues.call(this)}else this.debug.warn("Track not found",e);else this.debug.warn("Invalid caption argument",e);else Yt.toggle.call(this,!1,t)},setLanguage:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if($e.string(e)){var n=e.toLowerCase();this.captions.language=n;var i=Yt.getTracks.call(this),r=Yt.findTrack.call(this,[n]);Yt.set.call(this,i.indexOf(r),t)}else this.debug.warn("Invalid language argument",e)},getTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Array.from((this.media||{}).textTracks||[]).filter(function(n){return!e.isHTML5||t||e.captions.meta.has(n)}).filter(function(e){return["captions","subtitles"].includes(e.kind)})},findTrack:function(e){var t,n=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=Yt.getTracks.call(this),a=function(e){return Number((n.captions.meta.get(e)||{}).default)},s=Array.from(r).sort(function(e,t){return a(t)-a(e)});return e.every(function(e){return!(t=s.find(function(t){return t.language===e}))}),t||(i?s[0]:void 0)},getCurrentTrack:function(){return Yt.getTracks.call(this)[this.currentTrack]},getLabel:function(e){var t=e;return!$e.track(t)&&St.textTracks&&this.captions.toggled&&(t=Yt.getCurrentTrack.call(this)),$e.track(t)?$e.empty(t.label)?$e.empty(t.language)?Dt("enabled",this.config):e.language.toUpperCase():t.label:Dt("disabled",this.config)},updateCues:function(e){if(this.supported.ui)if($e.element(this.elements.captions))if($e.nullOrUndefined(e)||Array.isArray(e)){var t=e;if(!t){var n=Yt.getCurrentTrack.call(this);t=Array.from((n||{}).activeCues||[]).map(function(e){return e.getCueAsHTML()}).map(jt)}var i=t.map(function(e){return e.trim()}).join("\n");if(i!==this.elements.captions.innerHTML){lt(this.elements.captions);var r=at("span",ut(this.config.selectors.caption));r.innerHTML=i,this.elements.captions.appendChild(r),nt.call(this,this.media,"cuechange")}}else this.debug.warn("updateCues: Invalid input",e);else this.debug.warn("No captions element to render to")}},Jt={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,playsinline:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.4.8/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:"auto",update:!1},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",seekLabel:"{currentTime} of {duration}",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",download:"Download",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",menuBack:"Go back to previous menu",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad",qualityBadge:{2160:"4K",1440:"HD",1080:"HD",720:"HD",576:"SD",480:"SD"}},urls:{download:null,vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,download:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","download","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',download:'[data-plyr="download"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress__buffer",loop:".plyr__progress__loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",caption:".plyr__caption",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",posterEnabled:"plyr__poster-enabled",ads:"plyr__ads",control:"plyr__control",controlPressed:"plyr__control--pressed",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",display:{time:"plyr__time"},menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus",previewThumbnails:{thumbContainer:"plyr__preview-thumb",thumbContainerShown:"plyr__preview-thumb--is-shown",imageContainer:"plyr__preview-thumb__image-container",timeContainer:"plyr__preview-thumb__time-container",scrubbingContainer:"plyr__preview-scrubbing",scrubbingContainerShown:"plyr__preview-scrubbing--is-shown"}},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:"",tagUrl:""},previewThumbnails:{enabled:!1,src:""},vimeo:{byline:!1,portrait:!1,title:!1,speed:!0,transparent:!1},youtube:{noCookie:!1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1}},$t="picture-in-picture",Gt="inline",Qt={html5:"html5",youtube:"youtube",vimeo:"vimeo"},Zt={audio:"audio",video:"video"};var en=function(){},tn=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];Re(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return Fe(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):en}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):en}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):en}}]),e}();function nn(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;$e.element(e)&&(e.pressed=this.active),nt.call(this.player,this.target,this.active?"enterfullscreen":"exitfullscreen",!0),Et.isIos||function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if($e.element(e)){var n=ft.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=n[0],r=n[n.length-1];Qe.call(this,this.elements.container,"keydown",function(e){if("Tab"===e.key&&9===e.keyCode){var t=document.activeElement;t!==r||e.shiftKey?t===i&&e.shiftKey&&(r.focus(),e.preventDefault()):(i.focus(),e.preventDefault())}},t,!1)}}.call(this.player,this.target,this.active)}}function rn(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(t?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=t?"hidden":"",ht(this.target,this.player.config.classNames.fullscreen.fallback,t),Et.isIos){var n=document.head.querySelector('meta[name="viewport"]'),i="viewport-fit=cover";n||(n=document.createElement("meta")).setAttribute("name","viewport");var r=$e.string(n.content)&&n.content.includes(i);t?(this.cleanupViewport=!r,r||(n.content+=",".concat(i))):this.cleanupViewport&&(n.content=n.content.split(",").filter(function(e){return e.trim()!==i}).join(",")),setTimeout(function(){return _t(e.target)},100)}nn.call(this)}var an=function(){function e(t){var n=this;Re(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},this.forceFallback="force"===t.config.fullscreen.fallback,Ze.call(this.player,document,"ms"===this.prefix?"MSFullscreenChange":"".concat(this.prefix,"fullscreenchange"),function(){nn.call(n)}),Ze.call(this.player,this.player.elements.container,"dblclick",function(e){$e.element(n.player.elements.controls)&&n.player.elements.controls.contains(e.target)||n.toggle()}),this.update()}return Fe(e,[{key:"update",value:function(){var t;this.enabled?(t=this.forceFallback?"Fallback (forced)":e.native?"Native":"Fallback",this.player.debug.log("".concat(t," fullscreen enabled"))):this.player.debug.log("Fullscreen not supported and fallback disabled");ht(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(Et.isIos&&this.player.config.fullscreen.iosNative?this.target.webkitEnterFullscreen():!e.native||this.forceFallback?rn.call(this,!0):this.prefix?$e.empty(this.prefix)||this.target["".concat(this.prefix,"Request").concat(this.property)]():this.target.requestFullscreen())}},{key:"exit",value:function(){if(this.enabled)if(Et.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(!e.native||this.forceFallback)rn.call(this,!1);else if(this.prefix){if(!$e.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document["".concat(this.prefix).concat(t).concat(this.property)]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"usingNative",get:function(){return e.native&&!this.forceFallback}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(!e.native||this.forceFallback?pt(this.target,this.player.config.classNames.fullscreen.fallback):(this.prefix?document["".concat(this.prefix).concat(this.property,"Element")]:document.fullscreenElement)===this.target)}},{key:"target",get:function(){return Et.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if($e.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!$e.function(document["".concat(t,"ExitFullscreen")])&&!$e.function(document["".concat(t,"CancelFullScreen")]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}();function sn(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return new Promise(function(n,i){var r=new Image,a=function(){delete r.onload,delete r.onerror,(r.naturalWidth>=t?n:i)(r)};Object.assign(r,{onload:a,onerror:a,src:e})})}var on={addStyleHook:function(){ht(this.elements.container,this.config.selectors.container.replace(".",""),!0),ht(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for ".concat(this.provider," ").concat(this.type)),void on.toggleNativeControls.call(this,!0);$e.element(this.elements.controls)||(Wt.inject.call(this),this.listeners.controls()),on.toggleNativeControls.call(this),this.isHTML5&&Yt.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,Wt.updateVolume.call(this),Wt.timeUpdate.call(this),on.checkPlaying.call(this),ht(this.elements.container,this.config.classNames.pip.supported,St.pip&&this.isHTML5&&this.isVideo),ht(this.elements.container,this.config.classNames.airplay.supported,St.airplay&&this.isHTML5),ht(this.elements.container,this.config.classNames.isIos,Et.isIos),ht(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){nt.call(e,e.media,"ready")},0),on.setTitle.call(this),this.poster&&on.setPoster.call(this,this.poster,!1).catch(function(){}),this.config.duration&&Wt.durationUpdate.call(this)},setTitle:function(){var e=Dt("play",this.config);if($e.string(this.config.title)&&!$e.empty(this.config.title)&&(e+=", ".concat(this.config.title)),Array.from(this.elements.buttons.play||[]).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=gt.call(this,"iframe");if(!$e.element(t))return;var n=$e.empty(this.config.title)?"video":this.config.title,i=Dt("frameTitle",this.config);t.setAttribute("title",i.replace("{title}",n))}},togglePoster:function(e){ht(this.elements.container,this.config.classNames.posterEnabled,e)},setPoster:function(e){var t=this;return arguments.length>1&&void 0!==arguments[1]&&!arguments[1]||!this.poster?(this.media.setAttribute("poster",e),function(){var e=this;return new Promise(function(t){return e.ready?setTimeout(t,0):Ze.call(e,e.elements.container,"ready",t)}).then(function(){})}.call(this).then(function(){return sn(e)}).catch(function(n){throw e===t.poster&&on.togglePoster.call(t,!1),n}).then(function(){if(e!==t.poster)throw new Error("setPoster cancelled by later call to setPoster")}).then(function(){return Object.assign(t.elements.poster.style,{backgroundImage:"url('".concat(e,"')"),backgroundSize:""}),on.togglePoster.call(t,!0),e})):Promise.reject(new Error("Poster already set"))},checkPlaying:function(e){var t=this;ht(this.elements.container,this.config.classNames.playing,this.playing),ht(this.elements.container,this.config.classNames.paused,this.paused),ht(this.elements.container,this.config.classNames.stopped,this.stopped),Array.from(this.elements.buttons.play||[]).forEach(function(e){e.pressed=t.playing}),$e.event(e)&&"timeupdate"===e.type||on.toggleControls.call(this)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){ht(t.elements.container,t.config.classNames.loading,t.loading),on.toggleControls.call(t)},this.loading?250:0)},toggleControls:function(e){var t=this.elements.controls;if(t&&this.config.hideControls){var n=this.touch&&this.lastSeekTime+2e3>Date.now();this.toggleControls(Boolean(e||this.loading||this.paused||t.pressed||t.hover||n))}}};function ln(e){var t=e;$e.string(t)||$e.nullOrUndefined(this.embed)||(t=this.embed.ratio),$e.string(t)||(t=this.config.ratio);var n=Be(t.split(":").map(Number),2),i=100/n[0]*n[1];if(this.elements.wrapper.style.paddingBottom="".concat(i,"%"),this.isVimeo&&this.supported.ui){var r=(240-i)/4.8;this.media.style.transform="translateY(-".concat(r,"%)")}return{padding:i,ratio:t}}var cn=function(){function e(t){Re(this,e),this.player=t,this.lastKey=null,this.focusTimer=null,this.lastKeyDown=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.setTabFocus=this.setTabFocus.bind(this),this.firstTouch=this.firstTouch.bind(this)}return Fe(e,[{key:"handleKey",value:function(e){var t=this.player,n=t.elements,i=e.keyCode?e.keyCode:e.which,r="keydown"===e.type,a=r&&i===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&$e.number(i)){if(r){var s=document.activeElement;if($e.element(s)){var o=t.config.selectors.editable;if(s!==n.inputs.seek&&mt(s,o))return;if(32===e.which&&mt(s,'button, [role^="menuitem"]'))return}switch([32,37,38,39,40,48,49,50,51,52,53,54,56,57,67,70,73,75,76,77,79].includes(i)&&(e.preventDefault(),e.stopPropagation()),i){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:a||(t.currentTime=t.duration/10*(i-48));break;case 32:case 75:a||t.togglePlay();break;case 38:t.increaseVolume(.1);break;case 40:t.decreaseVolume(.1);break;case 77:a||(t.muted=!t.muted);break;case 39:t.forward();break;case 37:t.rewind();break;case 70:t.fullscreen.toggle();break;case 67:a||t.toggleCaptions();break;case 76:t.loop=!t.loop}27===i&&!t.fullscreen.usingNative&&t.fullscreen.active&&t.fullscreen.toggle(),this.lastKey=i}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){Wt.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){var e=this.player,t=e.elements;e.touch=!0,ht(t.container,e.config.classNames.isTouch,!0)}},{key:"setTabFocus",value:function(e){var t=this.player,n=t.elements;if(clearTimeout(this.focusTimer),"keydown"!==e.type||9===e.which){"keydown"===e.type&&(this.lastKeyDown=e.timeStamp);var i,r=e.timeStamp-this.lastKeyDown<=20;if("focus"!==e.type||r)i=t.config.classNames.tabFocus,ht(ft.call(t,".".concat(i)),i,!1),this.focusTimer=setTimeout(function(){var e=document.activeElement;n.container.contains(e)&&ht(document.activeElement,t.config.classNames.tabFocus,!0)},10)}}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.player;t.config.keyboard.global&&Qe.call(t,window,"keydown keyup",this.handleKey,e,!1),Qe.call(t,document.body,"click",this.toggleMenu,e),tt.call(t,document.body,"touchstart",this.firstTouch),Qe.call(t,document.body,"keydown focus blur",this.setTabFocus,e,!1,!0)}},{key:"container",value:function(){var e=this.player,t=e.config,n=e.elements,i=e.timers;!t.keyboard.global&&t.keyboard.focused&&Ze.call(e,n.container,"keydown keyup",this.handleKey,!1),Ze.call(e,n.container,"mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",function(t){var r=n.controls;r&&"enterfullscreen"===t.type&&(r.pressed=!1,r.hover=!1);var a=0;["touchstart","touchmove","mousemove"].includes(t.type)&&(on.toggleControls.call(e,!0),a=e.touch?3e3:2e3),clearTimeout(i.controls),i.controls=setTimeout(function(){return on.toggleControls.call(e,!1)},a)});var r=function(t){if(!t)return ln.call(e);var i=n.container.getBoundingClientRect(),r=i.width,a=i.height;return ln.call(e,"".concat(r,":").concat(a))},a=function(){window.clearTimeout(i.resized),i.resized=window.setTimeout(r,50)};Ze.call(e,n.container,"enterfullscreen exitfullscreen",function(t){var i=e.fullscreen,s=i.target,o=i.usingNative;if(e.isEmbed&&s===n.container){var l="enterfullscreen"===t.type,c=r(l);c.padding;!function(t,n,i){if(e.isVimeo){var r=e.elements.wrapper.firstChild,a=Be(t.split(":").map(Number),2)[1],s=Be(e.embed.ratio.split(":").map(Number),2),o=s[0],l=s[1];r.style.maxWidth=i?"".concat(a/l*o,"px"):null,r.style.margin=i?"0 auto":null}}(c.ratio,0,l),o||(l?Ze.call(e,window,"resize",a):et.call(e,window,"resize",a))}})}},{key:"media",value:function(){var e=this,t=this.player,n=t.elements;if(Ze.call(t,t.media,"timeupdate seeking seeked",function(e){return Wt.timeUpdate.call(t,e)}),Ze.call(t,t.media,"durationchange loadeddata loadedmetadata",function(e){return Wt.durationUpdate.call(t,e)}),Ze.call(t,t.media,"canplay loadeddata",function(){dt(n.volume,!t.hasAudio),dt(n.buttons.mute,!t.hasAudio)}),Ze.call(t,t.media,"ended",function(){t.isHTML5&&t.isVideo&&t.config.resetOnEnd&&t.restart()}),Ze.call(t,t.media,"progress playing seeking seeked",function(e){return Wt.updateProgress.call(t,e)}),Ze.call(t,t.media,"volumechange",function(e){return Wt.updateVolume.call(t,e)}),Ze.call(t,t.media,"playing play pause ended emptied timeupdate",function(e){return on.checkPlaying.call(t,e)}),Ze.call(t,t.media,"waiting canplay seeked playing",function(e){return on.checkLoading.call(t,e)}),Ze.call(t,t.media,"playing",function(){t.ads&&t.ads.enabled&&!t.ads.initialized&&t.ads.managerPromise.then(function(){return t.ads.play()}).catch(function(){return t.play()})}),t.supported.ui&&t.config.clickToPlay&&!t.isAudio){var i=gt.call(t,".".concat(t.config.classNames.video));if(!$e.element(i))return;Ze.call(t,n.container,"click",function(r){([n.container,i].includes(r.target)||i.contains(r.target))&&(t.touch&&t.config.hideControls||(t.ended?(e.proxy(r,t.restart,"restart"),e.proxy(r,t.play,"play")):e.proxy(r,t.togglePlay,"play")))})}t.supported.ui&&t.config.disableContextMenu&&Ze.call(t,n.wrapper,"contextmenu",function(e){e.preventDefault()},!1),Ze.call(t,t.media,"volumechange",function(){t.storage.set({volume:t.volume,muted:t.muted})}),Ze.call(t,t.media,"ratechange",function(){Wt.updateSetting.call(t,"speed"),t.storage.set({speed:t.speed})}),Ze.call(t,t.media,"qualitychange",function(e){Wt.updateSetting.call(t,"quality",null,e.detail.quality)}),Ze.call(t,t.media,"ready qualitychange",function(){Wt.setDownloadLink.call(t)});var r=t.config.events.concat(["keyup","keydown"]).join(" ");Ze.call(t,t.media,r,function(e){var i=e.detail,r=void 0===i?{}:i;"error"===e.type&&(r=t.media.error),nt.call(t,n.container,e.type,!0,r)})}},{key:"proxy",value:function(e,t,n){var i=this.player,r=i.config.listeners[n],a=!0;$e.function(r)&&(a=r.call(i,e)),a&&$e.function(t)&&t.call(i,e)}},{key:"bind",value:function(e,t,n,i){var r=this,a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=this.player,o=s.config.listeners[i],l=$e.function(o);Ze.call(s,e,t,function(e){return r.proxy(e,n,i)},a&&!l)}},{key:"controls",value:function(){var e=this,t=this.player,n=t.elements,i=Et.isIE?"change":"input";if(n.buttons.play&&Array.from(n.buttons.play).forEach(function(n){e.bind(n,"click",t.togglePlay,"play")}),this.bind(n.buttons.restart,"click",t.restart,"restart"),this.bind(n.buttons.rewind,"click",t.rewind,"rewind"),this.bind(n.buttons.fastForward,"click",t.forward,"fastForward"),this.bind(n.buttons.mute,"click",function(){t.muted=!t.muted},"mute"),this.bind(n.buttons.captions,"click",function(){return t.toggleCaptions()}),this.bind(n.buttons.download,"click",function(){nt.call(t,t.media,"download")},"download"),this.bind(n.buttons.fullscreen,"click",function(){t.fullscreen.toggle()},"fullscreen"),this.bind(n.buttons.pip,"click",function(){t.pip="toggle"},"pip"),this.bind(n.buttons.airplay,"click",t.airplay,"airplay"),this.bind(n.buttons.settings,"click",function(e){e.stopPropagation(),Wt.toggleMenu.call(t,e)}),this.bind(n.buttons.settings,"keyup",function(e){var n=e.which;[13,32].includes(n)&&(13!==n?(e.preventDefault(),e.stopPropagation(),Wt.toggleMenu.call(t,e)):Wt.focusFirstMenuItem.call(t,null,!0))},null,!1),this.bind(n.settings.menu,"keydown",function(e){27===e.which&&Wt.toggleMenu.call(t,e)}),this.bind(n.inputs.seek,"mousedown mousemove",function(e){var t=n.progress.getBoundingClientRect(),i=100/t.width*(e.pageX-t.left);e.currentTarget.setAttribute("seek-value",i)}),this.bind(n.inputs.seek,"mousedown mouseup keydown keyup touchstart touchend",function(e){var n=e.currentTarget,i=e.keyCode?e.keyCode:e.which;if(!$e.keyboardEvent(e)||39===i||37===i){t.lastSeekTime=Date.now();var r=n.hasAttribute("play-on-seeked"),a=["mouseup","touchend","keyup"].includes(e.type);r&&a?(n.removeAttribute("play-on-seeked"),t.play()):!a&&t.playing&&(n.setAttribute("play-on-seeked",""),t.pause())}}),Et.isIos){var r=ft.call(t,'input[type="range"]');Array.from(r).forEach(function(t){return e.bind(t,i,function(e){return _t(e.target)})})}this.bind(n.inputs.seek,i,function(e){var n=e.currentTarget,i=n.getAttribute("seek-value");$e.empty(i)&&(i=n.value),n.removeAttribute("seek-value"),t.currentTime=i/n.max*t.duration},"seek"),this.bind(n.progress,"mouseenter mouseleave mousemove",function(e){return Wt.updateSeekTooltip.call(t,e)}),this.bind(n.progress,"mousemove touchmove",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startMove(e)}),this.bind(n.progress,"mouseleave click",function(){var e=t.previewThumbnails;e&&e.loaded&&e.endMove(!1,!0)}),this.bind(n.progress,"mousedown touchstart",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startScrubbing(e)}),this.bind(n.progress,"mouseup touchend",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.endScrubbing(e)}),Et.isWebkit&&Array.from(ft.call(t,'input[type="range"]')).forEach(function(n){e.bind(n,"input",function(e){return Wt.updateRangeFill.call(t,e.target)})}),t.config.toggleInvert&&!$e.element(n.display.duration)&&this.bind(n.display.currentTime,"click",function(){0!==t.currentTime&&(t.config.invertTime=!t.config.invertTime,Wt.timeUpdate.call(t))}),this.bind(n.inputs.volume,i,function(e){t.volume=e.target.value},"volume"),this.bind(n.controls,"mouseenter mouseleave",function(e){n.controls.hover=!t.touch&&"mouseenter"===e.type}),this.bind(n.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){n.controls.pressed=["mousedown","touchstart"].includes(e.type)}),this.bind(n.controls,"focusin",function(){var n=t.config,i=t.elements,r=t.timers;ht(i.controls,n.classNames.noTransition,!0),on.toggleControls.call(t,!0),setTimeout(function(){ht(i.controls,n.classNames.noTransition,!1)},0);var a=e.touch?3e3:4e3;clearTimeout(r.controls),r.controls=setTimeout(function(){return on.toggleControls.call(t,!1)},a)}),this.bind(n.inputs.volume,"wheel",function(e){var n=e.webkitDirectionInvertedFromDevice,i=Be([e.deltaX,-e.deltaY].map(function(e){return n?-e:e}),2),r=i[0],a=i[1],s=Math.sign(Math.abs(r)>Math.abs(a)?r:a);t.increaseVolume(s/50);var o=t.media.volume;(1===s&&o<1||-1===s&&o>0)&&e.preventDefault()},"volume",!1)}}]),e}(),un=t(function(e,t){e.exports=function(){var e=function(){},t={},n={},i={};function r(e,t){if(e){var r=i[e];if(n[e]=t,r)for(;r.length;)r[0](e,t),r.splice(0,1)}}function a(t,n){t.call&&(t={success:t}),n.length?(t.error||e)(n):(t.success||e)(t)}function s(t,n,i,r){var a,o,l=document,c=i.async,u=(i.numRetries||0)+1,d=i.before||e,h=t.replace(/^(css|img)!/,"");r=r||0,/(^css!|\.css$)/.test(t)?(a=!0,(o=l.createElement("link")).rel="stylesheet",o.href=h):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(o=l.createElement("img")).src=h:((o=l.createElement("script")).src=t,o.async=void 0===c||c),o.onload=o.onerror=o.onbeforeload=function(e){var l=e.type[0];if(a&&"hideFocus"in o)try{o.sheet.cssText.length||(l="e")}catch(e){18!=e.code&&(l="e")}if("e"==l&&(r+=1)<u)return s(t,n,i,r);n(t,l,e.defaultPrevented)},!1!==d(t,o)&&l.head.appendChild(o)}function o(e,n,i){var o,l;if(n&&n.trim&&(o=n),l=(o?i:n)||{},o){if(o in t)throw"LoadJS";t[o]=!0}!function(e,t,n){var i,r,a=(e=e.push?e:[e]).length,o=a,l=[];for(i=function(e,n,i){if("e"==n&&l.push(e),"b"==n){if(!i)return;l.push(e)}--a||t(l)},r=0;r<o;r++)s(e[r],i,n)}(e,function(e){a(l,e),r(o,e)},l)}return o.ready=function(e,t){return function(e,t){e=e.push?e:[e];var r,a,s,o=[],l=e.length,c=l;for(r=function(e,n){n.length&&o.push(e),--c||t(o)};l--;)a=e[l],(s=n[a])?r(a,s):(i[a]=i[a]||[]).push(r)}(e,function(e){a(t,e)}),o},o.done=function(e){r(e,[])},o.reset=function(){t={},n={},i={}},o.isDefined=function(e){return e in t},o}()});function dn(e){return new Promise(function(t,n){un(e,{success:t,error:n})})}function hn(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,nt.call(this,this.media,e?"play":"pause"))}var pn={setup:function(){var e=this;ht(this.elements.wrapper,this.config.classNames.embed,!0),ln.call(this),$e.object(window.Vimeo)?pn.ready.call(this):dn(this.config.urls.vimeo.sdk).then(function(){pn.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},ready:function(){var e=this,t=this,n=t.config.vimeo,i=Xt(Ot({},{loop:t.config.loop.active,autoplay:t.autoplay,muted:t.muted,gesture:"media",playsinline:!this.config.fullscreen.iosNative},n)),r=t.media.getAttribute("src");$e.empty(r)&&(r=t.media.getAttribute(t.config.attributes.embed.id));var a,s=(a=r,$e.empty(a)?null:$e.number(Number(a))?a:a.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:a),o=at("iframe"),l=Mt(t.config.urls.vimeo.iframe,s,i);o.setAttribute("src",l),o.setAttribute("allowfullscreen",""),o.setAttribute("allowtransparency",""),o.setAttribute("allow","autoplay");var c=at("div",{poster:t.poster,class:t.config.classNames.embedContainer});c.appendChild(o),t.media=ct(c,t.media),Ht(Mt(t.config.urls.vimeo.api,s),"json").then(function(e){if(!$e.empty(e)){var n=new URL(e[0].thumbnail_large);n.pathname="".concat(n.pathname.split("_")[0],".jpg"),on.setPoster.call(t,n.href).catch(function(){})}}),t.embed=new window.Vimeo.Player(o,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){return hn.call(t,!0),t.embed.play()},t.media.pause=function(){return hn.call(t,!1),t.embed.pause()},t.media.stop=function(){t.pause(),t.currentTime=0};var u=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return u},set:function(e){var n=t.embed,i=t.media,r=t.paused,a=t.volume,s=r&&!n.hasPlayed;i.seeking=!0,nt.call(t,i,"seeking"),Promise.resolve(s&&n.setVolume(0)).then(function(){return n.setCurrentTime(e)}).then(function(){return s&&n.pause()}).then(function(){return s&&n.setVolume(a)}).catch(function(){})}});var d=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return d},set:function(e){t.embed.setPlaybackRate(e).then(function(){d=e,nt.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&Wt.setSpeedMenu.call(t,[])})}});var h=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return h},set:function(e){t.embed.setVolume(e).then(function(){h=e,nt.call(t,t.media,"volumechange")})}});var p=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return p},set:function(e){var n=!!$e.boolean(e)&&e;t.embed.setVolume(n?0:t.config.volume).then(function(){p=n,nt.call(t,t.media,"volumechange")})}});var m,f=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return f},set:function(e){var n=$e.boolean(e)?e:t.config.loop.active;t.embed.setLoop(n).then(function(){f=n})}}),t.embed.getVideoUrl().then(function(e){m=e,Wt.setDownloadLink.call(t)}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return m}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(n){var i=Be(n,2),r=i[0],a=i[1];t.embed.ratio="".concat(r,":").concat(a),ln.call(e,t.embed.ratio)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(n){t.config.title=n,on.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){u=e,nt.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,nt.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,Yt.setup.call(t)}),t.embed.on("cuechange",function(e){var n=e.cues,i=(void 0===n?[]:n).map(function(e){return t=e.text,n=document.createDocumentFragment(),i=document.createElement("div"),n.appendChild(i),i.innerHTML=t,n.firstChild.innerText;var t,n,i});Yt.updateCues.call(t,i)}),t.embed.on("loaded",function(){(t.embed.getPaused().then(function(e){hn.call(t,!e),e||nt.call(t,t.media,"playing")}),$e.element(t.embed.element)&&t.supported.ui)&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){hn.call(t,!0),nt.call(t,t.media,"playing")}),t.embed.on("pause",function(){hn.call(t,!1)}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,u=e.seconds,nt.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,nt.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&nt.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,nt.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,nt.call(t,t.media,"seeked")}),t.embed.on("ended",function(){t.media.paused=!0,nt.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,nt.call(t,t.media,"error")}),setTimeout(function(){return on.build.call(t)},0)}};function mn(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,nt.call(this,this.media,e?"play":"pause"))}var fn,gn,vn,yn={setup:function(){var e=this;ht(this.elements.wrapper,this.config.classNames.embed,!0),ln.call(this),$e.object(window.YT)&&$e.function(window.YT.Player)?yn.ready.call(this):(dn(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){yn.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if($e.function(this.embed.getVideoData)){var n=this.embed.getVideoData().title;if($e.empty(n))return this.config.title=n,void on.setTitle.call(this)}var i=this.config.keys.google;$e.string(i)&&!$e.empty(i)&&Ht(Mt(this.config.urls.youtube.api,e,i)).then(function(e){$e.object(e)&&(t.config.title=e.items[0].snippet.title,on.setTitle.call(t))}).catch(function(){})},ready:function(){var e=this,t=e.media.getAttribute("id");if($e.empty(t)||!t.startsWith("youtube-")){var n=e.media.getAttribute("src");$e.empty(n)&&(n=e.media.getAttribute(this.config.attributes.embed.id));var i,r,a=(i=n,$e.empty(i)?null:i.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:i),s=(r=e.provider,"".concat(r,"-").concat(Math.floor(1e4*Math.random()))),o=at("div",{id:s,poster:e.poster});e.media=ct(o,e.media);var l=function(e){return"https://img.youtube.com/vi/".concat(a,"/").concat(e,"default.jpg")};sn(l("maxres"),121).catch(function(){return sn(l("sd"),121)}).catch(function(){return sn(l("hq"))}).then(function(t){return on.setPoster.call(e,t.src)}).then(function(t){t.includes("maxres")||(e.elements.poster.style.backgroundSize="cover")}).catch(function(){});var c=e.config.youtube;e.embed=new window.YT.Player(s,{videoId:a,host:c.noCookie?"https://www.youtube-nocookie.com":void 0,playerVars:Ot({},{autoplay:e.config.autoplay?1:0,hl:e.config.hl,controls:e.supported.ui?0:1,disablekb:1,playsinline:e.config.fullscreen.iosNative?0:1,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language,widget_referrer:window?window.location.href:null},c),events:{onError:function(t){if(!e.media.error){var n=t.data,i={2:"The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.",5:"The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",100:"The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.",101:"The owner of the requested video does not allow it to be played in embedded players.",150:"The owner of the requested video does not allow it to be played in embedded players."}[n]||"An unknown error occured";e.media.error={code:n,message:i},nt.call(e,e.media,"error")}},onPlaybackRateChange:function(t){var n=t.target;e.media.playbackRate=n.getPlaybackRate(),nt.call(e,e.media,"ratechange")},onReady:function(t){if(!$e.function(e.media.play)){var n=t.target;yn.getTitle.call(e,a),e.media.play=function(){mn.call(e,!0),n.playVideo()},e.media.pause=function(){mn.call(e,!1),n.pauseVideo()},e.media.stop=function(){n.stopVideo()},e.media.duration=n.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(n.getCurrentTime())},set:function(t){e.paused&&!e.embed.hasPlayed&&e.embed.mute(),e.media.seeking=!0,nt.call(e,e.media,"seeking"),n.seekTo(t)}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return n.getPlaybackRate()},set:function(e){n.setPlaybackRate(e)}});var i=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return i},set:function(t){i=t,n.setVolume(100*i),nt.call(e,e.media,"volumechange")}});var r=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return r},set:function(t){var i=$e.boolean(t)?t:r;r=i,n[i?"mute":"unMute"](),nt.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return n.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=n.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),nt.call(e,e.media,"timeupdate"),nt.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=n.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&nt.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),nt.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return on.build.call(e)},50)}},onStateChange:function(t){var n=t.target;switch(clearInterval(e.timers.playing),e.media.seeking&&[1,2].includes(t.data)&&(e.media.seeking=!1,nt.call(e,e.media,"seeked")),t.data){case-1:nt.call(e,e.media,"timeupdate"),e.media.buffered=n.getVideoLoadedFraction(),nt.call(e,e.media,"progress");break;case 0:mn.call(e,!1),e.media.loop?(n.stopVideo(),n.playVideo()):nt.call(e,e.media,"ended");break;case 1:e.media.paused&&!e.embed.hasPlayed?e.media.pause():(mn.call(e,!0),nt.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){nt.call(e,e.media,"timeupdate")},50),e.media.duration!==n.getDuration()&&(e.media.duration=n.getDuration(),nt.call(e,e.media,"durationchange")));break;case 2:e.muted||e.embed.unMute(),mn.call(e,!1)}nt.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},bn={setup:function(){this.media?(ht(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),ht(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&ht(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=at("div",{class:this.config.classNames.video}),it(this.media,this.elements.wrapper),this.elements.poster=at("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isHTML5?xt.extend.call(this):this.isYouTube?yn.setup.call(this):this.isVimeo&&pn.setup.call(this)):this.debug.warn("No media element found!")}},kn=function(){function e(t){var n=this;Re(this,e),this.player=t,this.config=t.config.ads,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){n.on("loaded",e),n.on("error",t)}),this.load()}return Fe(e,[{key:"load",value:function(){var e=this;this.enabled&&($e.object(window.google)&&$e.object(window.google.ima)?this.ready():dn(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=at("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var n=new google.ima.AdsRequest;n.adTagUrl=this.tagUrl,n.linearAdSlotWidth=t.offsetWidth,n.linearAdSlotHeight=t.offsetHeight,n.nonLinearAdSlotWidth=t.offsetWidth,n.nonLinearAdSlotHeight=t.offsetHeight,n.forceNonLinearFullSlot=!1,n.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(n)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=zt(Math.max(e.manager.getRemainingTime(),0)),n="".concat(Dt("advertisement",e.player.config)," - ").concat(t);e.elements.container.setAttribute("data-badge-text",n)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this;if(this.enabled){var n=new google.ima.AdsRenderingSettings;n.restoreCustomPlaybackStateOnAdBreakComplete=!0,n.enablePreloading=!0,this.manager=e.getAdsManager(this.player,n),this.cuePoints=this.manager.getCuePoints(),$e.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var n=t.player.elements.progress;if($e.element(n)){var i=100/t.player.duration*e,r=at("span",{class:t.player.config.classNames.cues});r.style.left="".concat(i.toString(),"%"),n.appendChild(r)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}}},{key:"onAdEvent",value:function(e){var t=this,n=this.player.elements.container,i=e.getAd(),r=e.getAdData(),a=function(e){var n="ads".concat(e.replace(/_/g,"").toLowerCase());nt.call(t.player,t.player.media,n)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),a(e.type),this.pollCountdown(!0),i.isLinear()||(i.width=n.offsetWidth,i.height=n.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:a(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:a(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:a(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:a(e.type);break;case google.ima.AdEvent.Type.LOG:r.adError&&this.player.debug.warn("Non-fatal ad error: ".concat(r.adError.getMessage()))}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e,t=this,n=this.player.elements.container;this.player.on("ended",function(){t.loader.contentComplete()}),this.player.on("timeupdate",function(){e=t.player.currentTime}),this.player.on("seeked",function(){var n=t.player.currentTime;$e.empty(t.cuePoints)||t.cuePoints.forEach(function(i,r){e<i&&i<n&&(t.manager.discardAdBreak(),t.cuePoints.splice(r,1))})}),window.addEventListener("resize",function(){t.manager&&t.manager.resize(n.offsetWidth,n.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,n=arguments.length,i=new Array(n>1?n-1:0),r=1;r<n;r++)i[r-1]=arguments[r];var a=this.events[e];$e.array(a)&&a.forEach(function(e){$e.function(e)&&e.apply(t,i)})}},{key:"on",value:function(e,t){return $e.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var n=this;this.player.debug.log("Safety timer invoked from: ".concat(t)),this.safetyTimer=setTimeout(function(){n.cancel(),n.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){$e.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: ".concat(e)),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){var e=this.config;return this.player.isHTML5&&this.player.isVideo&&e.enabled&&(!$e.empty(e.publisherId)||$e.url(e.tagUrl))}},{key:"tagUrl",get:function(){var e=this.config;if($e.url(e.tagUrl))return e.tagUrl;var t={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:window.location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"".concat("https://go.aniview.com/api/adserver6/vast/","?").concat(Xt(t))}}]),e}(),wn=function(){function e(t){Re(this,e),this.player=t,this.thumbnails=[],this.loaded=!1,this.lastMouseMoveTime=Date.now(),this.mouseDown=!1,this.loadedImages=[],this.elements={thumb:{},scrubbing:{}},this.load()}return Fe(e,[{key:"load",value:function(){var e=this;this.player.elements.display.seekTooltip&&(this.player.elements.display.seekTooltip.hidden=this.enabled),this.enabled&&this.getThumbnails().then(function(){e.render(),e.determineContainerAutoSizing(),e.loaded=!0})}},{key:"getThumbnails",value:function(){var e=this;return new Promise(function(t){var n=e.player.config.previewThumbnails.src;if($e.empty(n))throw new Error("Missing previewThumbnails.src config attribute");var i=($e.string(n)?[n]:n).map(function(t){return e.getThumbnail(t)});Promise.all(i).then(function(){e.thumbnails.sort(function(e,t){return e.height-t.height}),e.player.debug.log("Preview thumbnails",e.thumbnails),t()})})}},{key:"getThumbnail",value:function(e){var t=this;return new Promise(function(n){Ht(e).then(function(i){var r,a,s={frames:(r=i,a=[],r.split(/\r\n\r\n|\n\n|\r\r/).forEach(function(e){var t={};e.split(/\r\n|\n|\r/).forEach(function(e){if($e.number(t.startTime)){if(!$e.empty(e.trim())&&$e.empty(t.text)){var n=e.trim().split("#xywh="),i=Be(n,1);if(t.text=i[0],n[1]){var r=Be(n[1].split(","),4);t.x=r[0],t.y=r[1],t.w=r[2],t.h=r[3]}}}else{var a=e.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);a&&(t.startTime=60*Number(a[1])*60+60*Number(a[2])+Number(a[3])+Number("0.".concat(a[4])),t.endTime=60*Number(a[6])*60+60*Number(a[7])+Number(a[8])+Number("0.".concat(a[9])))}}),t.text&&a.push(t)}),a),height:null,urlPrefix:""};s.frames[0].text.startsWith("/")||(s.urlPrefix=e.substring(0,e.lastIndexOf("/")+1));var o=new Image;o.onload=function(){s.height=o.naturalHeight,s.width=o.naturalWidth,t.thumbnails.push(s),n()},o.src=s.urlPrefix+s.frames[0].text})})}},{key:"startMove",value:function(e){if(this.loaded&&$e.event(e)&&["touchmove","mousemove"].includes(e.type)&&this.player.media.duration){if("touchmove"===e.type)this.seekTime=this.player.media.duration*(this.player.elements.inputs.seek.value/100);else{var t=this.player.elements.progress.getBoundingClientRect(),n=100/t.width*(e.pageX-t.left);this.seekTime=this.player.media.duration*(n/100),this.seekTime<0&&(this.seekTime=0),this.seekTime>this.player.media.duration-1&&(this.seekTime=this.player.media.duration-1),this.mousePosX=e.pageX,this.elements.thumb.time.innerText=zt(this.seekTime)}this.showImageAtCurrentTime()}}},{key:"endMove",value:function(){this.toggleThumbContainer(!1,!0)}},{key:"startScrubbing",value:function(e){!1!==e.button&&0!==e.button||(this.mouseDown=!0,this.player.media.duration&&(this.toggleScrubbingContainer(!0),this.toggleThumbContainer(!1,!0),this.showImageAtCurrentTime()))}},{key:"finishScrubbing",value:function(){var e=this;this.mouseDown=!1,Math.ceil(this.lastTime)===Math.ceil(this.player.media.currentTime)?this.toggleScrubbingContainer(!1):tt.call(this.player,this.player.media,"timeupdate",function(){e.mouseDown||e.toggleScrubbingContainer(!1)})}},{key:"listeners",value:function(){var e=this;this.player.on("play",function(){e.toggleThumbContainer(!1,!0)}),this.player.on("seeked",function(){e.toggleThumbContainer(!1)}),this.player.on("timeupdate",function(){e.lastTime=e.player.media.currentTime})}},{key:"render",value:function(){this.elements.thumb.container=at("div",{class:this.player.config.classNames.previewThumbnails.thumbContainer}),this.elements.thumb.imageContainer=at("div",{class:this.player.config.classNames.previewThumbnails.imageContainer}),this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);var e=at("div",{class:this.player.config.classNames.previewThumbnails.timeContainer});this.elements.thumb.time=at("span",{},"00:00"),e.appendChild(this.elements.thumb.time),this.elements.thumb.container.appendChild(e),this.player.elements.progress.appendChild(this.elements.thumb.container),this.elements.scrubbing.container=at("div",{class:this.player.config.classNames.previewThumbnails.scrubbingContainer}),this.player.elements.wrapper.appendChild(this.elements.scrubbing.container)}},{key:"showImageAtCurrentTime",value:function(){var e=this;this.mouseDown?this.setScrubbingContainerSize():(this.toggleThumbContainer(!0),this.setThumbContainerSizeAndPos());var t=this.thumbnails[0].frames.findIndex(function(t){return e.seekTime>=t.startTime&&e.seekTime<=t.endTime}),n=t>=0,i=0;this.toggleThumbContainer(n),n&&(this.thumbnails.forEach(function(n,r){e.loadedImages.includes(n.frames[t].text)&&(i=r)}),t!==this.showingThumb&&(this.showingThumb=t,this.loadImage(i)))}},{key:"loadImage",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=this.showingThumb,i=this.thumbnails[t],r=i.urlPrefix,a=i.frames[n],s=i.frames[n].text,o=r+s;if(this.currentImageElement&&this.currentImageElement.dataset.filename===s)this.showImage(this.currentImageElement,a,t,n,s,!1),this.currentImageElement.dataset.index=n,this.removeOldImages(this.currentImageElement);else{this.loadingImage&&this.usingSprites&&(this.loadingImage.onload=null);var l=new Image;l.src=o,l.dataset.index=n,l.dataset.filename=s,this.showingThumbFilename=s,this.player.debug.log("Loading image: ".concat(o)),l.onload=function(){return e.showImage(l,a,t,n,s,!0)},this.loadingImage=l,this.removeOldImages(l)}}},{key:"showImage",value:function(e,t,n,i,r){var a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];this.player.debug.log("Showing thumb: ".concat(r,". num: ").concat(i,". qual: ").concat(n,". newimg: ").concat(a)),this.setImageSizeAndOffset(e,t),a&&(this.currentImageContainer.appendChild(e),this.currentImageElement=e,this.loadedImages.includes(r)||this.loadedImages.push(r)),this.preloadNearby(i,!0).then(this.preloadNearby(i,!1)).then(this.getHigherQuality(n,e,t,r))}},{key:"removeOldImages",value:function(e){var t=this;Array.from(this.currentImageContainer.children).forEach(function(n){if("img"===n.tagName.toLowerCase()){var i=t.usingSprites?500:1e3;if(n.dataset.index!==e.dataset.index&&!n.dataset.deleting){n.dataset.deleting=!0;var r=t.currentImageContainer;setTimeout(function(){r.removeChild(n),t.player.debug.log("Removing thumb: ".concat(n.dataset.filename))},i)}}})}},{key:"preloadNearby",value:function(e){var t=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return new Promise(function(i){setTimeout(function(){var r=t.thumbnails[0].frames[e].text;if(t.showingThumbFilename===r){var a;a=n?t.thumbnails[0].frames.slice(e):t.thumbnails[0].frames.slice(0,e).reverse();var s=!1;a.forEach(function(e){var n=e.text;if(n!==r&&!t.loadedImages.includes(n)){s=!0,t.player.debug.log("Preloading thumb filename: ".concat(n));var a=t.thumbnails[0].urlPrefix+n,o=new Image;o.src=a,o.onload=function(){t.player.debug.log("Preloaded thumb filename: ".concat(n)),t.loadedImages.includes(n)||t.loadedImages.push(n),i()}}}),s||i()}},300)})}},{key:"getHigherQuality",value:function(e,t,n,i){var r=this;if(e<this.thumbnails.length-1){var a=t.naturalHeight;this.usingSprites&&(a=n.h),a<this.thumbContainerHeight&&setTimeout(function(){r.showingThumbFilename===i&&(r.player.debug.log("Showing higher quality thumb for: ".concat(i)),r.loadImage(e+1))},300)}}},{key:"toggleThumbContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.player.config.classNames.previewThumbnails.thumbContainerShown;this.elements.thumb.container.classList.toggle(n,e),!e&&t&&(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"toggleScrubbingContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.player.config.classNames.previewThumbnails.scrubbingContainerShown;this.elements.scrubbing.container.classList.toggle(t,e),e||(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"determineContainerAutoSizing",value:function(){this.elements.thumb.imageContainer.clientHeight>20&&(this.sizeSpecifiedInCSS=!0)}},{key:"setThumbContainerSizeAndPos",value:function(){if(!this.sizeSpecifiedInCSS){var e=Math.floor(this.thumbContainerHeight*this.thumbAspectRatio);this.elements.thumb.imageContainer.style.height="".concat(this.thumbContainerHeight,"px"),this.elements.thumb.imageContainer.style.width="".concat(e,"px")}this.setThumbContainerPos()}},{key:"setThumbContainerPos",value:function(){var e=this.player.elements.progress.getBoundingClientRect(),t=this.player.elements.container.getBoundingClientRect(),n=this.elements.thumb.container,i=t.left-e.left+10,r=t.right-e.left-n.clientWidth-10,a=this.mousePosX-e.left-n.clientWidth/2;a<i&&(a=i),a>r&&(a=r),n.style.left="".concat(a,"px")}},{key:"setScrubbingContainerSize",value:function(){this.elements.scrubbing.container.style.width="".concat(this.player.media.clientWidth,"px"),this.elements.scrubbing.container.style.height="".concat(this.player.media.clientWidth/this.thumbAspectRatio,"px")}},{key:"setImageSizeAndOffset",value:function(e,t){if(this.usingSprites){var n=this.thumbContainerHeight/t.h;e.style.height="".concat(Math.floor(e.naturalHeight*n),"px"),e.style.width="".concat(Math.floor(e.naturalWidth*n),"px"),e.style.left="-".concat(t.x*n,"px"),e.style.top="-".concat(t.y*n,"px")}}},{key:"enabled",get:function(){return this.player.isHTML5&&this.player.isVideo&&this.player.config.previewThumbnails.enabled}},{key:"currentImageContainer",get:function(){return this.mouseDown?this.elements.scrubbing.container:this.elements.thumb.imageContainer}},{key:"usingSprites",get:function(){return Object.keys(this.thumbnails[0].frames[0]).includes("w")}},{key:"thumbAspectRatio",get:function(){return this.usingSprites?this.thumbnails[0].frames[0].w/this.thumbnails[0].frames[0].h:this.thumbnails[0].width/this.thumbnails[0].height}},{key:"thumbContainerHeight",get:function(){return this.mouseDown?Math.floor(this.player.media.clientWidth/this.thumbAspectRatio):Math.floor(this.player.media.clientWidth/this.thumbAspectRatio/4)}},{key:"currentImageElement",get:function(){return this.mouseDown?this.currentScrubbingImageElement:this.currentThumbnailImageElement},set:function(e){this.mouseDown?this.currentScrubbingImageElement=e:this.currentThumbnailImageElement=e}}]),e}(),_n={insertElements:function(e,t){var n=this;$e.string(t)?st(e,this.media,{src:t}):$e.array(t)&&t.forEach(function(t){st(e,n.media,t)})},change:function(e){var t=this;Pt(e,"sources.length")?(xt.cancelRequests.call(this),this.destroy.call(this,function(){t.options.quality=[],ot(t.media),t.media=null,$e.element(t.elements.container)&&t.elements.container.removeAttribute("class");var n=e.sources,i=e.type,r=Be(n,1)[0],a=r.provider,s=void 0===a?Qt.html5:a,o=r.src,l="html5"===s?i:"div",c="html5"===s?{}:{src:o};Object.assign(t,{provider:s,type:i,supported:St.check(i,s,t.config.playsinline),media:at(l,c)}),t.elements.container.appendChild(t.media),$e.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),$e.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),on.addStyleHook.call(t),t.isHTML5&&_n.insertElements.call(t,"source",n),t.config.title=e.title,bn.setup.call(t),t.isHTML5&&Object.keys(e).includes("tracks")&&_n.insertElements.call(t,"track",e.tracks),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&on.build.call(t),t.isHTML5&&t.media.load(),t.previewThumbnails&&t.previewThumbnails.load(),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},Tn=function(){function e(t,n){var i=this;if(Re(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=St.touch,this.media=t,$e.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||$e.nodeList(this.media)||$e.array(this.media))&&(this.media=this.media[0]),this.config=Ot({},Jt,e.defaults,n||{},function(){try{return JSON.parse(i.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,captions:null,buttons:{},display:{},progress:{},inputs:{},settings:{popup:null,menu:null,panels:{},buttons:{}}},this.captions={active:null,currentTrack:-1,meta:new WeakMap},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new tn(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",St),!$e.nullOrUndefined(this.media)&&$e.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(St.check().api){var r=this.media.cloneNode(!0);r.autoplay=!1,this.elements.original=r;var a=this.media.tagName.toLowerCase(),s=null,o=null;switch(a){case"div":if(s=this.media.querySelector("iframe"),$e.element(s)){if(o=Kt(s.getAttribute("src")),this.provider=function(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e)?Qt.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?Qt.vimeo:null}(o.toString()),this.elements.container=this.media,this.media=s,this.elements.container.className="",o.search.length){var l=["1","true"];l.includes(o.searchParams.get("autoplay"))&&(this.config.autoplay=!0),l.includes(o.searchParams.get("loop"))&&(this.config.loop.active=!0),this.isYouTube?(this.config.playsinline=l.includes(o.searchParams.get("playsinline")),this.config.youtube.hl=o.searchParams.get("hl")):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if($e.empty(this.provider)||!Object.keys(Qt).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=Zt.video;break;case"video":case"audio":this.type=a,this.provider=Qt.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),(this.media.hasAttribute("playsinline")||this.media.hasAttribute("webkit-playsinline"))&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=St.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.eventListeners=[],this.listeners=new cn(this),this.storage=new Ft(this),this.media.plyr=this,$e.element(this.elements.container)||(this.elements.container=at("div",{tabindex:0}),it(this.media,this.elements.container)),on.addStyleHook.call(this),bn.setup.call(this),this.config.debug&&Ze.call(this,this.elements.container,this.config.events.join(" "),function(e){i.debug.log("event: ".concat(e.type))}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&on.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new an(this),this.config.ads.enabled&&(this.ads=new kn(this)),this.config.autoplay&&this.play(),this.lastSeekTime=0,this.config.previewThumbnails.enabled&&(this.previewThumbnails=new wn(this))):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return Fe(e,[{key:"play",value:function(){return $e.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&$e.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){($e.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):$e.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-($e.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+($e.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+($e.number(e)?e:0)}},{key:"decreaseVolume",value:function(e){this.increaseVolume(-e)}},{key:"toggleCaptions",value:function(e){Yt.toggle.call(this,e,!1)}},{key:"airplay",value:function(){St.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){if(this.supported.ui&&!this.isAudio){var t=pt(this.elements.container,this.config.classNames.hideControls),n=void 0===e?void 0:!e,i=ht(this.elements.container,this.config.classNames.hideControls,n);if(i&&this.config.controls.includes("settings")&&!$e.empty(this.config.settings)&&Wt.toggleMenu.call(this,!1),i!==t){var r=i?"controlshidden":"controlsshown";nt.call(this,this.media,r)}return!i}return!1}},{key:"on",value:function(e,t){Ze.call(this,this.elements.container,e,t)}},{key:"once",value:function(e,t){tt.call(this,this.elements.container,e,t)}},{key:"off",value:function(e,t){et(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var i=function(){document.body.style.overflow="",t.embed=null,n?(Object.keys(t.elements).length&&(ot(t.elements.buttons.play),ot(t.elements.captions),ot(t.elements.controls),ot(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),$e.function(e)&&e()):(function(){this&&this.eventListeners&&(this.eventListeners.forEach(function(e){var t=e.element,n=e.type,i=e.callback,r=e.options;t.removeEventListener(n,i,r)}),this.eventListeners=[])}.call(t),ct(t.elements.original,t.elements.container),nt.call(t,t.elements.original,"destroyed",!0),$e.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};this.stop(),this.isHTML5?(clearTimeout(this.timers.loading),on.toggleNativeControls.call(this,!0),i()):this.isYouTube?(clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&$e.function(this.embed.destroy)&&this.embed.destroy(),i()):this.isVimeo&&(null!==this.embed&&this.embed.unload().then(i),setTimeout(i,200))}}},{key:"supports",value:function(e){return St.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===Qt.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===Qt.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===Qt.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===Zt.video)}},{key:"isAudio",get:function(){return Boolean(this.type===Zt.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){if(this.duration){var t=$e.number(e)&&e>0;this.media.currentTime=t?Math.min(e,this.duration):0,this.debug.log("Seeking to ".concat(this.currentTime," seconds"))}},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return $e.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=(this.media||{}).duration,n=$e.number(t)&&t!==1/0?t:0;return e||n}},{key:"volume",set:function(e){var t=e;$e.string(t)&&(t=Number(t)),$e.number(t)||(t=this.storage.get("volume")),$e.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!$e.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;$e.boolean(t)||(t=this.storage.get("muted")),$e.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;$e.number(e)&&(t=e),$e.number(t)||(t=this.storage.get("speed")),$e.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed (".concat(t,")"))},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=this.config.quality,n=this.options.quality;if(n.length){var i=[!$e.empty(e)&&Number(e),this.storage.get("quality"),t.selected,t.default].find($e.number),r=!0;if(!n.includes(i)){var a=function(e,t){return $e.array(e)&&e.length?e.reduce(function(e,n){return Math.abs(n-t)<Math.abs(e-t)?n:e}):null}(n,i);this.debug.warn("Unsupported quality option: ".concat(i,", using ").concat(a," instead")),i=a,r=!1}t.selected=i,this.media.quality=i,r&&this.storage.set({quality:i})}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=$e.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){_n.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"download",get:function(){var e=this.config.urls.download;return $e.url(e)?e:this.source}},{key:"poster",set:function(e){this.isVideo?on.setPoster.call(this,e,!1).catch(function(){}):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=$e.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"currentTrack",set:function(e){Yt.set.call(this,e,!1)},get:function(){var e=this.captions,t=e.toggled,n=e.currentTrack;return t?n:-1}},{key:"language",set:function(e){Yt.setLanguage.call(this,e,!1)},get:function(){return(Yt.getCurrentTrack.call(this)||{}).language}},{key:"pip",set:function(e){if(St.pip){var t=$e.boolean(e)?e:!this.pip;$e.function(this.media.webkitSetPresentationMode)&&this.media.webkitSetPresentationMode(t?$t:Gt),$e.function(this.media.requestPictureInPicture)&&(!this.pip&&t?this.media.requestPictureInPicture():this.pip&&!t&&document.exitPictureInPicture())}},get:function(){return St.pip?$e.empty(this.media.webkitPresentationMode)?this.media===document.pictureInPictureElement:this.media.webkitPresentationMode===$t:null}}],[{key:"supported",value:function(e,t,n){return St.check(e,t,n)}},{key:"loadSprite",value:function(e,t){return Bt(e,t)}},{key:"setup",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=null;return $e.string(t)?i=Array.from(document.querySelectorAll(t)):$e.nodeList(t)?i=Array.from(t):$e.array(t)&&(i=t.filter($e.element)),$e.empty(i)?null:i.map(function(t){return new e(t,n)})}}]),e}();Tn.defaults=(fn=Jt,JSON.parse(JSON.stringify(fn))),gn=window.location.host,vn={prod:"plyr.io"===gn,dev:"dev.plyr.io"===gn},document.addEventListener("DOMContentLoaded",function(){Ie.context(function(){var e=document.getElementById("container");window.shr&&window.shr.setup({count:{classname:"button__count"}}),document.addEventListener("focusout",function(t){t.target.classList&&!e.contains(t.target)&&t.target.classList.remove("tab-focus")}),document.addEventListener("keydown",function(t){9===t.keyCode&&setTimeout(function(){var t=document.activeElement;t&&t.classList&&!e.contains(t)&&t.classList.add("tab-focus")},10)});var t=new Tn("#player",{debug:!0,title:"View From A Blue Moon",iconUrl:"dist/plyr.svg",keyboard:{global:!0},tooltips:{controls:!0},captions:{active:!0},keys:{google:"AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c"},ads:{enabled:vn.prod||vn.dev,publisherId:"918848828995742"},previewThumbnails:{enabled:!0,src:["https://cdn.plyr.io/static/demo/thumbs/100p.vtt","https://cdn.plyr.io/static/demo/thumbs/240p.vtt"]}});window.player=t;var n=document.querySelectorAll("[data-source]"),i={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},r=window.location.hash.replace("#",""),a=window.history&&window.history.pushState;function s(e,t,n){e&&e.classList[n?"add":"remove"](t)}function o(e,a){if(e in i&&(a||e!==r)&&(r.length||e!==i.video)){switch(e){case i.video:t.source={type:"video",title:"View From A Blue Moon",sources:[{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4",type:"video/mp4",size:576},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4",type:"video/mp4",size:720},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4",type:"video/mp4",size:1080},{src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4",type:"video/mp4",size:1440}],poster:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt",default:!0},{kind:"captions",label:"French",srclang:"fr",src:"https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt"}]};break;case i.audio:t.source={type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",sources:[{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]};break;case i.youtube:t.source={type:"video",sources:[{src:"https://youtube.com/watch?v=bTqVqk7FSmY",provider:"youtube"}]};break;case i.vimeo:t.source={type:"video",sources:[{src:"https://vimeo.com/76979871",provider:"vimeo"}]}}r=e,Array.from(n).forEach(function(e){return s(e.parentElement,"active",!1)}),s(document.querySelector('[data-source="'.concat(e,'"]')),"active",!0),Array.from(document.querySelectorAll(".plyr__cite")).forEach(function(e){e.setAttribute("hidden","")}),document.querySelector(".plyr__cite--".concat(e)).removeAttribute("hidden")}}if(Array.from(n).forEach(function(e){e.addEventListener("click",function(){var t=e.getAttribute("data-source");o(t),a&&window.history.pushState({type:t},"","#".concat(t))})}),window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&o(e.state.type)}),a){var l=!r.length;l&&(r=i.video),r in i&&window.history.replaceState({type:r},"",l?"":"#".concat(r)),r!==i.video&&o(r,!0)}})}),vn.prod&&Ie.config("https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555").install()}(); //# sourceMappingURL=demo.min.js.map diff --git a/demo/dist/demo.min.js.map b/demo/dist/demo.min.js.map index b526fa53..84e4db54 100644 --- a/demo/dist/demo.min.js.map +++ b/demo/dist/demo.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../../node_modules/raven-js/vendor/json-stringify-safe/stringify.js","../../../node_modules/raven-js/src/utils.js","../../../node_modules/raven-js/vendor/TraceKit/tracekit.js","../../../node_modules/raven-js/vendor/md5/md5.js","../../../node_modules/raven-js/src/configError.js","../../../node_modules/raven-js/src/console.js","../../../node_modules/raven-js/src/raven.js","../../../node_modules/raven-js/src/singleton.js","demo.js"],"names":["indexOf","haystack","needle","i","length","serializer","replacer","cycleReplacer","stack","keys","key","value","slice","join","thisPos","this","splice","push","Infinity","call","Error","err","message","name","Object","prototype","hasOwnProperty","stringifyError","module","exports","obj","spaces","JSON","stringify","getSerialize","_window","window","global","self","isUndefined","what","isPlainObject","toString","isString","isArray","supportsErrorEvent","ErrorEvent","e","supportsFetch","Headers","Request","Response","each","callback","j","hasKey","truncate","str","max","substr","object","joinRegExp","patterns","pattern","sources","len","replace","source","RegExp","htmlElementAsString","elem","className","classes","attr","out","tagName","toLowerCase","id","split","attrWhitelist","getAttribute","isOnlyOneTruthy","a","b","isSameStacktrace","stack1","stack2","frames1","frames","frames2","filename","lineno","colno","MAX_SERIALIZE_EXCEPTION_DEPTH","MAX_SERIALIZE_EXCEPTION_SIZE","MAX_SERIALIZE_KEYS_LENGTH","jsonSize","encodeURI","utf8Length","serializeValue","type","utils","isObject","isError","isErrorEvent","isFunction","isEmptyObject","_","supportsReferrerPolicy","referrerPolicy","supportsPromiseRejectionEvent","PromiseRejectionEvent","wrappedCallback","data","original","normalizedData","objectMerge","obj1","obj2","objectFrozen","isFrozen","urlencode","o","pairs","encodeURIComponent","uuid4","crypto","msCrypto","getRandomValues","arr","Uint16Array","pad","num","v","c","r","Math","random","htmlTreeAsString","nextStr","height","sepLength","parentNode","reverse","isSameException","ex1","ex2","values","stacktrace","parseUrl","url","match","query","fragment","protocol","host","path","relative","fill","replacement","track","orig","__raven__","__orig__","safeJoin","input","delimiter","output","String","serializeException","ex","depth","maxSize","serialized","serializeObject","reduce","acc","Array","map","val","serializeKeysForMessage","maxLength","filter","usedKeys","sanitize","sanitizeKeys","safeInput","sanitizeRegExp","sanitizeMask","parse","o_O","sanitizeWorker","workerInput","k","test","TraceKit","collectWindowErrors","debug","_slice","UNKNOWN_FUNCTION","ERROR_TYPES_RE","getLocationHref","document","location","href","report","_oldOnerrorHandler","_onErrorHandlerInstalled","handlers","lastArgs","lastException","lastExceptionStack","notifyHandlers","isWindowError","exception","apply","concat","arguments","inner","traceKitWindowOnError","msg","lineNo","colNo","error","computeStackTrace","augmentStackTraceWithInitialElement","processLastException","groups","line","column","undefined","func","_lastExceptionStack","_lastArgs","rethrow","args","setTimeout","incomplete","subscribe","handler","onerror","unsubscribe","uninstall","computeStackTraceFromStackProp","submatch","parts","element","chrome","winjs","gecko","geckoEval","chromeEval","lines","exec","isNative","columnNumber","stackInfo","initial","unshift","partial","computeStackTraceByWalkingCallerChain","item","functionName","funcs","recursion","curr","caller","substring","result","sourceURL","fileName","lineNumber","description","tracekit","safeAdd","x","y","lsw","md5cmn","q","s","t","cnt","md5ff","d","md5gg","md5hh","md5ii","binlMD5","olda","oldb","oldc","oldd","binl2rstr","length32","fromCharCode","rstr2binl","length8","charCodeAt","rstr2hex","charAt","str2rstrUTF8","unescape","rawMD5","rstrMD5","rawHMACMD5","hash","bkey","ipad","opad","rstrHMACMD5","md5_1","string","raw","RavenConfigError","constructor","configError","console$1","console","level","originalConsoleLevel","originalConsole","sentryLevel","logger","extra","Function","wrapConsoleMethod","require$$0","dsnKeys","dsnPattern","now","Date","_document","_navigator","navigator","keepOriginalCallback","Raven","method","_hasJSON","_hasDocument","_hasNavigator","_lastCapturedException","_lastData","_lastEventId","_globalServer","_globalKey","_globalProject","_globalContext","_globalOptions","release","SENTRY_RELEASE","ignoreErrors","ignoreUrls","whitelistUrls","includePaths","headers","captureUnhandledRejections","maxMessageLength","maxUrlLength","stackTraceLimit","autoBreadcrumbs","instrument","sampleRate","_fetchDefaults","keepalive","_ignoreOnError","_isRavenInstalled","_originalErrorStackTraceLimit","_originalConsole","_originalConsoleMethods","_plugins","_startTime","_wrappedBuiltIns","_breadcrumbs","_lastCapturedEvent","_keypressTimeout","_location","_lastHref","_resetBackoff","VERSION","config","dsn","options","_logDebug","globalOptions","setDSN","maxBreadcrumbs","min","autoBreadcrumbDefaults","xhr","dom","sentry","instrumentDefaults","tryCatch","install","isSetup","_handleOnErrorStackInfo","_attachPromiseRejectionHandler","_patchFunctionToString","_instrumentTryCatch","_instrumentBreadcrumbs","_drainPlugins","uri","_parseDSN","lastSlash","lastIndexOf","_dsn","user","_globalSecret","pass","_getGlobalServer","_globalEndpoint","context","wrap","_before","__raven_wrapper__","wrapped","deep","_ignoreNextOnError","captureException","property","_detachPromiseRejectionHandler","_unpatchFunctionToString","_restoreBuiltIns","_restoreConsole","_promiseRejectionHandler","event","reason","unhandledPromiseRejection","bind","addEventListener","removeEventListener","trimHeadFrames","captureMessage","_getCaptureExceptionOptionsFromPlainObject","_handleStackInfo","currentOptions","exKeys","sort","fingerprint","md5","__serialized__","initialCall","fileurl","_prepareFrames","_send","captureBreadcrumb","crumb","timestamp","breadcrumbCallback","shift","addPlugin","plugin","pluginArgs","setUserContext","setExtraContext","_mergeContext","setTagsContext","tags","clearContext","getContext","setEnvironment","environment","setRelease","setDataCallback","dataCallback","setBreadcrumbCallback","setShouldSendCallback","shouldSendCallback","setTransport","transport","lastEventId","ravenNotConfiguredError","afterLoad","RavenConfig","showReportDialog","eventId","encode","qs","email","globalServer","script","createElement","async","src","head","body","appendChild","_triggerEvent","eventType","evt","toUpperCase","createEvent","initEvent","createEventObject","dispatchEvent","fireEvent","_breadcrumbEventHandler","evtName","target","category","_keypressEventHandler","isContentEditable","timeout","clearTimeout","_captureUrlChange","from","to","parsedLoc","parsedTo","parsedFrom","_originalFunctionToString","wrappedBuiltIns","wrapTimeFn","fn","originalCallback","wrapEventTarget","proto","capture","secure","handleEvent","before","clickHandler","keypressHandler","requestAnimationFrame","cb","eventTargets","wrapProp","prop","xhrproto","XMLHttpRequest","origOpen","__raven_xhr","status_code","origSend","onreadystatechangeHandler","readyState","status","props","onreadystatechange","origFetch","fetchInput","fetchData","then","response","attachEvent","hasPushAndReplaceState","app","runtime","history","pushState","replaceState","oldOnPopState","onpopstate","currentHref","historyReplacementFunction","origHistFunction","log","consoleMethodCallback","builtin","installer","m","allowSecretKey","port","_processException","frame","_normalizeFrame","in_app","stackInfoUrl","normalized","function","prefixedMessage","culprit","_trimPacket","request","Referer","breadcrumbs","_trimBreadcrumbs","urlProp","urlProps","_getHttpData","httpData","userAgent","User-Agent","referrer","_backoffDuration","_backoffStart","_shouldBackoff","_isRepeatData","current","last","_setBackoffState","retry","get","getResponseHeader","parseInt","baseData","project","platform","serverName","server_name","_sanitizeData","forEach","_sendProcessedPayload","_getUuid","allowDuplicates","event_id","auth","sentry_version","sentry_client","sentry_key","sentry_secret","_makeRequest","onSuccess","onError","opts","evaluatedHeaders","evaluatedFetchParameters","_evaluateHash","fetchParameters","defaultFetchOptions","fetchOptions","fetch","ok","XDomainRequest","onload","open","setRequestHeader","send","evaluated","setUser","setReleaseContext","raven","_Raven","RavenConstructor","noConflict","isLive","singleton","Client","shr","setup","classList","remove","keyCode","activeElement","add","player","Plyr","buttons","querySelectorAll","types","currentType","historySupport","toggleClass","state","newSource","init","video","audio","youtube","vimeo","button","parentElement","querySelector","cite","setAttribute","removeAttribute","GoogleAnalyticsObject","l","getElementsByTagName","insertBefore","ga"],"mappings":"2JAcA,SAASA,EAAQC,EAAUC,GACzB,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAASG,SAAUD,EACrC,GAAIF,EAASE,KAAOD,EAAQ,OAAOC,EAErC,OAAQ,EAyBV,SAASE,EAAWC,EAAUC,GAC5B,IAAIC,KACAC,KAWJ,OATqB,MAAjBF,IACFA,EAAgB,SAASG,EAAKC,GAC5B,OAAIH,EAAM,KAAOG,EACR,eAEF,eAAiBF,EAAKG,MAAM,EAAGZ,EAAQQ,EAAOG,IAAQE,KAAK,KAAO,MAItE,SAASH,EAAKC,GACnB,GAAIH,EAAMJ,OAAS,EAAG,CACpB,IAAIU,EAAUd,EAAQQ,EAAOO,OAC5BD,EAAUN,EAAMQ,OAAOF,EAAU,GAAKN,EAAMS,KAAKF,OACjDD,EAAUL,EAAKO,OAAOF,EAASI,EAAAA,EAAUR,GAAOD,EAAKQ,KAAKP,IAEtDV,EAAQQ,EAAOG,KAClBA,EAAQJ,EAAcY,KAAKJ,KAAML,EAAKC,SAGxCH,EAAMS,KAAKN,GAGb,OAAmB,MAAZL,EACHK,aAAiBS,MA5CzB,SAAwBT,GACtB,IAAIU,GAEFb,MAAOG,EAAMH,MACbc,QAASX,EAAMW,QACfC,KAAMZ,EAAMY,MAGd,IAAK,IAAIpB,KAAKQ,EACRa,OAAOC,UAAUC,eAAeP,KAAKR,EAAOR,KAC9CkB,EAAIlB,GAAKQ,EAAMR,IAInB,OAAOkB,EA8BwBM,CAAehB,GAASA,EACjDL,EAASa,KAAKJ,KAAML,EAAKC,KA5DvBiB,EAAAC,QAUV,SAAmBC,EAAKxB,EAAUyB,EAAQxB,GACxC,OAAOyB,KAAKC,UAAUH,EAAKzB,EAAWC,EAAUC,GAAgBwB,KAVlEG,aAAuB7B,wCCVnB8B,kBACgB,oBAAXC,OACHA,YACkB,IAAXC,EAAyBA,EAAyB,oBAATC,KAAuBA,SAyB7E,SAASC,EAAYC,GACnB,YAAgB,IAATA,EAOT,SAASC,EAAcD,GACrB,MAAgD,oBAAzChB,OAAOC,UAAUiB,SAASvB,KAAKqB,GAGxC,SAASG,EAASH,GAChB,MAAgD,oBAAzChB,OAAOC,UAAUiB,SAASvB,KAAKqB,GAGxC,SAASI,EAAQJ,GACf,MAAgD,mBAAzChB,OAAOC,UAAUiB,SAASvB,KAAKqB,GAcxC,SAASK,IACP,IAEE,OADA,IAAIC,WAAW,KACR,EACP,MAAOC,GACP,OAAO,GAIX,SAASC,IACP,KAAM,UAAWb,GAAU,OAAO,EAElC,IAIE,OAHA,IAAIc,QACJ,IAAIC,QAAQ,IACZ,IAAIC,UACG,EACP,MAAOJ,GACP,OAAO,GAsCX,SAASK,EAAKtB,EAAKuB,GACjB,IAAIlD,EAAGmD,EAEP,GAAIf,EAAYT,EAAI1B,QAClB,IAAKD,KAAK2B,EACJyB,EAAOzB,EAAK3B,IACdkD,EAASlC,KAAK,KAAMhB,EAAG2B,EAAI3B,SAK/B,GADAmD,EAAIxB,EAAI1B,OAEN,IAAKD,EAAI,EAAGA,EAAImD,EAAGnD,IACjBkD,EAASlC,KAAK,KAAMhB,EAAG2B,EAAI3B,IA+BnC,SAASqD,EAASC,EAAKC,GACrB,GAAmB,iBAARA,EACT,MAAM,IAAItC,MAAM,0DAElB,MAAmB,iBAARqC,GAA4B,IAARC,EACtBD,EAEFA,EAAIrD,QAAUsD,EAAMD,EAAMA,EAAIE,OAAO,EAAGD,GAAO,IAUxD,SAASH,EAAOK,EAAQlD,GACtB,OAAOc,OAAOC,UAAUC,eAAeP,KAAKyC,EAAQlD,GAGtD,SAASmD,EAAWC,GAQlB,IALA,IAGEC,EAHEC,KACF7D,EAAI,EACJ8D,EAAMH,EAAS1D,OAGVD,EAAI8D,EAAK9D,IAEVwC,EADJoB,EAAUD,EAAS3D,IAIjB6D,EAAQ/C,KAAK8C,EAAQG,QAAQ,8BAA+B,SACnDH,GAAWA,EAAQI,QAE5BH,EAAQ/C,KAAK8C,EAAQI,QAIzB,OAAO,IAAIC,OAAOJ,EAAQnD,KAAK,KAAM,KAoHvC,SAASwD,EAAoBC,GAC3B,IACEC,EACAC,EACA9D,EACA+D,EACAtE,EALEuE,KAOJ,IAAKJ,IAASA,EAAKK,QACjB,MAAO,GAST,GANAD,EAAIzD,KAAKqD,EAAKK,QAAQC,eAClBN,EAAKO,IACPH,EAAIzD,KAAK,IAAMqD,EAAKO,KAGtBN,EAAYD,EAAKC,YACA5B,EAAS4B,GAExB,IADAC,EAAUD,EAAUO,MAAM,OACrB3E,EAAI,EAAGA,EAAIqE,EAAQpE,OAAQD,IAC9BuE,EAAIzD,KAAK,IAAMuD,EAAQrE,IAG3B,IAAI4E,GAAiB,OAAQ,OAAQ,QAAS,OAC9C,IAAK5E,EAAI,EAAGA,EAAI4E,EAAc3E,OAAQD,IACpCO,EAAMqE,EAAc5E,IACpBsE,EAAOH,EAAKU,aAAatE,KAEvBgE,EAAIzD,KAAK,IAAMP,EAAM,KAAO+D,EAAO,MAGvC,OAAOC,EAAI7D,KAAK,IAMlB,SAASoE,EAAgBC,EAAGC,GAC1B,WAAYD,IAAMC,GA8BpB,SAASC,EAAiBC,EAAQC,GAChC,GAAIL,EAAgBI,EAAQC,GAAS,OAAO,EAE5C,IAOIJ,EAAGC,EAPHI,EAAUF,EAAOG,OACjBC,EAAUH,EAAOE,OAGrB,GAAID,EAAQnF,SAAWqF,EAAQrF,OAAQ,OAAO,EAI9C,IAAK,IAAID,EAAI,EAAGA,EAAIoF,EAAQnF,OAAQD,IAGlC,GAFA+E,EAAIK,EAAQpF,GACZgF,EAAIM,EAAQtF,GAEV+E,EAAEQ,WAAaP,EAAEO,UACjBR,EAAES,SAAWR,EAAEQ,QACfT,EAAEU,QAAUT,EAAES,OACdV,EAAY,WAAMC,EAAY,SAE9B,OAAO,EAEX,OAAO,EA4CT,IAAIU,EAAgC,EAEhCC,EAA+B,MAC/BC,EAA4B,GAMhC,SAASC,EAASrF,GAChB,OALF,SAAoBA,GAClB,QAASsF,UAAUtF,GAAOmE,MAAM,SAAS1E,OAIlC8F,CAAWlE,KAAKC,UAAUtB,IAGnC,SAASwF,EAAexF,GACtB,GAAqB,iBAAVA,EAAoB,CAE7B,OAAO6C,EAAS7C,EADA,IAEX,GACY,iBAAVA,GACU,kBAAVA,QACU,IAAVA,EAEP,OAAOA,EAGT,IAAIyF,EAAO5E,OAAOC,UAAUiB,SAASvB,KAAKR,GAG1C,MAAa,oBAATyF,EAAmC,WAC1B,mBAATA,EAAkC,UACzB,sBAATA,EACKzF,EAAMY,KAAO,cAAgBZ,EAAMY,KAAO,IAAM,aAElDZ,EA+FT,IAAA0F,GACEC,SA/jBF,SAAkB9D,GAChB,MAAuB,iBAATA,GAA8B,OAATA,GA+jBnC+D,QA1jBF,SAAiB5F,GACf,UAAW+B,SAASvB,KAAKR,IACvB,IAAK,iBAEL,IAAK,qBAEL,IAAK,wBACH,OAAO,EACT,QACE,OAAOA,aAAiBS,QAkjB5BoF,aA9iBF,SAAsB7F,GACpB,OAAOkC,KAAoD,2BAAzBH,SAASvB,KAAKR,IA8iBhD4B,YAAaA,EACbkE,WAxiBF,SAAoBjE,GAClB,MAAuB,mBAATA,GAwiBdC,cAAeA,EACfE,SAAUA,EACVC,QAASA,EACT8D,cA5hBF,SAAuBlE,GACrB,IAAKC,EAAcD,GAAO,OAAO,EAEjC,IAAK,IAAImE,KAAKnE,EACZ,GAAIA,EAAKd,eAAeiF,GACtB,OAAO,EAGX,OAAO,GAqhBP9D,mBAAoBA,EACpBG,cAAeA,EACf4D,uBA1fF,WACE,IAAK5D,IAAiB,OAAO,EAE7B,IAKE,OAHA,IAAIE,QAAQ,cACV2D,eAAgB,YAEX,EACP,MAAO9D,GACP,OAAO,IAifT+D,8BA7eF,WACE,MAAwC,mBAA1BC,uBA6edC,gBA1eF,SAAyB3D,GASvB,OARA,SAAsB4D,EAAMC,GAC1B,IAAIC,EAAiB9D,EAAS4D,IAASA,EACvC,OAAIC,GACKA,EAASC,IAEXA,IAqeT/D,KAAMA,EACNgE,YA7cF,SAAqBC,EAAMC,GACzB,OAAKA,GAGLlE,EAAKkE,EAAM,SAAS5G,EAAKC,GACvB0G,EAAK3G,GAAOC,IAEP0G,GALEA,GA4cT7D,SAAUA,EACV+D,aA7bF,SAAsBzF,GACpB,QAAKN,OAAOgG,UAGLhG,OAAOgG,SAAS1F,IA0bvByB,OAAQA,EACRM,WAAYA,EACZ4D,UA7YF,SAAmBC,GACjB,IAAIC,KAIJ,OAHAvE,EAAKsE,EAAG,SAAShH,EAAKC,GACpBgH,EAAM1G,KAAK2G,mBAAmBlH,GAAO,IAAMkH,mBAAmBjH,MAEzDgH,EAAM9G,KAAK,MAyYlBgH,MArXF,WACE,IAAIC,EAAS3F,EAAQ2F,QAAU3F,EAAQ4F,SAEvC,IAAKxF,EAAYuF,IAAWA,EAAOE,gBAAiB,CAGlD,IAAIC,EAAM,IAAIC,YAAY,GAC1BJ,EAAOE,gBAAgBC,GAGvBA,EAAI,GAAe,KAATA,EAAI,GAAc,MAE5BA,EAAI,GAAe,MAATA,EAAI,GAAe,MAE7B,IAAIE,EAAM,SAASC,GAEjB,IADA,IAAIC,EAAID,EAAI1F,SAAS,IACd2F,EAAEjI,OAAS,GAChBiI,EAAI,IAAMA,EAEZ,OAAOA,GAGT,OACEF,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IACRE,EAAIF,EAAI,IAIV,MAAO,mCAAmC/D,QAAQ,QAAS,SAASoE,GAClE,IAAIC,EAAqB,GAAhBC,KAAKC,SAAiB,EAE/B,OADY,MAANH,EAAYC,EAAS,EAAJA,EAAW,GACzB7F,SAAS,OAiVtBgG,iBArUF,SAA0BpE,GAWxB,IATA,IAOEqE,EALAjE,KACAkE,EAAS,EACT3E,EAAM,EAEN4E,EADY,MACUzI,OAGjBkE,GAAQsE,IATW,KAgBV,UANdD,EAAUtE,EAAoBC,KAO3BsE,EAAS,GAAK3E,EAAMS,EAAItE,OAASyI,EAAYF,EAAQvI,QAhBvC,KAqBjBsE,EAAIzD,KAAK0H,GAET1E,GAAO0E,EAAQvI,OACfkE,EAAOA,EAAKwE,WAGd,OAAOpE,EAAIqE,UAAUlI,KAvBP,QA+TdwD,oBAAqBA,EACrB2E,gBA5OF,SAAyBC,EAAKC,GAC5B,OAAIjE,EAAgBgE,EAAKC,KAEzBD,EAAMA,EAAIE,OAAO,GACjBD,EAAMA,EAAIC,OAAO,GAEbF,EAAI7C,OAAS8C,EAAI9C,MAAQ6C,EAAItI,QAAUuI,EAAIvI,QAbxBuE,EAgBH+D,EAAIG,WAhBEjE,EAgBU+D,EAAIE,aAfjC7G,EAAY2C,KAAM3C,EAAY4C,KAiB9BC,EAAiB6D,EAAIG,WAAYF,EAAIE,cAlB9C,IAAyBlE,EAAGC,GAoP1BC,iBAAkBA,EAClBiE,SAxYF,SAAkBC,GAChB,GAAmB,iBAARA,EAAkB,SAC7B,IAAIC,EAAQD,EAAIC,MAAM,kEAGlBC,EAAQD,EAAM,IAAM,GACpBE,EAAWF,EAAM,IAAM,GAC3B,OACEG,SAAUH,EAAM,GAChBI,KAAMJ,EAAM,GACZK,KAAML,EAAM,GACZM,SAAUN,EAAM,GAAKC,EAAQC,IA8X/BK,KA9LF,SAAchI,EAAKP,EAAMwI,EAAaC,GACpC,GAAW,MAAPlI,EAAJ,CACA,IAAImI,EAAOnI,EAAIP,GACfO,EAAIP,GAAQwI,EAAYE,GACxBnI,EAAIP,GAAM2I,WAAY,EACtBpI,EAAIP,GAAM4I,SAAWF,EACjBD,GACFA,EAAM/I,MAAMa,EAAKP,EAAM0I,MAwLzBG,SA9KF,SAAkBC,EAAOC,GACvB,IAAK1H,EAAQyH,GAAQ,MAAO,GAI5B,IAFA,IAAIE,KAEKpK,EAAI,EAAGA,EAAIkK,EAAMjK,OAAQD,IAChC,IACEoK,EAAOtJ,KAAKuJ,OAAOH,EAAMlK,KACzB,MAAO4C,GACPwH,EAAOtJ,KAAK,gCAIhB,OAAOsJ,EAAO1J,KAAKyJ,IAkKnBG,mBAzGF,SAASA,EAAmBC,EAAIC,EAAOC,GACrC,IAAKnI,EAAciI,GAAK,OAAOA,EAG/BE,EAA2B,iBAD3BD,EAAyB,iBAAVA,EAAqB9E,EAAgC8E,GAC9B7E,EAA+B8E,EAErE,IAAIC,EAvBN,SAASC,EAAgBnK,EAAOgK,GAC9B,OAAc,IAAVA,EAAoBxE,EAAexF,GAEnC8B,EAAc9B,GACTa,OAAOf,KAAKE,GAAOoK,OAAO,SAASC,EAAKtK,GAE7C,OADAsK,EAAItK,GAAOoK,EAAgBnK,EAAMD,GAAMiK,EAAQ,GACxCK,OAEAC,MAAMrI,QAAQjC,GAChBA,EAAMuK,IAAI,SAASC,GACxB,OAAOL,EAAgBK,EAAKR,EAAQ,KAIjCxE,EAAexF,GASLmK,CAAgBJ,EAAIC,GAErC,OAAI3E,EAAS/D,EAAU4I,IAAeD,EAC7BH,EAAmBC,EAAIC,EAAQ,GAGjCE,GA8FPO,wBA3FF,SAAiC3K,EAAM4K,GACrC,GAAoB,iBAAT5K,GAAqC,iBAATA,EAAmB,OAAOA,EAAKiC,WACtE,IAAKuI,MAAMrI,QAAQnC,GAAO,MAAO,GAKjC,GAAoB,KAHpBA,EAAOA,EAAK6K,OAAO,SAAS5K,GAC1B,MAAsB,iBAARA,KAEPN,OAAc,MAAO,uBAG9B,GADAiL,EAAiC,iBAAdA,EAAyBtF,EAA4BsF,EACpE5K,EAAK,GAAGL,QAAUiL,EAAW,OAAO5K,EAAK,GAE7C,IAAK,IAAI8K,EAAW9K,EAAKL,OAAQmL,EAAW,EAAGA,IAAY,CACzD,IAAIV,EAAapK,EAAKG,MAAM,EAAG2K,GAAU1K,KAAK,MAC9C,KAAIgK,EAAWzK,OAASiL,GACxB,OAAIE,IAAa9K,EAAKL,OAAeyK,EAC9BA,EAAa,IAGtB,MAAO,IAyEPW,SAtEF,SAAkBnB,EAAOoB,GACvB,IAAK7I,EAAQ6I,IAAkB7I,EAAQ6I,IAAyC,IAAxBA,EAAarL,OACnE,OAAOiK,EAET,IAEIqB,EAFAC,EAAiB9H,EAAW4H,GAC5BG,EAAe,WAGnB,IACEF,EAAY1J,KAAK6J,MAAM5J,EAAUoI,IACjC,MAAOyB,GACP,OAAOzB,EAwBT,OArBA,SAAS0B,EAAeC,GACtB,OAAIpJ,EAAQoJ,GACHA,EAAYd,IAAI,SAASC,GAC9B,OAAOY,EAAeZ,KAItB1I,EAAcuJ,GACTxK,OAAOf,KAAKuL,GAAajB,OAAO,SAASC,EAAKiB,GAMnD,OALIN,EAAeO,KAAKD,GACtBjB,EAAIiB,GAAKL,EAETZ,EAAIiB,GAAKF,EAAeC,EAAYC,IAE/BjB,OAIJgB,EAGFD,CAAeL,KCtjBpBS,GACFC,qBAAqB,EACrBC,OAAO,GAILlK,EACgB,oBAAXC,OACHA,YACkB,IAAXC,EAAyBA,EAAyB,oBAATC,KAAuBA,QAGzEgK,KAAY1L,MACZ2L,EAAmB,IAGnBC,EAAiB,0GAErB,SAASC,IACP,MAAwB,oBAAbC,UAAiD,MAArBA,SAASC,SAAyB,GAElED,SAASC,SAASC,KA0C3BT,EAASU,OAAS,WAChB,IA0DIC,EAAoBC,EA1DpBC,KACFC,EAAW,KACXC,EAAgB,KAChBC,EAAqB,KAmCvB,SAASC,EAAe5M,EAAO6M,GAC7B,IAAIC,EAAY,KAChB,IAAID,GAAkBlB,EAASC,oBAA/B,CAGA,IAAK,IAAIjM,KAAK6M,EACZ,GAAIA,EAAStL,eAAevB,GAC1B,IACE6M,EAAS7M,GAAGoN,MAAM,MAAO/M,GAAOgN,OAAOlB,EAAOnL,KAAKsM,UAAW,KAC9D,MAAOC,GACPJ,EAAYI,EAKlB,GAAIJ,EACF,MAAMA,GAiBV,SAASK,EAAsBC,EAAKtE,EAAKuE,EAAQC,EAAOpD,GACtD,IAEI4C,EAAYjH,EAAMG,aAAakE,GAAMA,EAAGqD,MAAQrD,EAEhDpJ,EAAU+E,EAAMG,aAAaoH,GAAOA,EAAItM,QAAUsM,EAEtD,GAAIT,EACFhB,EAAS6B,kBAAkBC,oCACzBd,EACA7D,EACAuE,EACAvM,GAEF4M,SACK,GAAIZ,GAAajH,EAAME,QAAQ+G,GAOpCF,EADQjB,EAAS6B,kBAAkBV,IACb,OACjB,CACL,IAUMa,EAVFxB,GACFrD,IAAKA,EACL8E,KAAMP,EACNQ,OAAQP,GAGNvM,OAAO+M,EAGX,GAAkC,uBAA3B5L,SAASvB,KAAKG,IACf6M,EAAS7M,EAAQiI,MAAMiD,MAEzBjL,EAAO4M,EAAO,GACd7M,EAAU6M,EAAO,IAIrBxB,EAAS4B,KAAOhC,EAQhBa,GALE7L,KAAMA,EACND,QAASA,EACTgI,IAAKmD,IACLjM,OAAQmM,KAEY,GAGxB,QAAIG,GACKA,EAAmBS,MAAMxM,KAAM0M,WAwB1C,SAASS,IACP,IAAIM,EAAsBrB,EACxBsB,EAAYxB,EACdA,EAAW,KACXE,EAAqB,KACrBD,EAAgB,KAChBE,EAAeG,MAAM,MAAOiB,GAAqB,GAAOhB,OAAOiB,IAUjE,SAAS5B,EAAOnC,EAAIgE,GAClB,IAAIC,EAAOrC,EAAOnL,KAAKsM,UAAW,GAClC,GAAIN,EAAoB,CACtB,GAAID,IAAkBxC,EACpB,OAEAwD,IAIJ,IAAI1N,EAAQ2L,EAAS6B,kBAAkBtD,GAevC,GAdAyC,EAAqB3M,EACrB0M,EAAgBxC,EAChBuC,EAAW0B,EAMXC,WAAW,WACL1B,IAAkBxC,GACpBwD,KAED1N,EAAMqO,WAAa,IAAO,IAEb,IAAZH,EACF,MAAMhE,EAOV,OAHAmC,EAAOiC,UAzLP,SAAmBC,GA0HbhC,IAGJD,EAAqB3K,EAAQ6M,QAC7B7M,EAAQ6M,QAAUrB,EAClBZ,GAA2B,GA7H3BC,EAAS/L,KAAK8N,IAwLhBlC,EAAOoC,YAjLP,SAAqBF,GACnB,IAAK,IAAI5O,EAAI6M,EAAS5M,OAAS,EAAGD,GAAK,IAAKA,EACtC6M,EAAS7M,KAAO4O,GAClB/B,EAAShM,OAAOb,EAAG,IA+KzB0M,EAAOqC,UAvKP,WA+GOnC,IAGL5K,EAAQ6M,QAAUlC,EAClBC,GAA2B,EAC3BD,OAAqBwB,GAlHrBtB,MAsKKH,EAtMS,GA4PlBV,EAAS6B,kBAAoB,WA4C3B,SAASmB,EAA+BzE,GACtC,QAAwB,IAAbA,EAAGlK,OAA0BkK,EAAGlK,MAA3C,CAiBA,IAfA,IAUI4O,EACAC,EACAC,EAZAC,EAAS,0IACTC,EAAQ,wHAGRC,EAAQ,6JAERC,EAAY,gDACZC,EAAa,gCACbC,EAAQlF,EAAGlK,MAAMsE,MAAM,MACvBtE,KAMKL,GAFO,sBAAsB0P,KAAKnF,EAAGpJ,SAEjC,GAAGgC,EAAIsM,EAAMxP,OAAQD,EAAImD,IAAKnD,EAAG,CAC5C,GAAKkP,EAAQE,EAAOM,KAAKD,EAAMzP,IAAM,CACnC,IAAI2P,EAAWT,EAAM,IAAqC,IAA/BA,EAAM,GAAGrP,QAAQ,UAC/BqP,EAAM,IAAmC,IAA7BA,EAAM,GAAGrP,QAAQ,UAC3BoP,EAAWO,EAAWE,KAAKR,EAAM,OAE9CA,EAAM,GAAKD,EAAS,GACpBC,EAAM,GAAKD,EAAS,GACpBC,EAAM,GAAKD,EAAS,IAEtBE,GACEhG,IAAMwG,EAAsB,KAAXT,EAAM,GACvBd,KAAMc,EAAM,IAAM9C,EAClBoC,KAAMmB,GAAYT,EAAM,OACxBjB,KAAMiB,EAAM,IAAMA,EAAM,GAAK,KAC7BhB,OAAQgB,EAAM,IAAMA,EAAM,GAAK,WAE5B,GAAKA,EAAQG,EAAMK,KAAKD,EAAMzP,IACnCmP,GACEhG,IAAK+F,EAAM,GACXd,KAAMc,EAAM,IAAM9C,EAClBoC,QACAP,MAAOiB,EAAM,GACbhB,OAAQgB,EAAM,IAAMA,EAAM,GAAK,UAE5B,CAAA,KAAKA,EAAQI,EAAMI,KAAKD,EAAMzP,KAsBnC,SArBakP,EAAM,IAAMA,EAAM,GAAGrP,QAAQ,YAAc,IACzCoP,EAAWM,EAAUG,KAAKR,EAAM,MAE7CA,EAAM,GAAKD,EAAS,GACpBC,EAAM,GAAKD,EAAS,GACpBC,EAAM,GAAK,MACI,IAANlP,GAAYkP,EAAM,SAAiC,IAApB3E,EAAGqF,eAK3CvP,EAAM,GAAG6N,OAAS3D,EAAGqF,aAAe,GAEtCT,GACEhG,IAAK+F,EAAM,GACXd,KAAMc,EAAM,IAAM9C,EAClBoC,KAAMU,EAAM,GAAKA,EAAM,GAAGvK,MAAM,QAChCsJ,KAAMiB,EAAM,IAAMA,EAAM,GAAK,KAC7BhB,OAAQgB,EAAM,IAAMA,EAAM,GAAK,OAM9BC,EAAQf,MAAQe,EAAQlB,OAC3BkB,EAAQf,KAAOhC,GAGjB/L,EAAMS,KAAKqO,GAGb,OAAK9O,EAAMJ,QAKTmB,KAAMmJ,EAAGnJ,KACTD,QAASoJ,EAAGpJ,QACZgI,IAAKmD,IACLjM,MAAOA,GAPA,MAwBX,SAASyN,EAAoC+B,EAAW1G,EAAKuE,EAAQvM,GACnE,IAAI2O,GACF3G,IAAKA,EACL8E,KAAMP,GAGR,GAAIoC,EAAQ3G,KAAO2G,EAAQ7B,KAAM,CAO/B,GANA4B,EAAUnB,YAAa,EAElBoB,EAAQ1B,OACX0B,EAAQ1B,KAAOhC,GAGbyD,EAAUxP,MAAMJ,OAAS,GACvB4P,EAAUxP,MAAM,GAAG8I,MAAQ2G,EAAQ3G,IAAK,CAC1C,GAAI0G,EAAUxP,MAAM,GAAG4N,OAAS6B,EAAQ7B,KACtC,OAAO,EACF,IACJ4B,EAAUxP,MAAM,GAAG4N,MACpB4B,EAAUxP,MAAM,GAAG+N,OAAS0B,EAAQ1B,KAGpC,OADAyB,EAAUxP,MAAM,GAAG4N,KAAO6B,EAAQ7B,MAC3B,EAOb,OAFA4B,EAAUxP,MAAM0P,QAAQD,GACxBD,EAAUG,SAAU,GACb,EAKT,OAHEH,EAAUnB,YAAa,GAGlB,EAYT,SAASuB,EAAsC1F,EAAIC,GASjD,IARA,IAIE0E,EACAgB,EALEC,EAAe,qEACjB9P,KACA+P,KACAC,GAAY,EAMRC,EAAOL,EAAsCM,OACjDD,IAASD,EACTC,EAAOA,EAAKC,OAEZ,GAAID,IAASzC,GAAqByC,IAAStE,EAASU,OAApD,CAkBA,GAbAwD,GACE/G,IAAK,KACLiF,KAAMhC,EACN6B,KAAM,KACNC,OAAQ,MAGNoC,EAAKlP,KACP8O,EAAK9B,KAAOkC,EAAKlP,MACP8N,EAAQiB,EAAaT,KAAKY,EAAK/N,eACzC2N,EAAK9B,KAAOc,EAAM,SAGK,IAAdgB,EAAK9B,KACd,IACE8B,EAAK9B,KAAOc,EAAMhF,MAAMsG,UAAU,EAAGtB,EAAMhF,MAAMrK,QAAQ,MACzD,MAAO+C,IAGPwN,EAAM,GAAKE,GACbD,GAAY,EAEZD,EAAM,GAAKE,IAAQ,EAGrBjQ,EAAMS,KAAKoP,GAGT1F,GAGFnK,EAAMQ,OAAO,EAAG2J,GAGlB,IAAIiG,GACFrP,KAAMmJ,EAAGnJ,KACTD,QAASoJ,EAAGpJ,QACZgI,IAAKmD,IACLjM,MAAOA,GAQT,OANAyN,EACE2C,EACAlG,EAAGmG,WAAanG,EAAGoG,SACnBpG,EAAG0D,MAAQ1D,EAAGqG,WACdrG,EAAGpJ,SAAWoJ,EAAGsG,aAEZJ,EAQT,SAAS5C,EAAkBtD,EAAIC,GAC7B,IAAInK,EAAQ,KACZmK,EAAiB,MAATA,EAAgB,GAAKA,EAE7B,IAEE,GADAnK,EAAQ2O,EAA+BzE,GAErC,OAAOlK,EAET,MAAOuC,GACP,GAAIoJ,EAASE,MACX,MAAMtJ,EAIV,IAEE,GADAvC,EAAQ4P,EAAsC1F,EAAIC,EAAQ,GAExD,OAAOnK,EAET,MAAOuC,GACP,GAAIoJ,EAASE,MACX,MAAMtJ,EAGV,OACExB,KAAMmJ,EAAGnJ,KACTD,QAASoJ,EAAGpJ,QACZgI,IAAKmD,KAOT,OAHAuB,EAAkBC,oCAAsCA,EACxDD,EAAkBmB,+BAAiCA,EAE5CnB,EA1SoB,GA6S7B,IAAAiD,EAAiB9E,EC7lBjB,SAAS+E,EAAQC,EAAGC,GAClB,IAAIC,GAAW,MAAJF,IAAmB,MAAJC,GAE1B,OADWD,GAAK,KAAOC,GAAK,KAAOC,GAAO,KAC3B,GAAa,MAANA,EAaxB,SAASC,EAAOC,EAAGrM,EAAGC,EAAGgM,EAAGK,EAAGC,GAC7B,OAAOP,GARc9I,EAQQ8I,EAAQA,EAAQhM,EAAGqM,GAAIL,EAAQC,EAAGM,OARrCC,EAQ0CF,GAP7CpJ,IAAS,GAAKsJ,EAOmCvM,GAR1E,IAAuBiD,EAAKsJ,EAU5B,SAASC,EAAMzM,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAGK,EAAGC,GAC/B,OAAOH,EAAQnM,EAAImD,GAAOnD,EAAIyM,EAAI1M,EAAGC,EAAGgM,EAAGK,EAAGC,GAEhD,SAASI,EAAM3M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAGK,EAAGC,GAC/B,OAAOH,EAAQnM,EAAIyM,EAAMtJ,GAAKsJ,EAAI1M,EAAGC,EAAGgM,EAAGK,EAAGC,GAEhD,SAASK,EAAM5M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAGK,EAAGC,GAC/B,OAAOH,EAAOnM,EAAImD,EAAIsJ,EAAG1M,EAAGC,EAAGgM,EAAGK,EAAGC,GAEvC,SAASM,EAAM7M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAGK,EAAGC,GAC/B,OAAOH,EAAOhJ,GAAKnD,GAAKyM,GAAI1M,EAAGC,EAAGgM,EAAGK,EAAGC,GAM1C,SAASO,EAAQb,EAAGlN,GAKlB,IAAI9D,EACA8R,EACAC,EACAC,EACAC,EAPJjB,EAAElN,GAAO,IAAM,KAASA,EAAM,GAC9BkN,EAA8B,IAAzBlN,EAAM,KAAQ,GAAM,IAAWA,EAOpC,IAAIiB,EAAI,WACJC,GAAK,UACLmD,GAAK,WACLsJ,EAAI,UAER,IAAKzR,EAAI,EAAGA,EAAIgR,EAAE/Q,OAAQD,GAAK,GAC7B8R,EAAO/M,EACPgN,EAAO/M,EACPgN,EAAO7J,EACP8J,EAAOR,EAoEPzM,EAAI4M,EAJJ5M,EAAI4M,EAJJ5M,EAAI4M,EAJJ5M,EAAI4M,EALJ5M,EAAI2M,EAJJ3M,EAAI2M,EAJJ3M,EAAI2M,EAJJ3M,EAAI2M,EALJ3M,EAAI0M,EAJJ1M,EAAI0M,EAJJ1M,EAAI0M,EAJJ1M,EAAI0M,EALJ1M,EAAIwM,EAJJxM,EAAIwM,EAJJxM,EAAIwM,EAJJxM,EAAIwM,EAAMxM,EADVmD,EAAIqJ,EAAMrJ,EADVsJ,EAAID,EAAMC,EADV1M,EAAIyM,EAAMzM,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,GAAI,GAAI,WAChBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,IAAK,WACrB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,GAAI,WACpByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,YAGrCmI,EAAIqJ,EAAMrJ,EADVsJ,EAAID,EAAMC,EADV1M,EAAIyM,EAAMzM,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,WACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,GAAI,YACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,IAAK,YACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,UAGrCmI,EAAIqJ,EAAMrJ,EADVsJ,EAAID,EAAMC,EADV1M,EAAIyM,EAAMzM,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,EAAG,YACnBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,IAAK,YACrB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,IAAK,OACtByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,IAAK,YAGtCmI,EAAIqJ,EAAMrJ,EADVsJ,EAAID,EAAMC,EADV1M,EAAIyM,EAAMzM,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,IAAK,EAAG,YACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,IAAK,UACtB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,IAAK,YACtByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,GAAI,YAIrCmI,EAAIuJ,EAAMvJ,EADVsJ,EAAIC,EAAMD,EADV1M,EAAI2M,EAAM3M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,WACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,GAAI,YACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,GAAI,WACrByR,EAAG1M,EAAGiM,EAAEhR,GAAI,IAAK,WAGjCmI,EAAIuJ,EAAMvJ,EADVsJ,EAAIC,EAAMD,EADV1M,EAAI2M,EAAM3M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,WACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,EAAG,UACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,IAAK,WACtByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,WAGrCmI,EAAIuJ,EAAMvJ,EADVsJ,EAAIC,EAAMD,EADV1M,EAAI2M,EAAM3M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,EAAG,WACnBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,GAAI,YACrB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,IAAK,WACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,GAAI,YAGpCmI,EAAIuJ,EAAMvJ,EADVsJ,EAAIC,EAAMD,EADV1M,EAAI2M,EAAM3M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,IAAK,GAAI,YACrBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,GAAI,UACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,GAAI,YACpByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,IAAK,YAItCmI,EAAIwJ,EAAMxJ,EADVsJ,EAAIE,EAAMF,EADV1M,EAAI4M,EAAM5M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,QACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,IAAK,YACrB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,GAAI,YACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,IAAK,UAGtCmI,EAAIwJ,EAAMxJ,EADVsJ,EAAIE,EAAMF,EADV1M,EAAI4M,EAAM5M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,YACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,GAAI,YACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,IAAK,WACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,IAAK,YAGtCmI,EAAIwJ,EAAMxJ,EADVsJ,EAAIE,EAAMF,EADV1M,EAAI4M,EAAM5M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,IAAK,EAAG,WACpBgF,EAAGmD,EAAG6I,EAAEhR,GAAI,IAAK,WACjB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,IAAK,WACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,GAAI,UAGpCmI,EAAIwJ,EAAMxJ,EADVsJ,EAAIE,EAAMF,EADV1M,EAAI4M,EAAM5M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,WACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,IAAK,WACtB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,GAAI,WACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,WAIrCmI,EAAIyJ,EAAMzJ,EADVsJ,EAAIG,EAAMH,EADV1M,EAAI6M,EAAM7M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,GAAI,GAAI,WAChBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,GAAI,YACpB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,IAAK,YACtByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,UAGrCmI,EAAIyJ,EAAMzJ,EADVsJ,EAAIG,EAAMH,EADV1M,EAAI6M,EAAM7M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,IAAK,EAAG,YACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,GAAI,IAAK,YACrB+E,EAAGC,EAAGgM,EAAEhR,EAAI,IAAK,IAAK,SACtByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,YAGrCmI,EAAIyJ,EAAMzJ,EADVsJ,EAAIG,EAAMH,EADV1M,EAAI6M,EAAM7M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,EAAG,YACnBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,IAAK,UACtB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,IAAK,YACrByR,EAAG1M,EAAGiM,EAAEhR,EAAI,IAAK,GAAI,YAGrCmI,EAAIyJ,EAAMzJ,EADVsJ,EAAIG,EAAMH,EADV1M,EAAI6M,EAAM7M,EAAGC,EAAGmD,EAAGsJ,EAAGT,EAAEhR,EAAI,GAAI,GAAI,WACpBgF,EAAGmD,EAAG6I,EAAEhR,EAAI,IAAK,IAAK,YACtB+E,EAAGC,EAAGgM,EAAEhR,EAAI,GAAI,GAAI,WACpByR,EAAG1M,EAAGiM,EAAEhR,EAAI,GAAI,IAAK,WAErC+E,EAAIgM,EAAQhM,EAAG+M,GACf9M,EAAI+L,EAAQ/L,EAAG+M,GACf5J,EAAI4I,EAAQ5I,EAAG6J,GACfP,EAAIV,EAAQU,EAAGQ,GAEjB,OAAQlN,EAAGC,EAAGmD,EAAGsJ,GAMnB,SAASS,EAAUhI,GACjB,IAAIlK,EACAoK,EAAS,GACT+H,EAA0B,GAAfjI,EAAMjK,OACrB,IAAKD,EAAI,EAAGA,EAAImS,EAAUnS,GAAK,EAC7BoK,GAAUC,OAAO+H,aAAclI,EAAMlK,GAAK,KAAQA,EAAI,GAAO,KAE/D,OAAOoK,EAOT,SAASiI,EAAUnI,GACjB,IAAIlK,EACAoK,KAEJ,IADAA,GAAQF,EAAMjK,QAAU,GAAK,QAAKkO,EAC7BnO,EAAI,EAAGA,EAAIoK,EAAOnK,OAAQD,GAAK,EAClCoK,EAAOpK,GAAK,EAEd,IAAIsS,EAAyB,EAAfpI,EAAMjK,OACpB,IAAKD,EAAI,EAAGA,EAAIsS,EAAStS,GAAK,EAC5BoK,EAAOpK,GAAK,KAAiC,IAA1BkK,EAAMqI,WAAWvS,EAAI,KAAeA,EAAI,GAE7D,OAAOoK,EAkCT,SAASoI,EAAStI,GAChB,IAEI8G,EACAhR,EAFAoK,EAAS,GAGb,IAAKpK,EAAI,EAAGA,EAAIkK,EAAMjK,OAAQD,GAAK,EACjCgR,EAAI9G,EAAMqI,WAAWvS,GACrBoK,GANW,mBAMMqI,OAAQzB,IAAM,EAAK,IANzB,mBAMwCyB,OAAW,GAAJzB,GAE5D,OAAO5G,EAMT,SAASsI,EAAaxI,GACpB,OAAOyI,SAASlL,mBAAmByC,IAMrC,SAAS0I,EAAOvB,GACd,OAnDF,SAAiBA,GACf,OAAOa,EAAUL,EAAQQ,EAAUhB,GAAe,EAAXA,EAAEpR,SAkDlC4S,CAAQH,EAAarB,IAK9B,SAASyB,EAAWhH,EAAG2F,GACrB,OAlDF,SAAqBlR,EAAKuG,GACxB,IAAI9G,EAIA+S,EAHAC,EAAOX,EAAU9R,GACjB0S,KACAC,KAMJ,IAJAD,EAAK,IAAMC,EAAK,SAAM/E,EAClB6E,EAAK/S,OAAS,KAChB+S,EAAOnB,EAAQmB,EAAmB,EAAbzS,EAAIN,SAEtBD,EAAI,EAAGA,EAAI,GAAIA,GAAK,EACvBiT,EAAKjT,GAAe,UAAVgT,EAAKhT,GACfkT,EAAKlT,GAAe,WAAVgT,EAAKhT,GAGjB,OADA+S,EAAOlB,EAAQoB,EAAK5F,OAAOgF,EAAUvL,IAAQ,IAAoB,EAAdA,EAAK7G,QACjDiS,EAAUL,EAAQqB,EAAK7F,OAAO0F,GAAO,MAmCrCI,CAAYT,EAAa5G,GAAI4G,EAAajB,IAmBnD,IAAA2B,EAbA,SAAaC,EAAQ9S,EAAK+S,GACxB,OAAK/S,EAMA+S,EAGER,EAAWvS,EAAK8S,GAbhBb,EAASM,EAWIvS,EAAK8S,IANlBC,EAGEV,EAAOS,GAdTb,EAASI,EAYES,KC/PpB,SAASE,EAAiBpS,GACxBP,KAAKQ,KAAO,mBACZR,KAAKO,QAAUA,EAEjBoS,EAAiBjS,UAAY,IAAIL,MACjCsS,EAAiBjS,UAAUkS,YAAcD,EAEzC,IAAAE,EAAiBF,ECgCjBG,EArCiB,SAASC,EAASC,EAAO1Q,GACxC,IAAI2Q,EAAuBF,EAAQC,GAC/BE,EAAkBH,EAEtB,GAAMC,KAASD,EAAf,CAIA,IAAII,EAAwB,SAAVH,EAAmB,UAAYA,EAEjDD,EAAQC,GAAS,WACf,IAAIpF,KAAU/N,MAAMO,KAAKsM,WAErBG,EAAMvH,EAAM+D,SAASuE,EAAM,KAC3B1H,GAAQ8M,MAAOG,EAAaC,OAAQ,UAAWC,OAAQ3G,UAAWkB,IAExD,WAAVoF,GACc,IAAZpF,EAAK,KAEPf,EACE,sBAAwBvH,EAAM+D,SAASuE,EAAK/N,MAAM,GAAI,MAAQ,kBAChEqG,EAAKmN,MAAM3G,UAAYkB,EAAK/N,MAAM,GAClCyC,GAAYA,EAASuK,EAAK3G,IAG5B5D,GAAYA,EAASuK,EAAK3G,GAIxB+M,GAGFK,SAAS5S,UAAU8L,MAAMpM,KAAK6S,EAAsBC,EAAiBtF,MC1BvEpI,EAAUF,EAAME,QAChBD,EAAWD,EAAMC,SACjB7D,EAAgB4D,EAAM5D,cACtB+D,EAAeH,EAAMG,aACrBjE,EAAc8D,EAAM9D,YACpBkE,EAAaJ,EAAMI,WACnB9D,EAAW0D,EAAM1D,SACjBC,GAAUyD,EAAMzD,QAChB8D,GAAgBL,EAAMK,cACtBtD,GAAOiD,EAAMjD,KACbgE,GAAcf,EAAMe,YACpB5D,GAAW6C,EAAM7C,SACjB+D,GAAelB,EAAMkB,aACrBhE,GAAS8C,EAAM9C,OACfM,GAAawC,EAAMxC,WACnB4D,GAAYpB,EAAMoB,UAClBI,GAAQxB,EAAMwB,MACda,GAAmBrC,EAAMqC,iBACzBM,GAAkB3C,EAAM2C,gBACxB5D,GAAmBiB,EAAMjB,iBACzBiE,GAAWhD,EAAMgD,SACjBS,GAAOzD,EAAMyD,KACb9G,GAAgBqD,EAAMrD,cACtB4D,GAAyBP,EAAMO,uBAC/BwE,GAA0B/E,EAAM+E,wBAChCX,GAAqBpE,EAAMoE,mBAC3Be,GAAWnF,EAAMmF,SAEjB8I,GAAoBC,EAEpBC,GAAU,2CAA2C1P,MAAM,KAC7D2P,GAAa,gEAEf,SAASC,KACP,OAAQ,IAAIC,KAId,IAAIxS,GACgB,oBAAXC,OACHA,YACkB,IAAXC,EAAyBA,EAAyB,oBAATC,KAAuBA,QACzEsS,GAAYzS,GAAQuK,SACpBmI,GAAa1S,GAAQ2S,UAEzB,SAASC,GAAqB7N,EAAU7D,GACtC,OAAOoD,EAAWpD,GACd,SAAS4D,GACP,OAAO5D,EAAS4D,EAAMC,IAExB7D,EAMN,SAAS2R,KA2DP,IAAK,IAAIC,KA1DTlU,KAAKmU,WAA8B,iBAATlT,OAAqBA,KAAKC,WAEpDlB,KAAKoU,cAAgB5S,EAAYqS,IACjC7T,KAAKqU,eAAiB7S,EAAYsS,IAClC9T,KAAKsU,uBAAyB,KAC9BtU,KAAKuU,UAAY,KACjBvU,KAAKwU,aAAe,KACpBxU,KAAKyU,cAAgB,KACrBzU,KAAK0U,WAAa,KAClB1U,KAAK2U,eAAiB,KACtB3U,KAAK4U,kBACL5U,KAAK6U,gBAEHC,QAAS1T,GAAQ2T,gBAAkB3T,GAAQ2T,eAAejR,GAC1DsP,OAAQ,aACR4B,gBACAC,cACAC,iBACAC,gBACAC,QAAS,KACT/J,qBAAqB,EACrBgK,4BAA4B,EAC5BC,iBAAkB,EAElBC,aAAc,IACdC,gBAAiB,GACjBC,iBAAiB,EACjBC,YAAY,EACZC,WAAY,EACZjL,iBAEF1K,KAAK4V,gBACH1B,OAAQ,OACR2B,WAAW,EAKX/P,eAAgBD,KAA2B,SAAW,IAExD7F,KAAK8V,eAAiB,EACtB9V,KAAK+V,mBAAoB,EACzB/V,KAAKgW,8BAAgC3V,MAAMmV,gBAG3CxV,KAAKiW,iBAAmB7U,GAAQ2R,YAChC/S,KAAKkW,2BACLlW,KAAKmW,YACLnW,KAAKoW,WAAazC,KAClB3T,KAAKqW,oBACLrW,KAAKsW,gBACLtW,KAAKuW,mBAAqB,KAC1BvW,KAAKwW,iBACLxW,KAAKyW,UAAYrV,GAAQwK,SACzB5L,KAAK0W,UAAY1W,KAAKyW,WAAazW,KAAKyW,UAAU5K,KAClD7L,KAAK2W,gBAGc3W,KAAKiW,iBACtBjW,KAAKkW,wBAAwBhC,GAAUlU,KAAKiW,iBAAiB/B,GAUjED,GAAMvT,WAKJkW,QAAS,SAETtL,OAAO,EAEPF,SAAUA,EASVyL,OAAQ,SAASC,EAAKC,GACpB,IAAIxV,EAAOvB,KAEX,GAAIuB,EAAKkT,cAEP,OADAzU,KAAKgX,UAAU,QAAS,4CACjBzV,EAET,IAAKuV,EAAK,OAAOvV,EAEjB,IAAI0V,EAAgB1V,EAAKsT,eAGrBkC,GACF1U,GAAK0U,EAAS,SAASpX,EAAKC,GAEd,SAARD,GAA0B,UAARA,GAA2B,SAARA,EACvC4B,EAAKqT,eAAejV,GAAOC,EAE3BqX,EAActX,GAAOC,IAK3B2B,EAAK2V,OAAOJ,GAIZG,EAAcjC,aAAa9U,KAAK,qBAChC+W,EAAcjC,aAAa9U,KAAK,iDAGhC+W,EAAcjC,aAAelS,GAAWmU,EAAcjC,cACtDiC,EAAchC,aAAagC,EAAchC,WAAW5V,QAChDyD,GAAWmU,EAAchC,YAE7BgC,EAAc/B,gBAAgB+B,EAAc/B,cAAc7V,QACtDyD,GAAWmU,EAAc/B,eAE7B+B,EAAc9B,aAAerS,GAAWmU,EAAc9B,cACtD8B,EAAcE,eAAiB1P,KAAK9E,IAClC,EACA8E,KAAK2P,IAAIH,EAAcE,gBAAkB,IAAK,MAGhD,IAAIE,GACFC,KAAK,EACLvE,SAAS,EACTwE,KAAK,EACL3L,UAAU,EACV4L,QAAQ,GAGN/B,EAAkBwB,EAAcxB,gBACM,uBAAnC9T,SAASvB,KAAKqV,GACnBA,EAAkBpP,GAAYgR,EAAwB5B,IACzB,IAApBA,IACTA,EAAkB4B,GAEpBJ,EAAcxB,gBAAkBA,EAEhC,IAAIgC,GACFC,UAAU,GAGRhC,EAAauB,EAAcvB,WAW/B,MAVqC,uBAA9B/T,SAASvB,KAAKsV,GACnBA,EAAarP,GAAYoR,EAAoB/B,IACrB,IAAfA,IACTA,EAAa+B,GAEfR,EAAcvB,WAAaA,EAE3BtK,EAASC,sBAAwB4L,EAAc5L,oBAGxC9J,GAWToW,QAAS,WACP,IAAIpW,EAAOvB,KAyBX,OAxBIuB,EAAKqW,YAAcrW,EAAKwU,oBAC1B3K,EAASU,OAAOiC,UAAU,WACxBxM,EAAKsW,wBAAwBrL,MAAMjL,EAAMmL,aAGvCnL,EAAKsT,eAAeQ,4BACtB9T,EAAKuW,iCAGPvW,EAAKwW,yBAEDxW,EAAKsT,eAAea,YAAcnU,EAAKsT,eAAea,WAAWgC,UACnEnW,EAAKyW,sBAGHzW,EAAKsT,eAAeY,iBAAiBlU,EAAK0W,yBAG9C1W,EAAK2W,gBAEL3W,EAAKwU,mBAAoB,GAG3B1V,MAAMmV,gBAAkBjU,EAAKsT,eAAeW,gBACrCxV,MAQTkX,OAAQ,SAASJ,GACf,IACEqB,EADSnY,KACEoY,UAAUtB,GACrBuB,EAAYF,EAAItP,KAAKyP,YAAY,KACjCzP,EAAOsP,EAAItP,KAAKjG,OAAO,EAAGyV,GAHjBrY,KAKNuY,KAAOzB,EALD9W,KAMN0U,WAAayD,EAAIK,KANXxY,KAONyY,cAAgBN,EAAIO,MAAQP,EAAIO,KAAK9V,OAAO,GAPtC5C,KAQN2U,eAAiBwD,EAAItP,KAAKjG,OAAOyV,EAAY,GARvCrY,KAUNyU,cAVMzU,KAUe2Y,iBAAiBR,GAVhCnY,KAYN4Y,gBAZM5Y,KAaJyU,cAAgB,IAAM5L,EAAO,OAbzB7I,KAauC2U,eAAiB,UAInE3U,KAAK2W,iBAWPkC,QAAS,SAAS9B,EAASvJ,EAAMI,GAO/B,OANIlI,EAAWqR,KACbnJ,EAAOJ,MACPA,EAAOuJ,EACPA,OAAUxJ,GAGLvN,KAAK8Y,KAAK/B,EAASvJ,GAAMhB,MAAMxM,KAAM4N,IAW9CkL,KAAM,SAAS/B,EAASvJ,EAAMuL,GAC5B,IAAIxX,EAAOvB,KAGX,GAAIwB,EAAYgM,KAAU9H,EAAWqR,GACnC,OAAOA,EAWT,GAPIrR,EAAWqR,KACbvJ,EAAOuJ,EACPA,OAAUxJ,IAKP7H,EAAW8H,GACd,OAAOA,EAIT,IACE,GAAIA,EAAKrE,UACP,OAAOqE,EAIT,GAAIA,EAAKwL,kBACP,OAAOxL,EAAKwL,kBAEd,MAAOhX,GAIP,OAAOwL,EAGT,SAASyL,IACP,IAAIrL,KACFxO,EAAIsN,UAAUrN,OACd6Z,GAAQnC,GAAYA,IAA4B,IAAjBA,EAAQmC,KAQzC,IANIH,GAAWrT,EAAWqT,IACxBA,EAAQvM,MAAMxM,KAAM0M,WAKftN,KAAKwO,EAAKxO,GAAK8Z,EAAO3X,EAAKuX,KAAK/B,EAASrK,UAAUtN,IAAMsN,UAAUtN,GAE1E,IAKE,OAAOoO,EAAKhB,MAAMxM,KAAM4N,GACxB,MAAO5L,GAGP,MAFAT,EAAK4X,qBACL5X,EAAK6X,iBAAiBpX,EAAG+U,GACnB/U,GAKV,IAAK,IAAIqX,KAAY7L,EACfhL,GAAOgL,EAAM6L,KACfJ,EAAQI,GAAY7L,EAAK6L,IAW7B,OARAJ,EAAQvY,UAAY8M,EAAK9M,UAEzB8M,EAAKwL,kBAAoBC,EAGzBA,EAAQ9P,WAAY,EACpB8P,EAAQ7P,SAAWoE,EAEZyL,GAQT9K,UAAW,WAWT,OAVA/C,EAASU,OAAOqC,YAEhBnO,KAAKsZ,iCACLtZ,KAAKuZ,2BACLvZ,KAAKwZ,mBACLxZ,KAAKyZ,kBAELpZ,MAAMmV,gBAAkBxV,KAAKgW,8BAC7BhW,KAAK+V,mBAAoB,EAElB/V,MAWT0Z,yBAA0B,SAASC,GACjC3Z,KAAKgX,UAAU,QAAS,4CAA6C2C,GACrE3Z,KAAKoZ,iBAAiBO,EAAMC,QAC1BvG,OACEwG,2BAA2B,MAUjC/B,+BAAgC,WAI9B,OAHA9X,KAAK0Z,yBAA2B1Z,KAAK0Z,yBAAyBI,KAAK9Z,MACnEoB,GAAQ2Y,kBACN3Y,GAAQ2Y,iBAAiB,qBAAsB/Z,KAAK0Z,0BAC/C1Z,MAQTsZ,+BAAgC,WAG9B,OAFAlY,GAAQ4Y,qBACN5Y,GAAQ4Y,oBAAoB,qBAAsBha,KAAK0Z,0BAClD1Z,MAUToZ,iBAAkB,SAASzP,EAAIoN,GAG7B,GAFAA,EAAU1Q,IAAa4T,eAAgB,GAAIlD,OAEvCtR,EAAakE,IAAOA,EAAGqD,MAEzBrD,EAAKA,EAAGqD,WACH,GAAIxH,EAAQmE,GAEjBA,EAAKA,MACA,CAAA,IAAIjI,EAAciI,GAYvB,OAAO3J,KAAKka,eACVvQ,EACAtD,GAAY0Q,GACV1O,YAAY,EACZ4R,eAAgBlD,EAAQkD,eAAiB,KAZ7ClD,EAAU/W,KAAKma,2CAA2CpD,EAASpN,GACnEA,EAAK,IAAItJ,MAAM0W,EAAQxW,SAiBzBP,KAAKsU,uBAAyB3K,EAO9B,IACE,IAAIlK,EAAQ2L,EAAS6B,kBAAkBtD,GACvC3J,KAAKoa,iBAAiB3a,EAAOsX,GAC7B,MAAO7O,GACP,GAAIyB,IAAOzB,EACT,MAAMA,EAIV,OAAOlI,MAGTma,2CAA4C,SAASE,EAAgB1Q,GACnE,IAAI2Q,EAAS7Z,OAAOf,KAAKiK,GAAI4Q,OACzBxD,EAAU1Q,GAAYgU,GACxB9Z,QACE,2CAA6C8J,GAAwBiQ,GACvEE,aAAcC,EAAIH,IAClBjH,MAAOgH,EAAehH,YAIxB,OAFA0D,EAAQ1D,MAAMqH,eAAiBhR,GAAmBC,GAE3CoN,GAUTmD,eAAgB,SAASrN,EAAKkK,GAI5B,IACI/W,KAAK6U,eAAeG,aAAa7J,OACnCnL,KAAK6U,eAAeG,aAAa7J,KAAK0B,GAFxC,CAUA,IAOIlD,EAPAzD,EAAOG,IAEP9F,QAJJsM,GAAY,IADZkK,EAAUA,OAeV,IACE,MAAM,IAAI1W,MAAMwM,GAChB,MAAO3E,GACPyB,EAAKzB,EAIPyB,EAAGnJ,KAAO,KACV,IAAIf,EAAQ2L,EAAS6B,kBAAkBtD,GAGnCgR,EAAc9Y,GAAQpC,EAAMA,QAAUA,EAAMA,MAAM,GAKlDkb,GAAoC,2BAArBA,EAAYnN,OAC7BmN,EAAclb,EAAMA,MAAM,IAG5B,IAAImb,EAAWD,GAAeA,EAAYpS,KAAQ,GAElD,KACIvI,KAAK6U,eAAeI,WAAW9J,OACjCnL,KAAK6U,eAAeI,WAAW9J,KAAKyP,OAMlC5a,KAAK6U,eAAeK,cAAc/J,MACnCnL,KAAK6U,eAAeK,cAAc/J,KAAKyP,IAF1C,CAOA,GAAI5a,KAAK6U,eAAexM,YAAe0O,GAAWA,EAAQ1O,WAAa,CAErEnC,EAAKsU,YAAkC,MAApBtU,EAAKsU,YAAsB3N,EAAM3G,EAAKsU,aAEzDzD,EAAU1Q,IAEN4T,eAAgB,GAElBlD,IAMMkD,gBAAkB,EAE1B,IAAIxV,EAASzE,KAAK6a,eAAepb,EAAOsX,GACxC7Q,EAAKmC,YAEH5D,OAAQA,EAAOuD,WAcnB,OATI9B,EAAKsU,cACPtU,EAAKsU,YAAc3Y,GAAQqE,EAAKsU,aAC5BtU,EAAKsU,aACJtU,EAAKsU,cAIZxa,KAAK8a,MAAM5U,GAEJlG,QAGT+a,kBAAmB,SAASha,GAC1B,IAAIia,EAAQ3U,IAER4U,UAAWtH,KAAQ,KAErB5S,GAGF,GAAI2E,EAAW1F,KAAK6U,eAAeqG,oBAAqB,CACtD,IAAIrL,EAAS7P,KAAK6U,eAAeqG,mBAAmBF,GAEpD,GAAIzV,EAASsK,KAAYlK,GAAckK,GACrCmL,EAAQnL,OACH,IAAe,IAAXA,EACT,OAAO7P,KAQX,OAJAA,KAAKsW,aAAapW,KAAK8a,GACnBhb,KAAKsW,aAAajX,OAASW,KAAK6U,eAAesC,gBACjDnX,KAAKsW,aAAa6E,QAEbnb,MAGTob,UAAW,SAASC,GAClB,IAAIC,KAAgBzb,MAAMO,KAAKsM,UAAW,GAO1C,OALA1M,KAAKmW,SAASjW,MAAMmb,EAAQC,IACxBtb,KAAK+V,mBACP/V,KAAKkY,gBAGAlY,MASTub,eAAgB,SAAS/C,GAIvB,OAFAxY,KAAK4U,eAAe4D,KAAOA,EAEpBxY,MASTwb,gBAAiB,SAASnI,GAGxB,OAFArT,KAAKyb,cAAc,QAASpI,GAErBrT,MAST0b,eAAgB,SAASC,GAGvB,OAFA3b,KAAKyb,cAAc,OAAQE,GAEpB3b,MAQT4b,aAAc,WAGZ,OAFA5b,KAAK4U,kBAEE5U,MAQT6b,WAAY,WAEV,OAAO5a,KAAK6J,MAAM5J,EAAUlB,KAAK4U,kBASnCkH,eAAgB,SAASC,GAGvB,OAFA/b,KAAK6U,eAAekH,YAAcA,EAE3B/b,MASTgc,WAAY,SAASlH,GAGnB,OAFA9U,KAAK6U,eAAeC,QAAUA,EAEvB9U,MAUTic,gBAAiB,SAAS3Z,GACxB,IAAI6D,EAAWnG,KAAK6U,eAAeqH,aAEnC,OADAlc,KAAK6U,eAAeqH,aAAelI,GAAqB7N,EAAU7D,GAC3DtC,MAUTmc,sBAAuB,SAAS7Z,GAC9B,IAAI6D,EAAWnG,KAAK6U,eAAeqG,mBAEnC,OADAlb,KAAK6U,eAAeqG,mBAAqBlH,GAAqB7N,EAAU7D,GACjEtC,MAUToc,sBAAuB,SAAS9Z,GAC9B,IAAI6D,EAAWnG,KAAK6U,eAAewH,mBAEnC,OADArc,KAAK6U,eAAewH,mBAAqBrI,GAAqB7N,EAAU7D,GACjEtC,MAYTsc,aAAc,SAASC,GAGrB,OAFAvc,KAAK6U,eAAe0H,UAAYA,EAEzBvc,MAQTmM,cAAe,WACb,OAAOnM,KAAKsU,wBAQdkI,YAAa,WACX,OAAOxc,KAAKwU,cAQdoD,QAAS,WACP,QAAK5X,KAAKmU,aACLnU,KAAKyU,gBACHzU,KAAKyc,0BACRzc,KAAKyc,yBAA0B,EAC/Bzc,KAAKgX,UAAU,QAAS,2CAEnB,KAKX0F,UAAW,WAIT,IAAIC,EAAcvb,GAAQub,YACtBA,GACF3c,KAAK6W,OAAO8F,EAAY7F,IAAK6F,EAAY9F,QAAQc,WAIrDiF,iBAAkB,SAAS7F,GACzB,GACGlD,GADH,CAOA,IAAI2I,GAFJzF,EAAUA,OAEgB8F,SAAW7c,KAAKwc,cAC1C,IAAKA,EACH,MAAM,IAAI7J,EAAiB,mBAG7B,IAAImE,EAAMC,EAAQD,KAAO9W,KAAKuY,KAC9B,IAAKzB,EACH,MAAM,IAAInE,EAAiB,eAG7B,IAAImK,EAASjW,mBACTkW,EAAK,GACTA,GAAM,YAAcD,EAAON,GAC3BO,GAAM,QAAUD,EAAOhG,GAEvB,IAAI0B,EAAOzB,EAAQyB,MAAQxY,KAAK4U,eAAe4D,KAC3CA,IACEA,EAAKhY,OAAMuc,GAAM,SAAWD,EAAOtE,EAAKhY,OACxCgY,EAAKwE,QAAOD,GAAM,UAAYD,EAAOtE,EAAKwE,SAGhD,IAAIC,EAAejd,KAAK2Y,iBAAiB3Y,KAAKoY,UAAUtB,IAEpDoG,EAASrJ,GAAUsJ,cAAc,UACrCD,EAAOE,OAAQ,EACfF,EAAOG,IAAMJ,EAAe,yBAA2BF,GACtDlJ,GAAUyJ,MAAQzJ,GAAU0J,MAAMC,YAAYN,KAIjD/D,mBAAoB,WAClB,IAAI5X,EAAOvB,KACXA,KAAK8V,gBAAkB,EACvBjI,WAAW,WAETtM,EAAKuU,gBAAkB,KAI3B2H,cAAe,SAASC,EAAW3G,GAEjC,IAAI4G,EAAKhe,EAET,GAAKK,KAAKoU,aAAV,CAcA,IAAKzU,KAZLoX,EAAUA,MAEV2G,EAAY,QAAUA,EAAU9a,OAAO,EAAG,GAAGgb,cAAgBF,EAAU9a,OAAO,GAE1EiR,GAAUgK,aACZF,EAAM9J,GAAUgK,YAAY,eACxBC,UAAUJ,GAAW,GAAM,IAE/BC,EAAM9J,GAAUkK,qBACZL,UAAYA,EAGN3G,EACNvU,GAAOuU,EAASpX,KAClBge,EAAIhe,GAAOoX,EAAQpX,IAGvB,GAAIkU,GAAUgK,YAEZhK,GAAUmK,cAAcL,QAIxB,IACE9J,GAAUoK,UAAU,KAAON,EAAID,UAAU7Z,cAAe8Z,GACxD,MAAO3b,OAYbkc,wBAAyB,SAASC,GAChC,IAAI5c,EAAOvB,KACX,OAAO,SAAS2d,GASd,GALApc,EAAKiV,iBAAmB,KAKpBjV,EAAKgV,qBAAuBoH,EAAhC,CAQA,IAAIS,EANJ7c,EAAKgV,mBAAqBoH,EAO1B,IACES,EAASzW,GAAiBgW,EAAIS,QAC9B,MAAOpc,GACPoc,EAAS,YAGX7c,EAAKwZ,mBACHsD,SAAU,MAAQF,EAClB5d,QAAS6d,OAUfE,sBAAuB,WACrB,IAAI/c,EAAOvB,KAMX,OAAO,SAAS2d,GACd,IAAIS,EACJ,IACEA,EAAST,EAAIS,OACb,MAAOpc,GAGP,OAEF,IAAI4B,EAAUwa,GAAUA,EAAOxa,QAK/B,GACGA,IACY,UAAZA,GAAmC,aAAZA,GAA2Bwa,EAAOG,mBAF5D,CAQA,IAAIC,EAAUjd,EAAKiV,iBACdgI,GACHjd,EAAK2c,wBAAwB,QAA7B3c,CAAsCoc,GAExCc,aAAaD,GACbjd,EAAKiV,iBAAmB3I,WAAW,WACjCtM,EAAKiV,iBAAmB,MAjCP,QA4CvBkI,kBAAmB,SAASC,EAAMC,GAChC,IAAIC,EAAYvW,GAAStI,KAAKyW,UAAU5K,MACpCiT,EAAWxW,GAASsW,GACpBG,EAAazW,GAASqW,GAK1B3e,KAAK0W,UAAYkI,EAIbC,EAAUlW,WAAamW,EAASnW,UAAYkW,EAAUjW,OAASkW,EAASlW,OAC1EgW,EAAKE,EAAShW,UACZ+V,EAAUlW,WAAaoW,EAAWpW,UAAYkW,EAAUjW,OAASmW,EAAWnW,OAC9E+V,EAAOI,EAAWjW,UAEpB9I,KAAK+a,mBACHsD,SAAU,aACVnY,MACE0Y,GAAIA,EACJD,KAAMA,MAKZ5G,uBAAwB,WACtB,IAAIxW,EAAOvB,KACXuB,EAAKyd,0BAA4B1L,SAAS5S,UAAUiB,SAEpD2R,SAAS5S,UAAUiB,SAAW,WAC5B,MAAoB,mBAAT3B,MAAuBA,KAAKmJ,UAC9B5H,EAAKyd,0BAA0BxS,MAAMxM,KAAKoJ,SAAUsD,WAEtDnL,EAAKyd,0BAA0BxS,MAAMxM,KAAM0M,aAItD6M,yBAA0B,WACpBvZ,KAAKgf,4BAEP1L,SAAS5S,UAAUiB,SAAW3B,KAAKgf,4BAQvChH,oBAAqB,WACnB,IAAIzW,EAAOvB,KAEPif,EAAkB1d,EAAK8U,iBAE3B,SAAS6I,EAAWhW,GAClB,OAAO,SAASiW,EAAIzO,GAKlB,IADA,IAAI9C,EAAO,IAAI1D,MAAMwC,UAAUrN,QACtBD,EAAI,EAAGA,EAAIwO,EAAKvO,SAAUD,EACjCwO,EAAKxO,GAAKsN,UAAUtN,GAEtB,IAAIggB,EAAmBxR,EAAK,GAQ5B,OAPIlI,EAAW0Z,KACbxR,EAAK,GAAKrM,EAAKuX,KAAKsG,IAMlBlW,EAAKsD,MACAtD,EAAKsD,MAAMxM,KAAM4N,GAEjB1E,EAAK0E,EAAK,GAAIA,EAAK,KAKhC,IAAI6H,EAAkBzV,KAAK6U,eAAeY,gBAE1C,SAAS4J,EAAgB/d,GACvB,IAAIge,EAAQle,GAAQE,IAAWF,GAAQE,GAAQZ,UAC3C4e,GAASA,EAAM3e,gBAAkB2e,EAAM3e,eAAe,sBACxDoI,GACEuW,EACA,mBACA,SAASpW,GACP,OAAO,SAASiV,EAASgB,EAAII,EAASC,GAEpC,IACML,GAAMA,EAAGM,cACXN,EAAGM,YAAcle,EAAKuX,KAAKqG,EAAGM,cAEhC,MAAOnf,IAMT,IAAIof,EAAQC,EAAcC,EA6B1B,OA1BEnK,GACAA,EAAgB8B,MACJ,gBAAXjW,GAAuC,SAAXA,KAI7Bqe,EAAepe,EAAK2c,wBAAwB,SAC5C0B,EAAkBre,EAAK+c,wBACvBoB,EAAS,SAAS/B,GAIhB,GAAKA,EAAL,CAEA,IAAID,EACJ,IACEA,EAAYC,EAAItY,KAChB,MAAOrD,GAGP,OAEF,MAAkB,UAAd0b,EAA8BiC,EAAahC,GACxB,aAAdD,EAAiCkC,EAAgBjC,QAArD,KAGFzU,EAAK9I,KACVJ,KACAme,EACA5c,EAAKuX,KAAKqG,OAAI5R,EAAWmS,GACzBH,EACAC,KAINP,GAEFlW,GACEuW,EACA,sBACA,SAASpW,GACP,OAAO,SAASyU,EAAKwB,EAAII,EAASC,GAChC,IACEL,EAAKA,IAAOA,EAAGnG,kBAAoBmG,EAAGnG,kBAAoBmG,GAC1D,MAAOnd,IAGT,OAAOkH,EAAK9I,KAAKJ,KAAM2d,EAAKwB,EAAII,EAASC,KAG7CP,IAKNlW,GAAK3H,GAAS,aAAc8d,EAAYD,GACxClW,GAAK3H,GAAS,cAAe8d,EAAYD,GACrC7d,GAAQye,uBACV9W,GACE3H,GACA,wBACA,SAAS8H,GACP,OAAO,SAAS4W,GACd,OAAO5W,EAAK3H,EAAKuX,KAAKgH,MAG1Bb,GAqCJ,IA/BA,IAAIc,GACF,cACA,SACA,OACA,mBACA,iBACA,oBACA,kBACA,cACA,aACA,qBACA,cACA,aACA,iBACA,eACA,kBACA,cACA,cACA,eACA,qBACA,SACA,YACA,eACA,gBACA,YACA,kBACA,SACA,iBACA,4BACA,wBAEO3gB,EAAI,EAAGA,EAAI2gB,EAAa1gB,OAAQD,IACvCigB,EAAgBU,EAAa3gB,KAajC6Y,uBAAwB,WACtB,IAAI1W,EAAOvB,KACPyV,EAAkBzV,KAAK6U,eAAeY,gBAEtCwJ,EAAkB1d,EAAK8U,iBAE3B,SAAS2J,EAASC,EAAM3I,GAClB2I,KAAQ3I,GAAO5R,EAAW4R,EAAI2I,KAChClX,GAAKuO,EAAK2I,EAAM,SAAS/W,GACvB,OAAO3H,EAAKuX,KAAK5P,KAKvB,GAAIuM,EAAgB6B,KAAO,mBAAoBlW,GAAS,CACtD,IAAI8e,EAAW9e,GAAQ+e,gBAAkB/e,GAAQ+e,eAAezf,UAChEqI,GACEmX,EACA,OACA,SAASE,GACP,OAAO,SAASlM,EAAQ3L,GAYtB,OARI3G,EAAS2G,KAA0C,IAAlCA,EAAItJ,QAAQsC,EAAKmT,cACpC1U,KAAKqgB,aACHnM,OAAQA,EACR3L,IAAKA,EACL+X,YAAa,OAIVF,EAAS5T,MAAMxM,KAAM0M,aAGhCuS,GAGFlW,GACEmX,EACA,OACA,SAASK,GACP,OAAO,WAEL,IAAIjJ,EAAMtX,KAEV,SAASwgB,IACP,GAAIlJ,EAAI+I,aAAkC,IAAnB/I,EAAImJ,WAAkB,CAC3C,IAGEnJ,EAAI+I,YAAYC,YAAchJ,EAAIoJ,OAClC,MAAO1e,IAITT,EAAKwZ,mBACH1V,KAAM,OACNgZ,SAAU,MACVnY,KAAMoR,EAAI+I,eAMhB,IADA,IAAIM,GAAS,SAAU,UAAW,cACzBpe,EAAI,EAAGA,EAAIoe,EAAMthB,OAAQkD,IAChCyd,EAASW,EAAMpe,GAAI+U,GAiBrB,MAdI,uBAAwBA,GAAO5R,EAAW4R,EAAIsJ,oBAChD7X,GACEuO,EACA,qBACA,SAASpO,GACP,OAAO3H,EAAKuX,KAAK5P,OAAMqE,EAAWiT,KAMtClJ,EAAIsJ,mBAAqBJ,EAGpBD,EAAS/T,MAAMxM,KAAM0M,aAGhCuS,GAIAxJ,EAAgB6B,KAAOrV,MACzB8G,GACE3H,GACA,QACA,SAASyf,GACP,OAAO,WAKL,IADA,IAAIjT,EAAO,IAAI1D,MAAMwC,UAAUrN,QACtBD,EAAI,EAAGA,EAAIwO,EAAKvO,SAAUD,EACjCwO,EAAKxO,GAAKsN,UAAUtN,GAGtB,IAEImJ,EAFAuY,EAAalT,EAAK,GAClBsG,EAAS,MAeb,GAZ0B,iBAAf4M,EACTvY,EAAMuY,EACG,YAAa1f,IAAW0f,aAAsB1f,GAAQe,SAC/DoG,EAAMuY,EAAWvY,IACbuY,EAAW5M,SACbA,EAAS4M,EAAW5M,SAGtB3L,EAAM,GAAKuY,GAIyB,IAAlCvY,EAAItJ,QAAQsC,EAAKmT,YACnB,OAAOmM,EAAUrU,MAAMxM,KAAM4N,GAG3BA,EAAK,IAAMA,EAAK,GAAGsG,SACrBA,EAAStG,EAAK,GAAGsG,QAGnB,IAAI6M,GACF7M,OAAQA,EACR3L,IAAKA,EACL+X,YAAa,MAGf,OAAOO,EACJrU,MAAMxM,KAAM4N,GACZoT,KAAK,SAASC,GASb,OARAF,EAAUT,YAAcW,EAASP,OAEjCnf,EAAKwZ,mBACH1V,KAAM,OACNgZ,SAAU,QACVnY,KAAM6a,IAGDE,IAED,MAAE,SAAS3gB,GASjB,MAPAiB,EAAKwZ,mBACH1V,KAAM,OACNgZ,SAAU,QACVnY,KAAM6a,EACN/N,MAAO,UAGH1S,MAId2e,GAMAxJ,EAAgB8B,KAAOvX,KAAKoU,eAC1BP,GAAUkG,kBACZlG,GAAUkG,iBAAiB,QAASxY,EAAK2c,wBAAwB,UAAU,GAC3ErK,GAAUkG,iBAAiB,WAAYxY,EAAK+c,yBAAyB,IAC5DzK,GAAUqN,cAEnBrN,GAAUqN,YAAY,UAAW3f,EAAK2c,wBAAwB,UAC9DrK,GAAUqN,YAAY,aAAc3f,EAAK+c,2BAQ7C,IAAI9P,EAASpN,GAAQoN,OAEjB2S,IADsB3S,GAAUA,EAAO4S,KAAO5S,EAAO4S,IAAIC,UAG3DjgB,GAAQkgB,SACRA,QAAQC,WACRD,QAAQE,aACV,GAAI/L,EAAgB7J,UAAYuV,EAAwB,CAEtD,IAAIM,EAAgBrgB,GAAQsgB,WAC5BtgB,GAAQsgB,WAAa,WACnB,IAAIC,EAAcpgB,EAAKkV,UAAU5K,KAGjC,GAFAtK,EAAKmd,kBAAkBnd,EAAKmV,UAAWiL,GAEnCF,EACF,OAAOA,EAAcjV,MAAMxM,KAAM0M,YAIrC,IAAIkV,EAA6B,SAASC,GAGxC,OAAO,WACL,IAAItZ,EAAMmE,UAAUrN,OAAS,EAAIqN,UAAU,QAAKa,EAQhD,OALIhF,GAEFhH,EAAKmd,kBAAkBnd,EAAKmV,UAAWnO,EAAM,IAGxCsZ,EAAiBrV,MAAMxM,KAAM0M,aAIxC3D,GAAKuY,QAAS,YAAaM,EAA4B3C,GACvDlW,GAAKuY,QAAS,eAAgBM,EAA4B3C,GAG5D,GAAIxJ,EAAgB1C,SAAW,YAAa3R,IAAW2R,QAAQ+O,IAAK,CAElE,IAAIC,EAAwB,SAASlV,EAAK3G,GACxC3E,EAAKwZ,mBACHxa,QAASsM,EACTmG,MAAO9M,EAAK8M,MACZqL,SAAU,aAIdhc,IAAM,QAAS,OAAQ,OAAQ,QAAS,OAAQ,SAASuD,EAAGoN,GAC1DO,GAAkBR,QAASC,EAAO+O,OAKxCvI,iBAAkB,WAGhB,IADA,IAAIwI,EACGhiB,KAAKqW,iBAAiBhX,QAAQ,CAGnC,IAAI0B,GAFJihB,EAAUhiB,KAAKqW,iBAAiB8E,SAEd,GAChB3a,EAAOwhB,EAAQ,GACf9Y,EAAO8Y,EAAQ,GAEjBjhB,EAAIP,GAAQ0I,IAIhBuQ,gBAAiB,WAEf,IAAK,IAAIvF,KAAUlU,KAAKkW,wBACtBlW,KAAKiW,iBAAiB/B,GAAUlU,KAAKkW,wBAAwBhC,IAIjEgE,cAAe,WACb,IAAI3W,EAAOvB,KAGXqC,GAAKrC,KAAKmW,SAAU,SAASvQ,EAAGyV,GAC9B,IAAI4G,EAAY5G,EAAO,GACnBzN,EAAOyN,EAAO,GAClB4G,EAAUzV,MAAMjL,GAAOA,GAAMkL,OAAOmB,OAIxCwK,UAAW,SAAS1V,GAClB,IAAIwf,EAAIxO,GAAW5E,KAAKpM,GACtBoU,KACA1X,EAAI,EAEN,IACE,KAAOA,KAAK0X,EAAIrD,GAAQrU,IAAM8iB,EAAE9iB,IAAM,GACtC,MAAO4C,GACP,MAAM,IAAI2Q,EAAiB,gBAAkBjQ,GAG/C,GAAIoU,EAAI4B,OAAS1Y,KAAK6U,eAAesN,eACnC,MAAM,IAAIxP,EACR,kFAIJ,OAAOmE,GAGT6B,iBAAkB,SAASR,GAEzB,IAAI8E,EAAe,KAAO9E,EAAIvP,MAAQuP,EAAIiK,KAAO,IAAMjK,EAAIiK,KAAO,IAKlE,OAHIjK,EAAIxP,WACNsU,EAAe9E,EAAIxP,SAAW,IAAMsU,GAE/BA,GAGTpF,wBAAyB,WAElB7X,KAAK8V,gBACR9V,KAAKoa,iBAAiB5N,MAAMxM,KAAM0M,YAItC0N,iBAAkB,SAASnL,EAAW8H,GACpC,IAAItS,EAASzE,KAAK6a,eAAe5L,EAAW8H,GAE5C/W,KAAKyd,cAAc,UACjBxO,UAAWA,EACX8H,QAASA,IAGX/W,KAAKqiB,kBACHpT,EAAUzO,KACVyO,EAAU1O,QACV0O,EAAU1G,IACV0G,EAAUrK,OACVH,EACAsS,IAIJ8D,eAAgB,SAAS5L,EAAW8H,GAClC,IAAIxV,EAAOvB,KACPyE,KACJ,GAAIwK,EAAUxP,OAASwP,EAAUxP,MAAMJ,SACrCgD,GAAK4M,EAAUxP,MAAO,SAASL,EAAGK,GAChC,IAAI6iB,EAAQ/gB,EAAKghB,gBAAgB9iB,EAAOwP,EAAU1G,KAC9C+Z,GACF7d,EAAOvE,KAAKoiB,KAKZvL,GAAWA,EAAQkD,gBACrB,IAAK,IAAI1X,EAAI,EAAGA,EAAIwU,EAAQkD,gBAAkB1X,EAAIkC,EAAOpF,OAAQkD,IAC/DkC,EAAOlC,GAAGigB,QAAS,EAKzB,OADA/d,EAASA,EAAO5E,MAAM,EAAGG,KAAK6U,eAAeW,kBAI/C+M,gBAAiB,SAASD,EAAOG,GAE/B,IAAIC,GACF/d,SAAU2d,EAAM/Z,IAChB3D,OAAQ0d,EAAMjV,KACdxI,MAAOyd,EAAMhV,OACbqV,SAAUL,EAAM9U,MAAQ,KAuB1B,OAfK8U,EAAM/Z,MACTma,EAAW/d,SAAW8d,GAGxBC,EAAWF,SAGNxiB,KAAK6U,eAAeM,aAAahK,OACjCnL,KAAK6U,eAAeM,aAAahK,KAAKuX,EAAW/d,WAEpD,qBAAqBwG,KAAKuX,EAAqB,WAE/C,qBAAqBvX,KAAKuX,EAAW/d,WAGhC+d,GAGTL,kBAAmB,SAAShd,EAAM9E,EAASqa,EAAShW,EAAQH,EAAQsS,GAClE,IASI1O,EATAua,GAAmBvd,EAAOA,EAAO,KAAO,KAAO9E,GAAW,IAC9D,KACIP,KAAK6U,eAAeG,aAAa7J,OAClCnL,KAAK6U,eAAeG,aAAa7J,KAAK5K,KACrCP,KAAK6U,eAAeG,aAAa7J,KAAKyX,MAOtCne,GAAUA,EAAOpF,QACnBub,EAAUnW,EAAO,GAAGE,UAAYiW,EAGhCnW,EAAOuD,UACPK,GAAc5D,OAAQA,IACbmW,IACTvS,GACE5D,SAEIE,SAAUiW,EACVhW,OAAQA,EACR4d,QAAQ,QAOZxiB,KAAK6U,eAAeI,WAAW9J,OACjCnL,KAAK6U,eAAeI,WAAW9J,KAAKyP,OAMlC5a,KAAK6U,eAAeK,cAAc/J,MACnCnL,KAAK6U,eAAeK,cAAc/J,KAAKyP,KAF1C,CAOA,IAAI1U,EAAOG,IAGPkG,WACEnE,SAEI/C,KAAMA,EACNzF,MAAOW,EACP8H,WAAYA,KAIlBwa,QAASjI,GAEX7D,GAIF/W,KAAK8a,MAAM5U,KAGb4c,YAAa,SAAS5c,GAGpB,IAAIvD,EAAM3C,KAAK6U,eAAeS,iBAI9B,GAHIpP,EAAK3F,UACP2F,EAAK3F,QAAUkC,GAASyD,EAAK3F,QAASoC,IAEpCuD,EAAKqG,UAAW,CAClB,IAAIA,EAAYrG,EAAKqG,UAAUnE,OAAO,GACtCmE,EAAU3M,MAAQ6C,GAAS8J,EAAU3M,MAAO+C,GAG9C,IAAIogB,EAAU7c,EAAK6c,QAanB,OAZIA,IACEA,EAAQxa,MACVwa,EAAQxa,IAAM9F,GAASsgB,EAAQxa,IAAKvI,KAAK6U,eAAeU,eAEtDwN,EAAQC,UACVD,EAAQC,QAAUvgB,GAASsgB,EAAQC,QAAShjB,KAAK6U,eAAeU,gBAIhErP,EAAK+c,aAAe/c,EAAK+c,YAAY7a,QACvCpI,KAAKkjB,iBAAiBhd,EAAK+c,aAEtB/c,GAMTgd,iBAAkB,SAASD,GAQzB,IALA,IACEE,EACAnI,EACA9U,EAHEkd,GAAY,KAAM,OAAQ,OAKrBhkB,EAAI,EAAGA,EAAI6jB,EAAY7a,OAAO/I,SAAUD,EAE/C,IADA4b,EAAQiI,EAAY7a,OAAOhJ,IAElBuB,eAAe,SACrB4E,EAASyV,EAAM9U,QAChBM,GAAawU,EAAM9U,MAHrB,CAOAA,EAAOG,MAAgB2U,EAAM9U,MAC7B,IAAK,IAAI3D,EAAI,EAAGA,EAAI6gB,EAAS/jB,SAAUkD,EACrC4gB,EAAUC,EAAS7gB,GACf2D,EAAKvF,eAAewiB,IAAYjd,EAAKid,KACvCjd,EAAKid,GAAW1gB,GAASyD,EAAKid,GAAUnjB,KAAK6U,eAAeU,eAGhE0N,EAAY7a,OAAOhJ,GAAG8G,KAAOA,IAIjCmd,aAAc,WACZ,GAAKrjB,KAAKqU,eAAkBrU,KAAKoU,aAAjC,CACA,IAAIkP,KAkBJ,OAhBItjB,KAAKqU,eAAiBP,GAAWyP,YACnCD,EAASlO,SACPoO,aAAczP,UAAUwP,YAKxBniB,GAAQwK,UAAYxK,GAAQwK,SAASC,OACvCyX,EAAS/a,IAAMnH,GAAQwK,SAASC,MAG9B7L,KAAKoU,cAAgBP,GAAU4P,WAC5BH,EAASlO,UAASkO,EAASlO,YAChCkO,EAASlO,QAAQ4N,QAAUnP,GAAU4P,UAGhCH,IAGT3M,cAAe,WACb3W,KAAK0jB,iBAAmB,EACxB1jB,KAAK2jB,cAAgB,MAGvBC,eAAgB,WACd,OAAO5jB,KAAK0jB,kBAAoB/P,KAAQ3T,KAAK2jB,cAAgB3jB,KAAK0jB,kBAYpEG,cAAe,SAASC,GACtB,IAAIC,EAAO/jB,KAAKuU,UAEhB,SACGwP,GACDD,EAAQvjB,UAAYwjB,EAAKxjB,SACzBujB,EAAQjB,UAAYkB,EAAKlB,WAKvBiB,EAAQzb,YAAc0b,EAAK1b,WACtBhE,GAAiByf,EAAQzb,WAAY0b,EAAK1b,aACxCyb,EAAQvX,YAAawX,EAAKxX,WAE5BtE,GAAgB6b,EAAQvX,UAAWwX,EAAKxX,aAMnDyX,iBAAkB,SAASjB,GAEzB,IAAI/iB,KAAK4jB,iBAAT,CAIA,IAAIlD,EAASqC,EAAQrC,OAKrB,GAAiB,MAAXA,GAA6B,MAAXA,GAA6B,MAAXA,EAA1C,CAEA,IAAIuD,EACJ,IAIIA,EADEhiB,KACM8gB,EAAQ3N,QAAQ8O,IAAI,eAEpBnB,EAAQoB,kBAAkB,eAIpCF,EAA8B,IAAtBG,SAASH,EAAO,IACxB,MAAOjiB,IAIThC,KAAK0jB,iBAAmBO,IAII,EAAxBjkB,KAAK0jB,kBAAwB,KAEjC1jB,KAAK2jB,cAAgBhQ,QAGvBmH,MAAO,SAAS5U,GACd,IAAI+Q,EAAgBjX,KAAK6U,eAErBwP,GACAC,QAAStkB,KAAK2U,eACdvB,OAAQ6D,EAAc7D,OACtBmR,SAAU,cAEZjB,EAAWtjB,KAAKqjB,eAEdC,IACFe,EAAStB,QAAUO,GAIjBpd,EAAK+T,uBAAuB/T,EAAK+T,gBAErC/T,EAAOG,GAAYge,EAAUne,IAGxByV,KAAOtV,GAAYA,MAAgBrG,KAAK4U,eAAe+G,MAAOzV,EAAKyV,MACxEzV,EAAKmN,MAAQhN,GAAYA,MAAgBrG,KAAK4U,eAAevB,OAAQnN,EAAKmN,OAG1EnN,EAAKmN,MAAM,oBAAsBM,KAAQ3T,KAAKoW,WAE1CpW,KAAKsW,cAAgBtW,KAAKsW,aAAajX,OAAS,IAGlD6G,EAAK+c,aACH7a,UAAWvI,MAAMO,KAAKJ,KAAKsW,aAAc,KAIzCtW,KAAK4U,eAAe4D,OAEtBtS,EAAKsS,KAAOxY,KAAK4U,eAAe4D,MAI9BvB,EAAc8E,cAAa7V,EAAK6V,YAAc9E,EAAc8E,aAG5D9E,EAAcnC,UAAS5O,EAAK4O,QAAUmC,EAAcnC,SAGpDmC,EAAcuN,aAAYte,EAAKue,YAAcxN,EAAcuN,YAE/Dte,EAAOlG,KAAK0kB,cAAcxe,GAG1BzF,OAAOf,KAAKwG,GAAMye,QAAQ,SAAShlB,IAChB,MAAbuG,EAAKvG,IAA8B,KAAduG,EAAKvG,IAAegG,GAAcO,EAAKvG,aACvDuG,EAAKvG,KAIZ+F,EAAWuR,EAAciF,gBAC3BhW,EAAO+Q,EAAciF,aAAahW,IAASA,GAIxCA,IAAQP,GAAcO,KAMzBR,EAAWuR,EAAcoF,sBACxBpF,EAAcoF,mBAAmBnW,KAOhClG,KAAK4jB,iBACP5jB,KAAKgX,UAAU,OAAQ,uCAAwC9Q,GAIzB,iBAA7B+Q,EAActB,WACnBlO,KAAKC,SAAWuP,EAActB,YAChC3V,KAAK4kB,sBAAsB1e,GAG7BlG,KAAK4kB,sBAAsB1e,MAI/Bwe,cAAe,SAASxe,GACtB,OAAOuE,GAASvE,EAAMlG,KAAK6U,eAAenK,eAG5Cma,SAAU,WACR,OAAO/d,MAGT8d,sBAAuB,SAAS1e,EAAM5D,GACpC,IAAIf,EAAOvB,KACPiX,EAAgBjX,KAAK6U,eAEzB,GAAK7U,KAAK4X,UAQV,GALA1R,EAAOlG,KAAK8iB,YAAY5c,GAKnBlG,KAAK6U,eAAeiQ,kBAAmB9kB,KAAK6jB,cAAc3d,GAA/D,CAQAlG,KAAKwU,aAAetO,EAAK6e,WAAa7e,EAAK6e,SAAW/kB,KAAK6kB,YAG3D7kB,KAAKuU,UAAYrO,EAEjBlG,KAAKgX,UAAU,QAAS,uBAAwB9Q,GAEhD,IAAI8e,GACFC,eAAgB,IAChBC,cAAe,YAAcllB,KAAK4W,QAClCuO,WAAYnlB,KAAK0U,YAGf1U,KAAKyY,gBACPuM,EAAKI,cAAgBplB,KAAKyY,eAG5B,IAAIlM,EAAYrG,EAAKqG,WAAarG,EAAKqG,UAAUnE,OAAO,GAItDpI,KAAK6U,eAAeY,iBACpBzV,KAAK6U,eAAeY,gBAAgB+B,QAEpCxX,KAAK+a,mBACHsD,SAAU,SACV9d,QAASgM,GACJA,EAAUlH,KAAOkH,EAAUlH,KAAO,KAAO,IAAMkH,EAAU3M,MAC1DsG,EAAK3F,QACTwkB,SAAU7e,EAAK6e,SACf/R,MAAO9M,EAAK8M,OAAS,UAIzB,IAAIzK,EAAMvI,KAAK4Y,iBACd3B,EAAcsF,WAAavc,KAAKqlB,cAAcjlB,KAAKJ,MAClDuI,IAAKA,EACLyc,KAAMA,EACN9e,KAAMA,EACN6Q,QAASE,EACTqO,UAAW,WACT/jB,EAAKoV,gBAELpV,EAAKkc,cAAc,WACjBvX,KAAMA,EACNmX,IAAK9U,IAEPjG,GAAYA,KAEdijB,QAAS,SAAiBvY,GACxBzL,EAAKyV,UAAU,QAAS,mCAAoChK,GAExDA,EAAM+V,SACRxhB,EAAKyiB,iBAAiBhX,EAAM+V,SAG9BxhB,EAAKkc,cAAc,WACjBvX,KAAMA,EACNmX,IAAK9U,IAEPyE,EAAQA,GAAS,IAAI3M,MAAM,sDAC3BiC,GAAYA,EAAS0K,WApEvBhN,KAAKgX,UAAU,OAAQ,+BAAgC9Q,IAyE3Dmf,aAAc,SAASG,GAErB,IAAIjd,EAAMid,EAAKjd,IAAM,IAAM7B,GAAU8e,EAAKR,MAEtCS,EAAmB,KACnBC,KAUJ,GARIF,EAAKzO,QAAQ3B,UACfqQ,EAAmBzlB,KAAK2lB,cAAcH,EAAKzO,QAAQ3B,UAGjDoQ,EAAKzO,QAAQ6O,kBACfF,EAA2B1lB,KAAK2lB,cAAcH,EAAKzO,QAAQ6O,kBAGzD3jB,KAAiB,CACnByjB,EAAyBnI,KAAOrc,EAAUskB,EAAKtf,MAE/C,IAAI2f,EAAsBxf,MAAgBrG,KAAK4V,gBAC3CkQ,EAAezf,GAAYwf,EAAqBH,GAMpD,OAJID,IACFK,EAAa1Q,QAAUqQ,GAGlBrkB,GACJ2kB,MAAMxd,EAAKud,GACX9E,KAAK,SAASC,GACb,GAAIA,EAAS+E,GACXR,EAAKF,WAAaE,EAAKF,gBAClB,CACL,IAAItY,EAAQ,IAAI3M,MAAM,sBAAwB4gB,EAASP,QAGvD1T,EAAM+V,QAAU9B,EAChBuE,EAAKD,SAAWC,EAAKD,QAAQvY,MAGzB,MAAE,WACRwY,EAAKD,SACHC,EAAKD,QAAQ,IAAIllB,MAAM,6CAI/B,IAAI0iB,EAAU3hB,GAAQ+e,gBAAkB,IAAI/e,GAAQ+e,eAC/C4C,KAGS,oBAAqBA,GAAqC,oBAAnBkD,kBAIjD,oBAAqBlD,EACvBA,EAAQnC,mBAAqB,WAC3B,GAA2B,IAAvBmC,EAAQtC,WAEL,GAAuB,MAAnBsC,EAAQrC,OACjB8E,EAAKF,WAAaE,EAAKF,iBAClB,GAAIE,EAAKD,QAAS,CACvB,IAAIjlB,EAAM,IAAID,MAAM,sBAAwB0iB,EAAQrC,QACpDpgB,EAAIyiB,QAAUA,EACdyC,EAAKD,QAAQjlB,MAIjByiB,EAAU,IAAIkD,eAGd1d,EAAMA,EAAIpF,QAAQ,WAAY,IAG1BqiB,EAAKF,YACPvC,EAAQmD,OAASV,EAAKF,WAEpBE,EAAKD,UACPxC,EAAQ9U,QAAU,WAChB,IAAI3N,EAAM,IAAID,MAAM,qCACpBC,EAAIyiB,QAAUA,EACdyC,EAAKD,QAAQjlB,MAKnByiB,EAAQoD,KAAK,OAAQ5d,GAEjBkd,GACFpjB,GAAKojB,EAAkB,SAAS9lB,EAAKC,GACnCmjB,EAAQqD,iBAAiBzmB,EAAKC,KAIlCmjB,EAAQsD,KAAKnlB,EAAUskB,EAAKtf,UAG9Byf,cAAe,SAASxT,GACtB,IAAImU,KAEJ,IAAK,IAAI3mB,KAAOwS,EACd,GAAIA,EAAKxR,eAAehB,GAAM,CAC5B,IAAIC,EAAQuS,EAAKxS,GACjB2mB,EAAU3mB,GAAwB,mBAAVC,EAAuBA,IAAUA,EAI7D,OAAO0mB,GAGTtP,UAAW,SAAShE,GAGhBhT,KAAKkW,wBAAwBlD,KAC5BhT,KAAKsL,OAAStL,KAAK6U,eAAevJ,QAGnCgI,SAAS5S,UAAU8L,MAAMpM,KACvBJ,KAAKkW,wBAAwBlD,GAC7BhT,KAAKiW,oBACFpW,MAAMO,KAAKsM,UAAW,KAK/B+O,cAAe,SAAS9b,EAAKkZ,GACvBrX,EAAYqX,UACP7Y,KAAK4U,eAAejV,GAE3BK,KAAK4U,eAAejV,GAAO0G,GAAYrG,KAAK4U,eAAejV,OAAYkZ,KAM7E5E,GAAMvT,UAAU6lB,QAAUtS,GAAMvT,UAAU6a,eAC1CtH,GAAMvT,UAAU8lB,kBAAoBvS,GAAMvT,UAAUsb,WAEpD,IAAAyK,GAAiBxS,GC3mEb7S,GACgB,oBAAXC,OACHA,YACkB,IAAXC,EAAyBA,EAAyB,oBAATC,KAAuBA,QACzEmlB,GAAStlB,GAAQ6S,MAEjBA,GAAQ,IAAI0S,GAQhB1S,GAAM2S,WAAa,WAEjB,OADAxlB,GAAQ6S,MAAQyS,GACTzS,IAGTA,GAAMyI,YAEN,ICsRAtd,GAAAqR,GAAA9J,GAAAa,GAAArD,GAAA+d,GA3SA2E,GDqBAC,GAAiB7S,GAoCjB8S,GAAwBJ,iBCzDxBE,GAAA,YAAAxlB,OAAAuK,SAAAhD,UAKAiO,OAAA,6DAAAc,mBAGAoC,iBAAA,mBAAA,cACAlB,QAAA,WACAxX,OAAA2lB,YACAA,IAAAC,wBRRA,4BASAlN,iBAAA,WAAA,SAAAJ,KQWAyE,OAAA8I,UAAAC,OAJA,wBRFApN,iBAAA,UAAA,SAAAJ,GQWA,IAAAA,EAAAyN,oBAMA,oBACAC,cAAAH,UAAAI,IAhBA,cAiBA,SAIAC,EAAA,IAAAC,KAAA,kBACA,QACA,gCACA,qCAEA,uBAGA,qBAqDA,gBAGA,yDAGA,cACA,4BAKAD,OAAAA,MAGAE,EAAA9b,SAAA+b,iBAAA,iBACAC,SPpFA,cOsFA,gBACA,gBACA,SAEAC,EAAAvmB,OAAAuK,SAAAuG,KAAAhP,QAAA,IAAA,IACA0kB,EAAAxmB,OAAAigB,SAAAjgB,OAAAigB,QAAAC,mBAGAuG,EAAAvZ,EAAA/K,EAAAukB,GACAxZ,KACA2Y,UAAAa,EAAA,MAAA,UAAAvkB,YAKAwkB,EAAA3iB,EAAA4iB,MAEA5iB,KAAAsiB,IAAAM,GAAA5iB,IAAAuiB,KAAAA,EAAAvoB,QAAAgG,IAAAsiB,EAAAO,eAIA7iB,QACAsiB,EAAAO,QACA9kB,aACA,cACA,sCAGA,8EACA,iBACA,UAGA,8EACA,iBACA,UAGA,+EACA,iBACA,WAGA,+EPpFA,iBOsFA,cAGA,qFAGA,iBACA,kBACA,SACA,mFACA,SPlFA,iBOsFA,iBACA,SACA,wFAOAukB,EAAAQ,QACA/kB,aACA,cACA,4EPlFA,mFOsFA,kBAGA,mFACA,0BAOAukB,EAAAS,UACAhlB,aACA,sBAEA,mDACA,wBAMAukB,EAAAU,QACAjlB,aACA,sBAEA,sCACA,aAWAiC,QAGAsZ,KAAA8I,GAAA9C,QAAA,SAAA2D,UAAAR,EAAAQ,EAAAC,cAAA,UAAA,OAGA5c,SAAA6c,cAAA,iBAAAnjB,EAAA,MAAA,UAAA,SAGAsZ,KAAAhT,SAAA+b,iBAAA,gBAAA/C,QAAA,SAAA8D,KACAC,aAAA,SAAA,eAEAF,cAAA,gBAAAnjB,GAAAsjB,gBAAA,oBAIAhK,KAAA8I,GAAA9C,QAAA,SAAA2D,KACAvO,iBAAA,QAAA,eACA1U,EAAAijB,EAAArkB,aAAA,iBAEAoB,GPnFAwiB,UOsFAvG,QAAAC,WAAAlc,KAAAA,GAAA,GAAA,IAAAA,cAMA0U,iBAAA,WAAA,SAAAJ,GACAA,EAAAoO,OAAA,SAAApO,EAAAoO,SACApO,EAAAoO,MAAA1iB,QAKAwiB,EAAA,KACAK,GAAAN,EAAAvoB,OAGA6oB,MACAP,EAAAO,OAIAN,KAAAD,UACArG,QAAAE,mBAEAoG,GAEA,GACAM,EAAA,GAAA,IAAAN,GAKAA,IAAAD,EAAAO,SACAN,GAAA,QASAf,KACAznB,GAaAiC,OAbAoP,GAaA9E,SAbAhF,GAaA,SAbAa,GAaA,QAZAohB,sBAAAphB,MACA,GACApI,GAAA,IACA,YACAA,GAAA,GAAAoR,EAAApR,GAAA,GAAAoR,OAAAtQ,KAAAwM,ePnFA,GAAAmc,EAAA,EAAA,IAAAjV,QOsFAnD,GAAA0M,cAAAxW,OACA8J,GAAAqY,qBAAAniB,IAAA,MACAyW,MAAA,KACAC,IAEA,mDADAtV,WAAAghB,aAAA5kB,GAAA+d,WAEA8G,GAAA,SAAA,iBAAA,eACAA,GAAA,OAAA","file":"demo.min.js","sourcesContent":["/*\n json-stringify-safe\n Like JSON.stringify, but doesn't throw on circular references.\n\n Originally forked from https://github.com/isaacs/json-stringify-safe\n version 5.0.1 on 3/8/2017 and modified to handle Errors serialization\n and IE8 compatibility. Tests for this are in test/vendor.\n\n ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE\n*/\n\nexports = module.exports = stringify;\nexports.getSerialize = serializer;\n\nfunction indexOf(haystack, needle) {\n for (var i = 0; i < haystack.length; ++i) {\n if (haystack[i] === needle) return i;\n }\n return -1;\n}\n\nfunction stringify(obj, replacer, spaces, cycleReplacer) {\n return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);\n}\n\n// https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106\nfunction stringifyError(value) {\n var err = {\n // These properties are implemented as magical getters and don't show up in for in\n stack: value.stack,\n message: value.message,\n name: value.name\n };\n\n for (var i in value) {\n if (Object.prototype.hasOwnProperty.call(value, i)) {\n err[i] = value[i];\n }\n }\n\n return err;\n}\n\nfunction serializer(replacer, cycleReplacer) {\n var stack = [];\n var keys = [];\n\n if (cycleReplacer == null) {\n cycleReplacer = function(key, value) {\n if (stack[0] === value) {\n return '[Circular ~]';\n }\n return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']';\n };\n }\n\n return function(key, value) {\n if (stack.length > 0) {\n var thisPos = indexOf(stack, this);\n ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);\n ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);\n\n if (~indexOf(stack, value)) {\n value = cycleReplacer.call(this, key, value);\n }\n } else {\n stack.push(value);\n }\n\n return replacer == null\n ? value instanceof Error ? stringifyError(value) : value\n : replacer.call(this, key, value);\n };\n}\n","var stringify = require('../vendor/json-stringify-safe/stringify');\n\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\nfunction isObject(what) {\n return typeof what === 'object' && what !== null;\n}\n\n// Yanked from https://git.io/vS8DV re-used under CC0\n// with some tiny modifications\nfunction isError(value) {\n switch ({}.toString.call(value)) {\n case '[object Error]':\n return true;\n case '[object Exception]':\n return true;\n case '[object DOMException]':\n return true;\n default:\n return value instanceof Error;\n }\n}\n\nfunction isErrorEvent(value) {\n return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]';\n}\n\nfunction isUndefined(what) {\n return what === void 0;\n}\n\nfunction isFunction(what) {\n return typeof what === 'function';\n}\n\nfunction isPlainObject(what) {\n return Object.prototype.toString.call(what) === '[object Object]';\n}\n\nfunction isString(what) {\n return Object.prototype.toString.call(what) === '[object String]';\n}\n\nfunction isArray(what) {\n return Object.prototype.toString.call(what) === '[object Array]';\n}\n\nfunction isEmptyObject(what) {\n if (!isPlainObject(what)) return false;\n\n for (var _ in what) {\n if (what.hasOwnProperty(_)) {\n return false;\n }\n }\n return true;\n}\n\nfunction supportsErrorEvent() {\n try {\n new ErrorEvent(''); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsFetch() {\n if (!('fetch' in _window)) return false;\n\n try {\n new Headers(); // eslint-disable-line no-new\n new Request(''); // eslint-disable-line no-new\n new Response(); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\n// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n// https://caniuse.com/#feat=referrer-policy\n// It doesn't. And it throw exception instead of ignoring this parameter...\n// REF: https://github.com/getsentry/raven-js/issues/1233\nfunction supportsReferrerPolicy() {\n if (!supportsFetch()) return false;\n\n try {\n // eslint-disable-next-line no-new\n new Request('pickleRick', {\n referrerPolicy: 'origin'\n });\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsPromiseRejectionEvent() {\n return typeof PromiseRejectionEvent === 'function';\n}\n\nfunction wrappedCallback(callback) {\n function dataCallback(data, original) {\n var normalizedData = callback(data) || data;\n if (original) {\n return original(normalizedData) || normalizedData;\n }\n return normalizedData;\n }\n\n return dataCallback;\n}\n\nfunction each(obj, callback) {\n var i, j;\n\n if (isUndefined(obj.length)) {\n for (i in obj) {\n if (hasKey(obj, i)) {\n callback.call(null, i, obj[i]);\n }\n }\n } else {\n j = obj.length;\n if (j) {\n for (i = 0; i < j; i++) {\n callback.call(null, i, obj[i]);\n }\n }\n }\n}\n\nfunction objectMerge(obj1, obj2) {\n if (!obj2) {\n return obj1;\n }\n each(obj2, function(key, value) {\n obj1[key] = value;\n });\n return obj1;\n}\n\n/**\n * This function is only used for react-native.\n * react-native freezes object that have already been sent over the\n * js bridge. We need this function in order to check if the object is frozen.\n * So it's ok that objectFrozen returns false if Object.isFrozen is not\n * supported because it's not relevant for other \"platforms\". See related issue:\n * https://github.com/getsentry/react-native-sentry/issues/57\n */\nfunction objectFrozen(obj) {\n if (!Object.isFrozen) {\n return false;\n }\n return Object.isFrozen(obj);\n}\n\nfunction truncate(str, max) {\n if (typeof max !== 'number') {\n throw new Error('2nd argument to `truncate` function should be a number');\n }\n if (typeof str !== 'string' || max === 0) {\n return str;\n }\n return str.length <= max ? str : str.substr(0, max) + '\\u2026';\n}\n\n/**\n * hasKey, a better form of hasOwnProperty\n * Example: hasKey(MainHostObject, property) === true/false\n *\n * @param {Object} host object to check property\n * @param {string} key to check\n */\nfunction hasKey(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\nfunction joinRegExp(patterns) {\n // Combine an array of regular expressions and strings into one large regexp\n // Be mad.\n var sources = [],\n i = 0,\n len = patterns.length,\n pattern;\n\n for (; i < len; i++) {\n pattern = patterns[i];\n if (isString(pattern)) {\n // If it's a string, we need to escape it\n // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n sources.push(pattern.replace(/([.*+?^=!:${}()|\\[\\]\\/\\\\])/g, '\\\\$1'));\n } else if (pattern && pattern.source) {\n // If it's a regexp already, we want to extract the source\n sources.push(pattern.source);\n }\n // Intentionally skip other cases\n }\n return new RegExp(sources.join('|'), 'i');\n}\n\nfunction urlencode(o) {\n var pairs = [];\n each(o, function(key, value) {\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n });\n return pairs.join('&');\n}\n\n// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B\n// intentionally using regex and not <a/> href parsing trick because React Native and other\n// environments where DOM might not be available\nfunction parseUrl(url) {\n if (typeof url !== 'string') return {};\n var match = url.match(/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$/);\n\n // coerce to undefined values to empty string so we don't get 'undefined'\n var query = match[6] || '';\n var fragment = match[8] || '';\n return {\n protocol: match[2],\n host: match[4],\n path: match[5],\n relative: match[5] + query + fragment // everything minus origin\n };\n}\nfunction uuid4() {\n var crypto = _window.crypto || _window.msCrypto;\n\n if (!isUndefined(crypto) && crypto.getRandomValues) {\n // Use window.crypto API if available\n // eslint-disable-next-line no-undef\n var arr = new Uint16Array(8);\n crypto.getRandomValues(arr);\n\n // set 4 in byte 7\n arr[3] = (arr[3] & 0xfff) | 0x4000;\n // set 2 most significant bits of byte 9 to '10'\n arr[4] = (arr[4] & 0x3fff) | 0x8000;\n\n var pad = function(num) {\n var v = num.toString(16);\n while (v.length < 4) {\n v = '0' + v;\n }\n return v;\n };\n\n return (\n pad(arr[0]) +\n pad(arr[1]) +\n pad(arr[2]) +\n pad(arr[3]) +\n pad(arr[4]) +\n pad(arr[5]) +\n pad(arr[6]) +\n pad(arr[7])\n );\n } else {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523\n return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (Math.random() * 16) | 0,\n v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @param elem\n * @returns {string}\n */\nfunction htmlTreeAsString(elem) {\n /* eslint no-extra-parens:0*/\n var MAX_TRAVERSE_HEIGHT = 5,\n MAX_OUTPUT_LEN = 80,\n out = [],\n height = 0,\n len = 0,\n separator = ' > ',\n sepLength = separator.length,\n nextStr;\n\n while (elem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = htmlElementAsString(elem);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds MAX_OUTPUT_LEN\n // (ignore this limit if we are on the first iteration)\n if (\n nextStr === 'html' ||\n (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)\n ) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n elem = elem.parentNode;\n }\n\n return out.reverse().join(separator);\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @param HTMLElement\n * @returns {string}\n */\nfunction htmlElementAsString(elem) {\n var out = [],\n className,\n classes,\n key,\n attr,\n i;\n\n if (!elem || !elem.tagName) {\n return '';\n }\n\n out.push(elem.tagName.toLowerCase());\n if (elem.id) {\n out.push('#' + elem.id);\n }\n\n className = elem.className;\n if (className && isString(className)) {\n classes = className.split(/\\s+/);\n for (i = 0; i < classes.length; i++) {\n out.push('.' + classes[i]);\n }\n }\n var attrWhitelist = ['type', 'name', 'title', 'alt'];\n for (i = 0; i < attrWhitelist.length; i++) {\n key = attrWhitelist[i];\n attr = elem.getAttribute(key);\n if (attr) {\n out.push('[' + key + '=\"' + attr + '\"]');\n }\n }\n return out.join('');\n}\n\n/**\n * Returns true if either a OR b is truthy, but not both\n */\nfunction isOnlyOneTruthy(a, b) {\n return !!(!!a ^ !!b);\n}\n\n/**\n * Returns true if both parameters are undefined\n */\nfunction isBothUndefined(a, b) {\n return isUndefined(a) && isUndefined(b);\n}\n\n/**\n * Returns true if the two input exception interfaces have the same content\n */\nfunction isSameException(ex1, ex2) {\n if (isOnlyOneTruthy(ex1, ex2)) return false;\n\n ex1 = ex1.values[0];\n ex2 = ex2.values[0];\n\n if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false;\n\n // in case both stacktraces are undefined, we can't decide so default to false\n if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false;\n\n return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);\n}\n\n/**\n * Returns true if the two input stack trace interfaces have the same content\n */\nfunction isSameStacktrace(stack1, stack2) {\n if (isOnlyOneTruthy(stack1, stack2)) return false;\n\n var frames1 = stack1.frames;\n var frames2 = stack2.frames;\n\n // Exit early if frame count differs\n if (frames1.length !== frames2.length) return false;\n\n // Iterate through every frame; bail out if anything differs\n var a, b;\n for (var i = 0; i < frames1.length; i++) {\n a = frames1[i];\n b = frames2[i];\n if (\n a.filename !== b.filename ||\n a.lineno !== b.lineno ||\n a.colno !== b.colno ||\n a['function'] !== b['function']\n )\n return false;\n }\n return true;\n}\n\n/**\n * Polyfill a method\n * @param obj object e.g. `document`\n * @param name method name present on object e.g. `addEventListener`\n * @param replacement replacement function\n * @param track {optional} record instrumentation to an array\n */\nfunction fill(obj, name, replacement, track) {\n if (obj == null) return;\n var orig = obj[name];\n obj[name] = replacement(orig);\n obj[name].__raven__ = true;\n obj[name].__orig__ = orig;\n if (track) {\n track.push([obj, name, orig]);\n }\n}\n\n/**\n * Join values in array\n * @param input array of values to be joined together\n * @param delimiter string to be placed in-between values\n * @returns {string}\n */\nfunction safeJoin(input, delimiter) {\n if (!isArray(input)) return '';\n\n var output = [];\n\n for (var i = 0; i < input.length; i++) {\n try {\n output.push(String(input[i]));\n } catch (e) {\n output.push('[value cannot be serialized]');\n }\n }\n\n return output.join(delimiter);\n}\n\n// Default Node.js REPL depth\nvar MAX_SERIALIZE_EXCEPTION_DEPTH = 3;\n// 50kB, as 100kB is max payload size, so half sounds reasonable\nvar MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024;\nvar MAX_SERIALIZE_KEYS_LENGTH = 40;\n\nfunction utf8Length(value) {\n return ~-encodeURI(value).split(/%..|./).length;\n}\n\nfunction jsonSize(value) {\n return utf8Length(JSON.stringify(value));\n}\n\nfunction serializeValue(value) {\n if (typeof value === 'string') {\n var maxLength = 40;\n return truncate(value, maxLength);\n } else if (\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'undefined'\n ) {\n return value;\n }\n\n var type = Object.prototype.toString.call(value);\n\n // Node.js REPL notation\n if (type === '[object Object]') return '[Object]';\n if (type === '[object Array]') return '[Array]';\n if (type === '[object Function]')\n return value.name ? '[Function: ' + value.name + ']' : '[Function]';\n\n return value;\n}\n\nfunction serializeObject(value, depth) {\n if (depth === 0) return serializeValue(value);\n\n if (isPlainObject(value)) {\n return Object.keys(value).reduce(function(acc, key) {\n acc[key] = serializeObject(value[key], depth - 1);\n return acc;\n }, {});\n } else if (Array.isArray(value)) {\n return value.map(function(val) {\n return serializeObject(val, depth - 1);\n });\n }\n\n return serializeValue(value);\n}\n\nfunction serializeException(ex, depth, maxSize) {\n if (!isPlainObject(ex)) return ex;\n\n depth = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_DEPTH : depth;\n maxSize = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_SIZE : maxSize;\n\n var serialized = serializeObject(ex, depth);\n\n if (jsonSize(stringify(serialized)) > maxSize) {\n return serializeException(ex, depth - 1);\n }\n\n return serialized;\n}\n\nfunction serializeKeysForMessage(keys, maxLength) {\n if (typeof keys === 'number' || typeof keys === 'string') return keys.toString();\n if (!Array.isArray(keys)) return '';\n\n keys = keys.filter(function(key) {\n return typeof key === 'string';\n });\n if (keys.length === 0) return '[object has no keys]';\n\n maxLength = typeof maxLength !== 'number' ? MAX_SERIALIZE_KEYS_LENGTH : maxLength;\n if (keys[0].length >= maxLength) return keys[0];\n\n for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) {\n var serialized = keys.slice(0, usedKeys).join(', ');\n if (serialized.length > maxLength) continue;\n if (usedKeys === keys.length) return serialized;\n return serialized + '\\u2026';\n }\n\n return '';\n}\n\nfunction sanitize(input, sanitizeKeys) {\n if (!isArray(sanitizeKeys) || (isArray(sanitizeKeys) && sanitizeKeys.length === 0))\n return input;\n\n var sanitizeRegExp = joinRegExp(sanitizeKeys);\n var sanitizeMask = '********';\n var safeInput;\n\n try {\n safeInput = JSON.parse(stringify(input));\n } catch (o_O) {\n return input;\n }\n\n function sanitizeWorker(workerInput) {\n if (isArray(workerInput)) {\n return workerInput.map(function(val) {\n return sanitizeWorker(val);\n });\n }\n\n if (isPlainObject(workerInput)) {\n return Object.keys(workerInput).reduce(function(acc, k) {\n if (sanitizeRegExp.test(k)) {\n acc[k] = sanitizeMask;\n } else {\n acc[k] = sanitizeWorker(workerInput[k]);\n }\n return acc;\n }, {});\n }\n\n return workerInput;\n }\n\n return sanitizeWorker(safeInput);\n}\n\nmodule.exports = {\n isObject: isObject,\n isError: isError,\n isErrorEvent: isErrorEvent,\n isUndefined: isUndefined,\n isFunction: isFunction,\n isPlainObject: isPlainObject,\n isString: isString,\n isArray: isArray,\n isEmptyObject: isEmptyObject,\n supportsErrorEvent: supportsErrorEvent,\n supportsFetch: supportsFetch,\n supportsReferrerPolicy: supportsReferrerPolicy,\n supportsPromiseRejectionEvent: supportsPromiseRejectionEvent,\n wrappedCallback: wrappedCallback,\n each: each,\n objectMerge: objectMerge,\n truncate: truncate,\n objectFrozen: objectFrozen,\n hasKey: hasKey,\n joinRegExp: joinRegExp,\n urlencode: urlencode,\n uuid4: uuid4,\n htmlTreeAsString: htmlTreeAsString,\n htmlElementAsString: htmlElementAsString,\n isSameException: isSameException,\n isSameStacktrace: isSameStacktrace,\n parseUrl: parseUrl,\n fill: fill,\n safeJoin: safeJoin,\n serializeException: serializeException,\n serializeKeysForMessage: serializeKeysForMessage,\n sanitize: sanitize\n};\n","var utils = require('../../src/utils');\n\n/*\n TraceKit - Cross brower stack traces\n\n This was originally forked from github.com/occ/TraceKit, but has since been\n largely re-written and is now maintained as part of raven-js. Tests for\n this are in test/vendor.\n\n MIT license\n*/\n\nvar TraceKit = {\n collectWindowErrors: true,\n debug: false\n};\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n// global reference to slice\nvar _slice = [].slice;\nvar UNKNOWN_FUNCTION = '?';\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types\nvar ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;\n\nfunction getLocationHref() {\n if (typeof document === 'undefined' || document.location == null) return '';\n\n return document.location.href;\n}\n\n/**\n * TraceKit.report: cross-browser processing of unhandled exceptions\n *\n * Syntax:\n * TraceKit.report.subscribe(function(stackInfo) { ... })\n * TraceKit.report.unsubscribe(function(stackInfo) { ... })\n * TraceKit.report(exception)\n * try { ...code... } catch(ex) { TraceKit.report(ex); }\n *\n * Supports:\n * - Firefox: full stack trace with line numbers, plus column number\n * on top frame; column number is not guaranteed\n * - Opera: full stack trace with line and column numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n * - IE: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n *\n * In theory, TraceKit should work on all of the following versions:\n * - IE5.5+ (only 8.0 tested)\n * - Firefox 0.9+ (only 3.5+ tested)\n * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require\n * Exceptions Have Stacktrace to be enabled in opera:config)\n * - Safari 3+ (only 4+ tested)\n * - Chrome 1+ (only 5+ tested)\n * - Konqueror 3.5+ (untested)\n *\n * Requires TraceKit.computeStackTrace.\n *\n * Tries to catch all unhandled exceptions and report them to the\n * subscribed handlers. Please note that TraceKit.report will rethrow the\n * exception. This is REQUIRED in order to get a useful stack trace in IE.\n * If the exception does not reach the top of the browser, you will only\n * get a stack trace from the point where TraceKit.report was called.\n *\n * Handlers receive a stackInfo object as described in the\n * TraceKit.computeStackTrace docs.\n */\nTraceKit.report = (function reportModuleWrapper() {\n var handlers = [],\n lastArgs = null,\n lastException = null,\n lastExceptionStack = null;\n\n /**\n * Add a crash handler.\n * @param {Function} handler\n */\n function subscribe(handler) {\n installGlobalHandler();\n handlers.push(handler);\n }\n\n /**\n * Remove a crash handler.\n * @param {Function} handler\n */\n function unsubscribe(handler) {\n for (var i = handlers.length - 1; i >= 0; --i) {\n if (handlers[i] === handler) {\n handlers.splice(i, 1);\n }\n }\n }\n\n /**\n * Remove all crash handlers.\n */\n function unsubscribeAll() {\n uninstallGlobalHandler();\n handlers = [];\n }\n\n /**\n * Dispatch stack information to all handlers.\n * @param {Object.<string, *>} stack\n */\n function notifyHandlers(stack, isWindowError) {\n var exception = null;\n if (isWindowError && !TraceKit.collectWindowErrors) {\n return;\n }\n for (var i in handlers) {\n if (handlers.hasOwnProperty(i)) {\n try {\n handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));\n } catch (inner) {\n exception = inner;\n }\n }\n }\n\n if (exception) {\n throw exception;\n }\n }\n\n var _oldOnerrorHandler, _onErrorHandlerInstalled;\n\n /**\n * Ensures all global unhandled exceptions are recorded.\n * Supported by Gecko and IE.\n * @param {string} msg Error message.\n * @param {string} url URL of script that generated the exception.\n * @param {(number|string)} lineNo The line number at which the error\n * occurred.\n * @param {?(number|string)} colNo The column number at which the error\n * occurred.\n * @param {?Error} ex The actual Error object.\n */\n function traceKitWindowOnError(msg, url, lineNo, colNo, ex) {\n var stack = null;\n // If 'ex' is ErrorEvent, get real Error from inside\n var exception = utils.isErrorEvent(ex) ? ex.error : ex;\n // If 'msg' is ErrorEvent, get real message from inside\n var message = utils.isErrorEvent(msg) ? msg.message : msg;\n\n if (lastExceptionStack) {\n TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(\n lastExceptionStack,\n url,\n lineNo,\n message\n );\n processLastException();\n } else if (exception && utils.isError(exception)) {\n // non-string `exception` arg; attempt to extract stack trace\n\n // New chrome and blink send along a real error object\n // Let's just report that like a normal error.\n // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror\n stack = TraceKit.computeStackTrace(exception);\n notifyHandlers(stack, true);\n } else {\n var location = {\n url: url,\n line: lineNo,\n column: colNo\n };\n\n var name = undefined;\n var groups;\n\n if ({}.toString.call(message) === '[object String]') {\n var groups = message.match(ERROR_TYPES_RE);\n if (groups) {\n name = groups[1];\n message = groups[2];\n }\n }\n\n location.func = UNKNOWN_FUNCTION;\n\n stack = {\n name: name,\n message: message,\n url: getLocationHref(),\n stack: [location]\n };\n notifyHandlers(stack, true);\n }\n\n if (_oldOnerrorHandler) {\n return _oldOnerrorHandler.apply(this, arguments);\n }\n\n return false;\n }\n\n function installGlobalHandler() {\n if (_onErrorHandlerInstalled) {\n return;\n }\n _oldOnerrorHandler = _window.onerror;\n _window.onerror = traceKitWindowOnError;\n _onErrorHandlerInstalled = true;\n }\n\n function uninstallGlobalHandler() {\n if (!_onErrorHandlerInstalled) {\n return;\n }\n _window.onerror = _oldOnerrorHandler;\n _onErrorHandlerInstalled = false;\n _oldOnerrorHandler = undefined;\n }\n\n function processLastException() {\n var _lastExceptionStack = lastExceptionStack,\n _lastArgs = lastArgs;\n lastArgs = null;\n lastExceptionStack = null;\n lastException = null;\n notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));\n }\n\n /**\n * Reports an unhandled Error to TraceKit.\n * @param {Error} ex\n * @param {?boolean} rethrow If false, do not re-throw the exception.\n * Only used for window.onerror to not cause an infinite loop of\n * rethrowing.\n */\n function report(ex, rethrow) {\n var args = _slice.call(arguments, 1);\n if (lastExceptionStack) {\n if (lastException === ex) {\n return; // already caught by an inner catch block, ignore\n } else {\n processLastException();\n }\n }\n\n var stack = TraceKit.computeStackTrace(ex);\n lastExceptionStack = stack;\n lastException = ex;\n lastArgs = args;\n\n // If the stack trace is incomplete, wait for 2 seconds for\n // slow slow IE to see if onerror occurs or not before reporting\n // this exception; otherwise, we will end up with an incomplete\n // stack trace\n setTimeout(function() {\n if (lastException === ex) {\n processLastException();\n }\n }, stack.incomplete ? 2000 : 0);\n\n if (rethrow !== false) {\n throw ex; // re-throw to propagate to the top level (and cause window.onerror)\n }\n }\n\n report.subscribe = subscribe;\n report.unsubscribe = unsubscribe;\n report.uninstall = unsubscribeAll;\n return report;\n})();\n\n/**\n * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript\n *\n * Syntax:\n * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)\n * Returns:\n * s.name - exception name\n * s.message - exception message\n * s.stack[i].url - JavaScript or HTML file URL\n * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)\n * s.stack[i].args - arguments passed to the function, if known\n * s.stack[i].line - line number, if known\n * s.stack[i].column - column number, if known\n *\n * Supports:\n * - Firefox: full stack trace with line numbers and unreliable column\n * number on top frame\n * - Opera 10: full stack trace with line and column numbers\n * - Opera 9-: full stack trace with line numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the topmost stacktrace element\n * only\n * - IE: no line numbers whatsoever\n *\n * Tries to guess names of anonymous functions by looking for assignments\n * in the source code. In IE and Safari, we have to guess source file names\n * by searching for function bodies inside all page scripts. This will not\n * work for scripts that are loaded cross-domain.\n * Here be dragons: some function names may be guessed incorrectly, and\n * duplicate functions may be mismatched.\n *\n * TraceKit.computeStackTrace should only be used for tracing purposes.\n * Logging of unhandled exceptions should be done with TraceKit.report,\n * which builds on top of TraceKit.computeStackTrace and provides better\n * IE support by utilizing the window.onerror event to retrieve information\n * about the top of the stack.\n *\n * Note: In IE and Safari, no stack trace is recorded on the Error object,\n * so computeStackTrace instead walks its *own* chain of callers.\n * This means that:\n * * in Safari, some methods may be missing from the stack trace;\n * * in IE, the topmost function in the stack trace will always be the\n * caller of computeStackTrace.\n *\n * This is okay for tracing (because you are likely to be calling\n * computeStackTrace from the function you want to be the topmost element\n * of the stack trace anyway), but not okay for logging unhandled\n * exceptions (because your catch block will likely be far away from the\n * inner function that actually caused the exception).\n *\n */\nTraceKit.computeStackTrace = (function computeStackTraceWrapper() {\n // Contents of Exception in various browsers.\n //\n // SAFARI:\n // ex.message = Can't find variable: qq\n // ex.line = 59\n // ex.sourceId = 580238192\n // ex.sourceURL = http://...\n // ex.expressionBeginOffset = 96\n // ex.expressionCaretOffset = 98\n // ex.expressionEndOffset = 98\n // ex.name = ReferenceError\n //\n // FIREFOX:\n // ex.message = qq is not defined\n // ex.fileName = http://...\n // ex.lineNumber = 59\n // ex.columnNumber = 69\n // ex.stack = ...stack trace... (see the example below)\n // ex.name = ReferenceError\n //\n // CHROME:\n // ex.message = qq is not defined\n // ex.name = ReferenceError\n // ex.type = not_defined\n // ex.arguments = ['aa']\n // ex.stack = ...stack trace...\n //\n // INTERNET EXPLORER:\n // ex.message = ...\n // ex.name = ReferenceError\n //\n // OPERA:\n // ex.message = ...message... (see the example below)\n // ex.name = ReferenceError\n // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)\n // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'\n\n /**\n * Computes stack trace information from the stack property.\n * Chrome and Gecko use this property.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceFromStackProp(ex) {\n if (typeof ex.stack === 'undefined' || !ex.stack) return;\n\n var chrome = /^\\s*at (?:(.*?) ?\\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\\/).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i;\n var winjs = /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i;\n // NOTE: blob urls are now supposed to always have an origin, therefore it's format\n // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\\/` as well\n var gecko = /^\\s*(.*?)(?:\\((.*?)\\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\\/.*?|\\[native code\\]|[^@]*bundle)(?::(\\d+))?(?::(\\d+))?\\s*$/i;\n // Used to additionally parse URL/line/column from eval frames\n var geckoEval = /(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i;\n var chromeEval = /\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/;\n var lines = ex.stack.split('\\n');\n var stack = [];\n var submatch;\n var parts;\n var element;\n var reference = /^(.*) is undefined$/.exec(ex.message);\n\n for (var i = 0, j = lines.length; i < j; ++i) {\n if ((parts = chrome.exec(lines[i]))) {\n var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line\n var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line\n if (isEval && (submatch = chromeEval.exec(parts[2]))) {\n // throw out eval line/column and use top-most line/column number\n parts[2] = submatch[1]; // url\n parts[3] = submatch[2]; // line\n parts[4] = submatch[3]; // column\n }\n element = {\n url: !isNative ? parts[2] : null,\n func: parts[1] || UNKNOWN_FUNCTION,\n args: isNative ? [parts[2]] : [],\n line: parts[3] ? +parts[3] : null,\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = winjs.exec(lines[i]))) {\n element = {\n url: parts[2],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: [],\n line: +parts[3],\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = gecko.exec(lines[i]))) {\n var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;\n if (isEval && (submatch = geckoEval.exec(parts[3]))) {\n // throw out eval line/column and use top-most line number\n parts[3] = submatch[1];\n parts[4] = submatch[2];\n parts[5] = null; // no column when eval\n } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {\n // FireFox uses this awesome columnNumber property for its top frame\n // Also note, Firefox's column number is 0-based and everything else expects 1-based,\n // so adding 1\n // NOTE: this hack doesn't work if top-most frame is eval\n stack[0].column = ex.columnNumber + 1;\n }\n element = {\n url: parts[3],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: parts[2] ? parts[2].split(',') : [],\n line: parts[4] ? +parts[4] : null,\n column: parts[5] ? +parts[5] : null\n };\n } else {\n continue;\n }\n\n if (!element.func && element.line) {\n element.func = UNKNOWN_FUNCTION;\n }\n\n stack.push(element);\n }\n\n if (!stack.length) {\n return null;\n }\n\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n }\n\n /**\n * Adds information about the first frame to incomplete stack traces.\n * Safari and IE require this to get complete data on the first frame.\n * @param {Object.<string, *>} stackInfo Stack trace information from\n * one of the compute* methods.\n * @param {string} url The URL of the script that caused an error.\n * @param {(number|string)} lineNo The line number of the script that\n * caused an error.\n * @param {string=} message The error generated by the browser, which\n * hopefully contains the name of the object that caused the error.\n * @return {boolean} Whether or not the stack information was\n * augmented.\n */\n function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {\n var initial = {\n url: url,\n line: lineNo\n };\n\n if (initial.url && initial.line) {\n stackInfo.incomplete = false;\n\n if (!initial.func) {\n initial.func = UNKNOWN_FUNCTION;\n }\n\n if (stackInfo.stack.length > 0) {\n if (stackInfo.stack[0].url === initial.url) {\n if (stackInfo.stack[0].line === initial.line) {\n return false; // already in stack trace\n } else if (\n !stackInfo.stack[0].line &&\n stackInfo.stack[0].func === initial.func\n ) {\n stackInfo.stack[0].line = initial.line;\n return false;\n }\n }\n }\n\n stackInfo.stack.unshift(initial);\n stackInfo.partial = true;\n return true;\n } else {\n stackInfo.incomplete = true;\n }\n\n return false;\n }\n\n /**\n * Computes stack trace information by walking the arguments.caller\n * chain at the time the exception occurred. This will cause earlier\n * frames to be missed but is the only way to get any stack trace in\n * Safari and IE. The top frame is restored by\n * {@link augmentStackTraceWithInitialElement}.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceByWalkingCallerChain(ex, depth) {\n var functionName = /function\\s+([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*)?\\s*\\(/i,\n stack = [],\n funcs = {},\n recursion = false,\n parts,\n item,\n source;\n\n for (\n var curr = computeStackTraceByWalkingCallerChain.caller;\n curr && !recursion;\n curr = curr.caller\n ) {\n if (curr === computeStackTrace || curr === TraceKit.report) {\n // console.log('skipping internal function');\n continue;\n }\n\n item = {\n url: null,\n func: UNKNOWN_FUNCTION,\n line: null,\n column: null\n };\n\n if (curr.name) {\n item.func = curr.name;\n } else if ((parts = functionName.exec(curr.toString()))) {\n item.func = parts[1];\n }\n\n if (typeof item.func === 'undefined') {\n try {\n item.func = parts.input.substring(0, parts.input.indexOf('{'));\n } catch (e) {}\n }\n\n if (funcs['' + curr]) {\n recursion = true;\n } else {\n funcs['' + curr] = true;\n }\n\n stack.push(item);\n }\n\n if (depth) {\n // console.log('depth is ' + depth);\n // console.log('stack is ' + stack.length);\n stack.splice(0, depth);\n }\n\n var result = {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n augmentStackTraceWithInitialElement(\n result,\n ex.sourceURL || ex.fileName,\n ex.line || ex.lineNumber,\n ex.message || ex.description\n );\n return result;\n }\n\n /**\n * Computes a stack trace for an exception.\n * @param {Error} ex\n * @param {(string|number)=} depth\n */\n function computeStackTrace(ex, depth) {\n var stack = null;\n depth = depth == null ? 0 : +depth;\n\n try {\n stack = computeStackTraceFromStackProp(ex);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n\n try {\n stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref()\n };\n }\n\n computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;\n computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp;\n\n return computeStackTrace;\n})();\n\nmodule.exports = TraceKit;\n","/*\n * JavaScript MD5\n * https://github.com/blueimp/JavaScript-MD5\n *\n * Copyright 2011, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * https://opensource.org/licenses/MIT\n *\n * Based on\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for more info.\n */\n\n/*\n* Add integers, wrapping at 2^32. This uses 16-bit operations internally\n* to work around bugs in some JS interpreters.\n*/\nfunction safeAdd(x, y) {\n var lsw = (x & 0xffff) + (y & 0xffff);\n var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n}\n\n/*\n* Bitwise rotate a 32-bit number to the left.\n*/\nfunction bitRotateLeft(num, cnt) {\n return (num << cnt) | (num >>> (32 - cnt));\n}\n\n/*\n* These functions implement the four basic operations the algorithm uses.\n*/\nfunction md5cmn(q, a, b, x, s, t) {\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n}\nfunction md5ff(a, b, c, d, x, s, t) {\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\n}\nfunction md5gg(a, b, c, d, x, s, t) {\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\n}\nfunction md5hh(a, b, c, d, x, s, t) {\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\n}\nfunction md5ii(a, b, c, d, x, s, t) {\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\n/*\n* Calculate the MD5 of an array of little-endian words, and a bit length.\n*/\nfunction binlMD5(x, len) {\n /* append padding */\n x[len >> 5] |= 0x80 << (len % 32);\n x[(((len + 64) >>> 9) << 4) + 14] = len;\n\n var i;\n var olda;\n var oldb;\n var oldc;\n var oldd;\n var a = 1732584193;\n var b = -271733879;\n var c = -1732584194;\n var d = 271733878;\n\n for (i = 0; i < x.length; i += 16) {\n olda = a;\n oldb = b;\n oldc = c;\n oldd = d;\n\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\n\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\n\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\n\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\n\n a = safeAdd(a, olda);\n b = safeAdd(b, oldb);\n c = safeAdd(c, oldc);\n d = safeAdd(d, oldd);\n }\n return [a, b, c, d];\n}\n\n/*\n* Convert an array of little-endian words to a string\n*/\nfunction binl2rstr(input) {\n var i;\n var output = '';\n var length32 = input.length * 32;\n for (i = 0; i < length32; i += 8) {\n output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff);\n }\n return output;\n}\n\n/*\n* Convert a raw string to an array of little-endian words\n* Characters >255 have their high-byte silently ignored.\n*/\nfunction rstr2binl(input) {\n var i;\n var output = [];\n output[(input.length >> 2) - 1] = undefined;\n for (i = 0; i < output.length; i += 1) {\n output[i] = 0;\n }\n var length8 = input.length * 8;\n for (i = 0; i < length8; i += 8) {\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32);\n }\n return output;\n}\n\n/*\n* Calculate the MD5 of a raw string\n*/\nfunction rstrMD5(s) {\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\n}\n\n/*\n* Calculate the HMAC-MD5, of a key and some data (raw strings)\n*/\nfunction rstrHMACMD5(key, data) {\n var i;\n var bkey = rstr2binl(key);\n var ipad = [];\n var opad = [];\n var hash;\n ipad[15] = opad[15] = undefined;\n if (bkey.length > 16) {\n bkey = binlMD5(bkey, key.length * 8);\n }\n for (i = 0; i < 16; i += 1) {\n ipad[i] = bkey[i] ^ 0x36363636;\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\n }\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\n}\n\n/*\n* Convert a raw string to a hex string\n*/\nfunction rstr2hex(input) {\n var hexTab = '0123456789abcdef';\n var output = '';\n var x;\n var i;\n for (i = 0; i < input.length; i += 1) {\n x = input.charCodeAt(i);\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\n }\n return output;\n}\n\n/*\n* Encode a string as utf-8\n*/\nfunction str2rstrUTF8(input) {\n return unescape(encodeURIComponent(input));\n}\n\n/*\n* Take string arguments and return either raw or hex encoded strings\n*/\nfunction rawMD5(s) {\n return rstrMD5(str2rstrUTF8(s));\n}\nfunction hexMD5(s) {\n return rstr2hex(rawMD5(s));\n}\nfunction rawHMACMD5(k, d) {\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\n}\nfunction hexHMACMD5(k, d) {\n return rstr2hex(rawHMACMD5(k, d));\n}\n\nfunction md5(string, key, raw) {\n if (!key) {\n if (!raw) {\n return hexMD5(string);\n }\n return rawMD5(string);\n }\n if (!raw) {\n return hexHMACMD5(key, string);\n }\n return rawHMACMD5(key, string);\n}\n\nmodule.exports = md5;\n","function RavenConfigError(message) {\n this.name = 'RavenConfigError';\n this.message = message;\n}\nRavenConfigError.prototype = new Error();\nRavenConfigError.prototype.constructor = RavenConfigError;\n\nmodule.exports = RavenConfigError;\n","var utils = require('./utils');\n\nvar wrapMethod = function(console, level, callback) {\n var originalConsoleLevel = console[level];\n var originalConsole = console;\n\n if (!(level in console)) {\n return;\n }\n\n var sentryLevel = level === 'warn' ? 'warning' : level;\n\n console[level] = function() {\n var args = [].slice.call(arguments);\n\n var msg = utils.safeJoin(args, ' ');\n var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}};\n\n if (level === 'assert') {\n if (args[0] === false) {\n // Default browsers message\n msg =\n 'Assertion failed: ' + (utils.safeJoin(args.slice(1), ' ') || 'console.assert');\n data.extra.arguments = args.slice(1);\n callback && callback(msg, data);\n }\n } else {\n callback && callback(msg, data);\n }\n\n // this fails for some browsers. :(\n if (originalConsoleLevel) {\n // IE9 doesn't allow calling apply on console functions directly\n // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193\n Function.prototype.apply.call(originalConsoleLevel, originalConsole, args);\n }\n };\n};\n\nmodule.exports = {\n wrapMethod: wrapMethod\n};\n","/*global XDomainRequest:false */\n\nvar TraceKit = require('../vendor/TraceKit/tracekit');\nvar stringify = require('../vendor/json-stringify-safe/stringify');\nvar md5 = require('../vendor/md5/md5');\nvar RavenConfigError = require('./configError');\n\nvar utils = require('./utils');\nvar isError = utils.isError;\nvar isObject = utils.isObject;\nvar isPlainObject = utils.isPlainObject;\nvar isErrorEvent = utils.isErrorEvent;\nvar isUndefined = utils.isUndefined;\nvar isFunction = utils.isFunction;\nvar isString = utils.isString;\nvar isArray = utils.isArray;\nvar isEmptyObject = utils.isEmptyObject;\nvar each = utils.each;\nvar objectMerge = utils.objectMerge;\nvar truncate = utils.truncate;\nvar objectFrozen = utils.objectFrozen;\nvar hasKey = utils.hasKey;\nvar joinRegExp = utils.joinRegExp;\nvar urlencode = utils.urlencode;\nvar uuid4 = utils.uuid4;\nvar htmlTreeAsString = utils.htmlTreeAsString;\nvar isSameException = utils.isSameException;\nvar isSameStacktrace = utils.isSameStacktrace;\nvar parseUrl = utils.parseUrl;\nvar fill = utils.fill;\nvar supportsFetch = utils.supportsFetch;\nvar supportsReferrerPolicy = utils.supportsReferrerPolicy;\nvar serializeKeysForMessage = utils.serializeKeysForMessage;\nvar serializeException = utils.serializeException;\nvar sanitize = utils.sanitize;\n\nvar wrapConsoleMethod = require('./console').wrapMethod;\n\nvar dsnKeys = 'source protocol user pass host port path'.split(' '),\n dsnPattern = /^(?:(\\w+):)?\\/\\/(?:(\\w+)(:\\w+)?@)?([\\w\\.-]+)(?::(\\d+))?(\\/.*)/;\n\nfunction now() {\n return +new Date();\n}\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _document = _window.document;\nvar _navigator = _window.navigator;\n\nfunction keepOriginalCallback(original, callback) {\n return isFunction(callback)\n ? function(data) {\n return callback(data, original);\n }\n : callback;\n}\n\n// First, check for JSON support\n// If there is no JSON, we no-op the core features of Raven\n// since JSON is required to encode the payload\nfunction Raven() {\n this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify);\n // Raven can run in contexts where there's no document (react-native)\n this._hasDocument = !isUndefined(_document);\n this._hasNavigator = !isUndefined(_navigator);\n this._lastCapturedException = null;\n this._lastData = null;\n this._lastEventId = null;\n this._globalServer = null;\n this._globalKey = null;\n this._globalProject = null;\n this._globalContext = {};\n this._globalOptions = {\n // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin\n release: _window.SENTRY_RELEASE && _window.SENTRY_RELEASE.id,\n logger: 'javascript',\n ignoreErrors: [],\n ignoreUrls: [],\n whitelistUrls: [],\n includePaths: [],\n headers: null,\n collectWindowErrors: true,\n captureUnhandledRejections: true,\n maxMessageLength: 0,\n // By default, truncates URL values to 250 chars\n maxUrlLength: 250,\n stackTraceLimit: 50,\n autoBreadcrumbs: true,\n instrument: true,\n sampleRate: 1,\n sanitizeKeys: []\n };\n this._fetchDefaults = {\n method: 'POST',\n keepalive: true,\n // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n // https://caniuse.com/#feat=referrer-policy\n // It doesn't. And it throw exception instead of ignoring this parameter...\n // REF: https://github.com/getsentry/raven-js/issues/1233\n referrerPolicy: supportsReferrerPolicy() ? 'origin' : ''\n };\n this._ignoreOnError = 0;\n this._isRavenInstalled = false;\n this._originalErrorStackTraceLimit = Error.stackTraceLimit;\n // capture references to window.console *and* all its methods first\n // before the console plugin has a chance to monkey patch\n this._originalConsole = _window.console || {};\n this._originalConsoleMethods = {};\n this._plugins = [];\n this._startTime = now();\n this._wrappedBuiltIns = [];\n this._breadcrumbs = [];\n this._lastCapturedEvent = null;\n this._keypressTimeout;\n this._location = _window.location;\n this._lastHref = this._location && this._location.href;\n this._resetBackoff();\n\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsole) {\n this._originalConsoleMethods[method] = this._originalConsole[method];\n }\n}\n\n/*\n * The core Raven singleton\n *\n * @this {Raven}\n */\n\nRaven.prototype = {\n // Hardcode version string so that raven source can be loaded directly via\n // webpack (using a build step causes webpack #1617). Grunt verifies that\n // this value matches package.json during build.\n // See: https://github.com/getsentry/raven-js/issues/465\n VERSION: '3.24.2',\n\n debug: false,\n\n TraceKit: TraceKit, // alias to TraceKit\n\n /*\n * Configure Raven with a DSN and extra options\n *\n * @param {string} dsn The public Sentry DSN\n * @param {object} options Set of global options [optional]\n * @return {Raven}\n */\n config: function(dsn, options) {\n var self = this;\n\n if (self._globalServer) {\n this._logDebug('error', 'Error: Raven has already been configured');\n return self;\n }\n if (!dsn) return self;\n\n var globalOptions = self._globalOptions;\n\n // merge in options\n if (options) {\n each(options, function(key, value) {\n // tags and extra are special and need to be put into context\n if (key === 'tags' || key === 'extra' || key === 'user') {\n self._globalContext[key] = value;\n } else {\n globalOptions[key] = value;\n }\n });\n }\n\n self.setDSN(dsn);\n\n // \"Script error.\" is hard coded into browsers for errors that it can't read.\n // this is the result of a script being pulled in from an external domain and CORS.\n globalOptions.ignoreErrors.push(/^Script error\\.?$/);\n globalOptions.ignoreErrors.push(/^Javascript error: Script error\\.? on line 0$/);\n\n // join regexp rules into one big rule\n globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);\n globalOptions.ignoreUrls = globalOptions.ignoreUrls.length\n ? joinRegExp(globalOptions.ignoreUrls)\n : false;\n globalOptions.whitelistUrls = globalOptions.whitelistUrls.length\n ? joinRegExp(globalOptions.whitelistUrls)\n : false;\n globalOptions.includePaths = joinRegExp(globalOptions.includePaths);\n globalOptions.maxBreadcrumbs = Math.max(\n 0,\n Math.min(globalOptions.maxBreadcrumbs || 100, 100)\n ); // default and hard limit is 100\n\n var autoBreadcrumbDefaults = {\n xhr: true,\n console: true,\n dom: true,\n location: true,\n sentry: true\n };\n\n var autoBreadcrumbs = globalOptions.autoBreadcrumbs;\n if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {\n autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);\n } else if (autoBreadcrumbs !== false) {\n autoBreadcrumbs = autoBreadcrumbDefaults;\n }\n globalOptions.autoBreadcrumbs = autoBreadcrumbs;\n\n var instrumentDefaults = {\n tryCatch: true\n };\n\n var instrument = globalOptions.instrument;\n if ({}.toString.call(instrument) === '[object Object]') {\n instrument = objectMerge(instrumentDefaults, instrument);\n } else if (instrument !== false) {\n instrument = instrumentDefaults;\n }\n globalOptions.instrument = instrument;\n\n TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;\n\n // return for chaining\n return self;\n },\n\n /*\n * Installs a global window.onerror error handler\n * to capture and report uncaught exceptions.\n * At this point, install() is required to be called due\n * to the way TraceKit is set up.\n *\n * @return {Raven}\n */\n install: function() {\n var self = this;\n if (self.isSetup() && !self._isRavenInstalled) {\n TraceKit.report.subscribe(function() {\n self._handleOnErrorStackInfo.apply(self, arguments);\n });\n\n if (self._globalOptions.captureUnhandledRejections) {\n self._attachPromiseRejectionHandler();\n }\n\n self._patchFunctionToString();\n\n if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) {\n self._instrumentTryCatch();\n }\n\n if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs();\n\n // Install all of the plugins\n self._drainPlugins();\n\n self._isRavenInstalled = true;\n }\n\n Error.stackTraceLimit = self._globalOptions.stackTraceLimit;\n return this;\n },\n\n /*\n * Set the DSN (can be called multiple time unlike config)\n *\n * @param {string} dsn The public Sentry DSN\n */\n setDSN: function(dsn) {\n var self = this,\n uri = self._parseDSN(dsn),\n lastSlash = uri.path.lastIndexOf('/'),\n path = uri.path.substr(1, lastSlash);\n\n self._dsn = dsn;\n self._globalKey = uri.user;\n self._globalSecret = uri.pass && uri.pass.substr(1);\n self._globalProject = uri.path.substr(lastSlash + 1);\n\n self._globalServer = self._getGlobalServer(uri);\n\n self._globalEndpoint =\n self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/';\n\n // Reset backoff state since we may be pointing at a\n // new project/server\n this._resetBackoff();\n },\n\n /*\n * Wrap code within a context so Raven can capture errors\n * reliably across domains that is executed immediately.\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The callback to be immediately executed within the context\n * @param {array} args An array of arguments to be called with the callback [optional]\n */\n context: function(options, func, args) {\n if (isFunction(options)) {\n args = func || [];\n func = options;\n options = undefined;\n }\n\n return this.wrap(options, func).apply(this, args);\n },\n\n /*\n * Wrap code within a context and returns back a new function to be executed\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The function to be wrapped in a new context\n * @param {function} func A function to call before the try/catch wrapper [optional, private]\n * @return {function} The newly wrapped functions with a context\n */\n wrap: function(options, func, _before) {\n var self = this;\n // 1 argument has been passed, and it's not a function\n // so just return it\n if (isUndefined(func) && !isFunction(options)) {\n return options;\n }\n\n // options is optional\n if (isFunction(options)) {\n func = options;\n options = undefined;\n }\n\n // At this point, we've passed along 2 arguments, and the second one\n // is not a function either, so we'll just return the second argument.\n if (!isFunction(func)) {\n return func;\n }\n\n // We don't wanna wrap it twice!\n try {\n if (func.__raven__) {\n return func;\n }\n\n // If this has already been wrapped in the past, return that\n if (func.__raven_wrapper__) {\n return func.__raven_wrapper__;\n }\n } catch (e) {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return func;\n }\n\n function wrapped() {\n var args = [],\n i = arguments.length,\n deep = !options || (options && options.deep !== false);\n\n if (_before && isFunction(_before)) {\n _before.apply(this, arguments);\n }\n\n // Recursively wrap all of a function's arguments that are\n // functions themselves.\n while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i];\n\n try {\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means Raven caught an error invoking your application code. This is\n // expected behavior and NOT indicative of a bug with Raven.js.\n return func.apply(this, args);\n } catch (e) {\n self._ignoreNextOnError();\n self.captureException(e, options);\n throw e;\n }\n }\n\n // copy over properties of the old function\n for (var property in func) {\n if (hasKey(func, property)) {\n wrapped[property] = func[property];\n }\n }\n wrapped.prototype = func.prototype;\n\n func.__raven_wrapper__ = wrapped;\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n wrapped.__raven__ = true;\n wrapped.__orig__ = func;\n\n return wrapped;\n },\n\n /**\n * Uninstalls the global error handler.\n *\n * @return {Raven}\n */\n uninstall: function() {\n TraceKit.report.uninstall();\n\n this._detachPromiseRejectionHandler();\n this._unpatchFunctionToString();\n this._restoreBuiltIns();\n this._restoreConsole();\n\n Error.stackTraceLimit = this._originalErrorStackTraceLimit;\n this._isRavenInstalled = false;\n\n return this;\n },\n\n /**\n * Callback used for `unhandledrejection` event\n *\n * @param {PromiseRejectionEvent} event An object containing\n * promise: the Promise that was rejected\n * reason: the value with which the Promise was rejected\n * @return void\n */\n _promiseRejectionHandler: function(event) {\n this._logDebug('debug', 'Raven caught unhandled promise rejection:', event);\n this.captureException(event.reason, {\n extra: {\n unhandledPromiseRejection: true\n }\n });\n },\n\n /**\n * Installs the global promise rejection handler.\n *\n * @return {raven}\n */\n _attachPromiseRejectionHandler: function() {\n this._promiseRejectionHandler = this._promiseRejectionHandler.bind(this);\n _window.addEventListener &&\n _window.addEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Uninstalls the global promise rejection handler.\n *\n * @return {raven}\n */\n _detachPromiseRejectionHandler: function() {\n _window.removeEventListener &&\n _window.removeEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Manually capture an exception and send it over to Sentry\n *\n * @param {error} ex An exception to be logged\n * @param {object} options A specific set of options for this error [optional]\n * @return {Raven}\n */\n captureException: function(ex, options) {\n options = objectMerge({trimHeadFrames: 0}, options ? options : {});\n\n if (isErrorEvent(ex) && ex.error) {\n // If it is an ErrorEvent with `error` property, extract it to get actual Error\n ex = ex.error;\n } else if (isError(ex)) {\n // we have a real Error object\n ex = ex;\n } else if (isPlainObject(ex)) {\n // If it is plain Object, serialize it manually and extract options\n // This will allow us to group events based on top-level keys\n // which is much better than creating new group when any key/value change\n options = this._getCaptureExceptionOptionsFromPlainObject(options, ex);\n ex = new Error(options.message);\n } else {\n // If none of previous checks were valid, then it means that\n // it's not a plain Object\n // it's not a valid ErrorEvent (one with an error property)\n // it's not an Error\n // So bail out and capture it as a simple message:\n return this.captureMessage(\n ex,\n objectMerge(options, {\n stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace\n trimHeadFrames: options.trimHeadFrames + 1\n })\n );\n }\n\n // Store the raw exception object for potential debugging and introspection\n this._lastCapturedException = ex;\n\n // TraceKit.report will re-raise any exception passed to it,\n // which means you have to wrap it in try/catch. Instead, we\n // can wrap it here and only re-raise if TraceKit.report\n // raises an exception different from the one we asked to\n // report on.\n try {\n var stack = TraceKit.computeStackTrace(ex);\n this._handleStackInfo(stack, options);\n } catch (ex1) {\n if (ex !== ex1) {\n throw ex1;\n }\n }\n\n return this;\n },\n\n _getCaptureExceptionOptionsFromPlainObject: function(currentOptions, ex) {\n var exKeys = Object.keys(ex).sort();\n var options = objectMerge(currentOptions, {\n message:\n 'Non-Error exception captured with keys: ' + serializeKeysForMessage(exKeys),\n fingerprint: [md5(exKeys)],\n extra: currentOptions.extra || {}\n });\n options.extra.__serialized__ = serializeException(ex);\n\n return options;\n },\n\n /*\n * Manually send a message to Sentry\n *\n * @param {string} msg A plain message to be captured in Sentry\n * @param {object} options A specific set of options for this message [optional]\n * @return {Raven}\n */\n captureMessage: function(msg, options) {\n // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an\n // early call; we'll error on the side of logging anything called before configuration since it's\n // probably something you should see:\n if (\n !!this._globalOptions.ignoreErrors.test &&\n this._globalOptions.ignoreErrors.test(msg)\n ) {\n return;\n }\n\n options = options || {};\n msg = msg + ''; // Make sure it's actually a string\n\n var data = objectMerge(\n {\n message: msg\n },\n options\n );\n\n var ex;\n // Generate a \"synthetic\" stack trace from this point.\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative\n // of a bug with Raven.js. Sentry generates synthetic traces either by configuration,\n // or if it catches a thrown object without a \"stack\" property.\n try {\n throw new Error(msg);\n } catch (ex1) {\n ex = ex1;\n }\n\n // null exception name so `Error` isn't prefixed to msg\n ex.name = null;\n var stack = TraceKit.computeStackTrace(ex);\n\n // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]\n var initialCall = isArray(stack.stack) && stack.stack[1];\n\n // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call\n // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd\n // initialCall => captureException(string) => captureMessage(string)\n if (initialCall && initialCall.func === 'Raven.captureException') {\n initialCall = stack.stack[2];\n }\n\n var fileurl = (initialCall && initialCall.url) || '';\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n if (this._globalOptions.stacktrace || (options && options.stacktrace)) {\n // fingerprint on msg, not stack trace (legacy behavior, could be revisited)\n data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;\n\n options = objectMerge(\n {\n trimHeadFrames: 0\n },\n options\n );\n // Since we know this is a synthetic trace, the top frame (this function call)\n // MUST be from Raven.js, so mark it for trimming\n // We add to the trim counter so that callers can choose to trim extra frames, such\n // as utility functions.\n options.trimHeadFrames += 1;\n\n var frames = this._prepareFrames(stack, options);\n data.stacktrace = {\n // Sentry expects frames oldest to newest\n frames: frames.reverse()\n };\n }\n\n // Make sure that fingerprint is always wrapped in an array\n if (data.fingerprint) {\n data.fingerprint = isArray(data.fingerprint)\n ? data.fingerprint\n : [data.fingerprint];\n }\n\n // Fire away!\n this._send(data);\n\n return this;\n },\n\n captureBreadcrumb: function(obj) {\n var crumb = objectMerge(\n {\n timestamp: now() / 1000\n },\n obj\n );\n\n if (isFunction(this._globalOptions.breadcrumbCallback)) {\n var result = this._globalOptions.breadcrumbCallback(crumb);\n\n if (isObject(result) && !isEmptyObject(result)) {\n crumb = result;\n } else if (result === false) {\n return this;\n }\n }\n\n this._breadcrumbs.push(crumb);\n if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {\n this._breadcrumbs.shift();\n }\n return this;\n },\n\n addPlugin: function(plugin /*arg1, arg2, ... argN*/) {\n var pluginArgs = [].slice.call(arguments, 1);\n\n this._plugins.push([plugin, pluginArgs]);\n if (this._isRavenInstalled) {\n this._drainPlugins();\n }\n\n return this;\n },\n\n /*\n * Set/clear a user to be sent along with the payload.\n *\n * @param {object} user An object representing user data [optional]\n * @return {Raven}\n */\n setUserContext: function(user) {\n // Intentionally do not merge here since that's an unexpected behavior.\n this._globalContext.user = user;\n\n return this;\n },\n\n /*\n * Merge extra attributes to be sent along with the payload.\n *\n * @param {object} extra An object representing extra data [optional]\n * @return {Raven}\n */\n setExtraContext: function(extra) {\n this._mergeContext('extra', extra);\n\n return this;\n },\n\n /*\n * Merge tags to be sent along with the payload.\n *\n * @param {object} tags An object representing tags [optional]\n * @return {Raven}\n */\n setTagsContext: function(tags) {\n this._mergeContext('tags', tags);\n\n return this;\n },\n\n /*\n * Clear all of the context.\n *\n * @return {Raven}\n */\n clearContext: function() {\n this._globalContext = {};\n\n return this;\n },\n\n /*\n * Get a copy of the current context. This cannot be mutated.\n *\n * @return {object} copy of context\n */\n getContext: function() {\n // lol javascript\n return JSON.parse(stringify(this._globalContext));\n },\n\n /*\n * Set environment of application\n *\n * @param {string} environment Typically something like 'production'.\n * @return {Raven}\n */\n setEnvironment: function(environment) {\n this._globalOptions.environment = environment;\n\n return this;\n },\n\n /*\n * Set release version of application\n *\n * @param {string} release Typically something like a git SHA to identify version\n * @return {Raven}\n */\n setRelease: function(release) {\n this._globalOptions.release = release;\n\n return this;\n },\n\n /*\n * Set the dataCallback option\n *\n * @param {function} callback The callback to run which allows the\n * data blob to be mutated before sending\n * @return {Raven}\n */\n setDataCallback: function(callback) {\n var original = this._globalOptions.dataCallback;\n this._globalOptions.dataCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the breadcrumbCallback option\n *\n * @param {function} callback The callback to run which allows filtering\n * or mutating breadcrumbs\n * @return {Raven}\n */\n setBreadcrumbCallback: function(callback) {\n var original = this._globalOptions.breadcrumbCallback;\n this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the shouldSendCallback option\n *\n * @param {function} callback The callback to run which allows\n * introspecting the blob before sending\n * @return {Raven}\n */\n setShouldSendCallback: function(callback) {\n var original = this._globalOptions.shouldSendCallback;\n this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /**\n * Override the default HTTP transport mechanism that transmits data\n * to the Sentry server.\n *\n * @param {function} transport Function invoked instead of the default\n * `makeRequest` handler.\n *\n * @return {Raven}\n */\n setTransport: function(transport) {\n this._globalOptions.transport = transport;\n\n return this;\n },\n\n /*\n * Get the latest raw exception that was captured by Raven.\n *\n * @return {error}\n */\n lastException: function() {\n return this._lastCapturedException;\n },\n\n /*\n * Get the last event id\n *\n * @return {string}\n */\n lastEventId: function() {\n return this._lastEventId;\n },\n\n /*\n * Determine if Raven is setup and ready to go.\n *\n * @return {boolean}\n */\n isSetup: function() {\n if (!this._hasJSON) return false; // needs JSON support\n if (!this._globalServer) {\n if (!this.ravenNotConfiguredError) {\n this.ravenNotConfiguredError = true;\n this._logDebug('error', 'Error: Raven has not been configured.');\n }\n return false;\n }\n return true;\n },\n\n afterLoad: function() {\n // TODO: remove window dependence?\n\n // Attempt to initialize Raven on load\n var RavenConfig = _window.RavenConfig;\n if (RavenConfig) {\n this.config(RavenConfig.dsn, RavenConfig.config).install();\n }\n },\n\n showReportDialog: function(options) {\n if (\n !_document // doesn't work without a document (React native)\n )\n return;\n\n options = options || {};\n\n var lastEventId = options.eventId || this.lastEventId();\n if (!lastEventId) {\n throw new RavenConfigError('Missing eventId');\n }\n\n var dsn = options.dsn || this._dsn;\n if (!dsn) {\n throw new RavenConfigError('Missing DSN');\n }\n\n var encode = encodeURIComponent;\n var qs = '';\n qs += '?eventId=' + encode(lastEventId);\n qs += '&dsn=' + encode(dsn);\n\n var user = options.user || this._globalContext.user;\n if (user) {\n if (user.name) qs += '&name=' + encode(user.name);\n if (user.email) qs += '&email=' + encode(user.email);\n }\n\n var globalServer = this._getGlobalServer(this._parseDSN(dsn));\n\n var script = _document.createElement('script');\n script.async = true;\n script.src = globalServer + '/api/embed/error-page/' + qs;\n (_document.head || _document.body).appendChild(script);\n },\n\n /**** Private functions ****/\n _ignoreNextOnError: function() {\n var self = this;\n this._ignoreOnError += 1;\n setTimeout(function() {\n // onerror should trigger before setTimeout\n self._ignoreOnError -= 1;\n });\n },\n\n _triggerEvent: function(eventType, options) {\n // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it\n var evt, key;\n\n if (!this._hasDocument) return;\n\n options = options || {};\n\n eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1);\n\n if (_document.createEvent) {\n evt = _document.createEvent('HTMLEvents');\n evt.initEvent(eventType, true, true);\n } else {\n evt = _document.createEventObject();\n evt.eventType = eventType;\n }\n\n for (key in options)\n if (hasKey(options, key)) {\n evt[key] = options[key];\n }\n\n if (_document.createEvent) {\n // IE9 if standards\n _document.dispatchEvent(evt);\n } else {\n // IE8 regardless of Quirks or Standards\n // IE9 if quirks\n try {\n _document.fireEvent('on' + evt.eventType.toLowerCase(), evt);\n } catch (e) {\n // Do nothing\n }\n }\n },\n\n /**\n * Wraps addEventListener to capture UI breadcrumbs\n * @param evtName the event name (e.g. \"click\")\n * @returns {Function}\n * @private\n */\n _breadcrumbEventHandler: function(evtName) {\n var self = this;\n return function(evt) {\n // reset keypress timeout; e.g. triggering a 'click' after\n // a 'keypress' will reset the keypress debounce so that a new\n // set of keypresses can be recorded\n self._keypressTimeout = null;\n\n // It's possible this handler might trigger multiple times for the same\n // event (e.g. event propagation through node ancestors). Ignore if we've\n // already captured the event.\n if (self._lastCapturedEvent === evt) return;\n\n self._lastCapturedEvent = evt;\n\n // try/catch both:\n // - accessing evt.target (see getsentry/raven-js#838, #768)\n // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly\n // can throw an exception in some circumstances.\n var target;\n try {\n target = htmlTreeAsString(evt.target);\n } catch (e) {\n target = '<unknown>';\n }\n\n self.captureBreadcrumb({\n category: 'ui.' + evtName, // e.g. ui.click, ui.input\n message: target\n });\n };\n },\n\n /**\n * Wraps addEventListener to capture keypress UI events\n * @returns {Function}\n * @private\n */\n _keypressEventHandler: function() {\n var self = this,\n debounceDuration = 1000; // milliseconds\n\n // TODO: if somehow user switches keypress target before\n // debounce timeout is triggered, we will only capture\n // a single breadcrumb from the FIRST target (acceptable?)\n return function(evt) {\n var target;\n try {\n target = evt.target;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n var tagName = target && target.tagName;\n\n // only consider keypress events on actual input elements\n // this will disregard keypresses targeting body (e.g. tabbing\n // through elements, hotkeys, etc)\n if (\n !tagName ||\n (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)\n )\n return;\n\n // record first keypress in a series, but ignore subsequent\n // keypresses until debounce clears\n var timeout = self._keypressTimeout;\n if (!timeout) {\n self._breadcrumbEventHandler('input')(evt);\n }\n clearTimeout(timeout);\n self._keypressTimeout = setTimeout(function() {\n self._keypressTimeout = null;\n }, debounceDuration);\n };\n },\n\n /**\n * Captures a breadcrumb of type \"navigation\", normalizing input URLs\n * @param to the originating URL\n * @param from the target URL\n * @private\n */\n _captureUrlChange: function(from, to) {\n var parsedLoc = parseUrl(this._location.href);\n var parsedTo = parseUrl(to);\n var parsedFrom = parseUrl(from);\n\n // because onpopstate only tells you the \"new\" (to) value of location.href, and\n // not the previous (from) value, we need to track the value of the current URL\n // state ourselves\n this._lastHref = to;\n\n // Use only the path component of the URL if the URL matches the current\n // document (almost all the time when using pushState)\n if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host)\n to = parsedTo.relative;\n if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host)\n from = parsedFrom.relative;\n\n this.captureBreadcrumb({\n category: 'navigation',\n data: {\n to: to,\n from: from\n }\n });\n },\n\n _patchFunctionToString: function() {\n var self = this;\n self._originalFunctionToString = Function.prototype.toString;\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = function() {\n if (typeof this === 'function' && this.__raven__) {\n return self._originalFunctionToString.apply(this.__orig__, arguments);\n }\n return self._originalFunctionToString.apply(this, arguments);\n };\n },\n\n _unpatchFunctionToString: function() {\n if (this._originalFunctionToString) {\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = this._originalFunctionToString;\n }\n },\n\n /**\n * Wrap timer functions and event targets to catch errors and provide\n * better metadata.\n */\n _instrumentTryCatch: function() {\n var self = this;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapTimeFn(orig) {\n return function(fn, t) {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n var originalCallback = args[0];\n if (isFunction(originalCallback)) {\n args[0] = self.wrap(originalCallback);\n }\n\n // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it\n // also supports only two arguments and doesn't care what this is, so we\n // can just call the original function directly.\n if (orig.apply) {\n return orig.apply(this, args);\n } else {\n return orig(args[0], args[1]);\n }\n };\n }\n\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n function wrapEventTarget(global) {\n var proto = _window[global] && _window[global].prototype;\n if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {\n fill(\n proto,\n 'addEventListener',\n function(orig) {\n return function(evtName, fn, capture, secure) {\n // preserve arity\n try {\n if (fn && fn.handleEvent) {\n fn.handleEvent = self.wrap(fn.handleEvent);\n }\n } catch (err) {\n // can sometimes get 'Permission denied to access property \"handle Event'\n }\n\n // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`\n // so that we don't have more than one wrapper function\n var before, clickHandler, keypressHandler;\n\n if (\n autoBreadcrumbs &&\n autoBreadcrumbs.dom &&\n (global === 'EventTarget' || global === 'Node')\n ) {\n // NOTE: generating multiple handlers per addEventListener invocation, should\n // revisit and verify we can just use one (almost certainly)\n clickHandler = self._breadcrumbEventHandler('click');\n keypressHandler = self._keypressEventHandler();\n before = function(evt) {\n // need to intercept every DOM event in `before` argument, in case that\n // same wrapped method is re-used for different events (e.g. mousemove THEN click)\n // see #724\n if (!evt) return;\n\n var eventType;\n try {\n eventType = evt.type;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n if (eventType === 'click') return clickHandler(evt);\n else if (eventType === 'keypress') return keypressHandler(evt);\n };\n }\n return orig.call(\n this,\n evtName,\n self.wrap(fn, undefined, before),\n capture,\n secure\n );\n };\n },\n wrappedBuiltIns\n );\n fill(\n proto,\n 'removeEventListener',\n function(orig) {\n return function(evt, fn, capture, secure) {\n try {\n fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn);\n } catch (e) {\n // ignore, accessing __raven_wrapper__ will throw in some Selenium environments\n }\n return orig.call(this, evt, fn, capture, secure);\n };\n },\n wrappedBuiltIns\n );\n }\n }\n\n fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);\n fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns);\n if (_window.requestAnimationFrame) {\n fill(\n _window,\n 'requestAnimationFrame',\n function(orig) {\n return function(cb) {\n return orig(self.wrap(cb));\n };\n },\n wrappedBuiltIns\n );\n }\n\n // event targets borrowed from bugsnag-js:\n // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666\n var eventTargets = [\n 'EventTarget',\n 'Window',\n 'Node',\n 'ApplicationCache',\n 'AudioTrackList',\n 'ChannelMergerNode',\n 'CryptoOperation',\n 'EventSource',\n 'FileReader',\n 'HTMLUnknownElement',\n 'IDBDatabase',\n 'IDBRequest',\n 'IDBTransaction',\n 'KeyOperation',\n 'MediaController',\n 'MessagePort',\n 'ModalWindow',\n 'Notification',\n 'SVGElementInstance',\n 'Screen',\n 'TextTrack',\n 'TextTrackCue',\n 'TextTrackList',\n 'WebSocket',\n 'WebSocketWorker',\n 'Worker',\n 'XMLHttpRequest',\n 'XMLHttpRequestEventTarget',\n 'XMLHttpRequestUpload'\n ];\n for (var i = 0; i < eventTargets.length; i++) {\n wrapEventTarget(eventTargets[i]);\n }\n },\n\n /**\n * Instrument browser built-ins w/ breadcrumb capturing\n * - XMLHttpRequests\n * - DOM interactions (click/typing)\n * - window.location changes\n * - console\n *\n * Can be disabled or individually configured via the `autoBreadcrumbs` config option\n */\n _instrumentBreadcrumbs: function() {\n var self = this;\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapProp(prop, xhr) {\n if (prop in xhr && isFunction(xhr[prop])) {\n fill(xhr, prop, function(orig) {\n return self.wrap(orig);\n }); // intentionally don't track filled methods on XHR instances\n }\n }\n\n if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) {\n var xhrproto = _window.XMLHttpRequest && _window.XMLHttpRequest.prototype;\n fill(\n xhrproto,\n 'open',\n function(origOpen) {\n return function(method, url) {\n // preserve arity\n\n // if Sentry key appears in URL, don't capture\n if (isString(url) && url.indexOf(self._globalKey) === -1) {\n this.__raven_xhr = {\n method: method,\n url: url,\n status_code: null\n };\n }\n\n return origOpen.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n\n fill(\n xhrproto,\n 'send',\n function(origSend) {\n return function() {\n // preserve arity\n var xhr = this;\n\n function onreadystatechangeHandler() {\n if (xhr.__raven_xhr && xhr.readyState === 4) {\n try {\n // touching statusCode in some platforms throws\n // an exception\n xhr.__raven_xhr.status_code = xhr.status;\n } catch (e) {\n /* do nothing */\n }\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'xhr',\n data: xhr.__raven_xhr\n });\n }\n }\n\n var props = ['onload', 'onerror', 'onprogress'];\n for (var j = 0; j < props.length; j++) {\n wrapProp(props[j], xhr);\n }\n\n if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {\n fill(\n xhr,\n 'onreadystatechange',\n function(orig) {\n return self.wrap(orig, undefined, onreadystatechangeHandler);\n } /* intentionally don't track this instrumentation */\n );\n } else {\n // if onreadystatechange wasn't actually set by the page on this xhr, we\n // are free to set our own and capture the breadcrumb\n xhr.onreadystatechange = onreadystatechangeHandler;\n }\n\n return origSend.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n }\n\n if (autoBreadcrumbs.xhr && supportsFetch()) {\n fill(\n _window,\n 'fetch',\n function(origFetch) {\n return function() {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n\n var fetchInput = args[0];\n var method = 'GET';\n var url;\n\n if (typeof fetchInput === 'string') {\n url = fetchInput;\n } else if ('Request' in _window && fetchInput instanceof _window.Request) {\n url = fetchInput.url;\n if (fetchInput.method) {\n method = fetchInput.method;\n }\n } else {\n url = '' + fetchInput;\n }\n\n // if Sentry key appears in URL, don't capture, as it's our own request\n if (url.indexOf(self._globalKey) !== -1) {\n return origFetch.apply(this, args);\n }\n\n if (args[1] && args[1].method) {\n method = args[1].method;\n }\n\n var fetchData = {\n method: method,\n url: url,\n status_code: null\n };\n\n return origFetch\n .apply(this, args)\n .then(function(response) {\n fetchData.status_code = response.status;\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData\n });\n\n return response;\n })\n ['catch'](function(err) {\n // if there is an error performing the request\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData,\n level: 'error'\n });\n\n throw err;\n });\n };\n },\n wrappedBuiltIns\n );\n }\n\n // Capture breadcrumbs from any click that is unhandled / bubbled up all the way\n // to the document. Do this before we instrument addEventListener.\n if (autoBreadcrumbs.dom && this._hasDocument) {\n if (_document.addEventListener) {\n _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);\n _document.addEventListener('keypress', self._keypressEventHandler(), false);\n } else if (_document.attachEvent) {\n // IE8 Compatibility\n _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));\n _document.attachEvent('onkeypress', self._keypressEventHandler());\n }\n }\n\n // record navigation (URL) changes\n // NOTE: in Chrome App environment, touching history.pushState, *even inside\n // a try/catch block*, will cause Chrome to output an error to console.error\n // borrowed from: https://github.com/angular/angular.js/pull/13945/files\n var chrome = _window.chrome;\n var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;\n var hasPushAndReplaceState =\n !isChromePackagedApp &&\n _window.history &&\n history.pushState &&\n history.replaceState;\n if (autoBreadcrumbs.location && hasPushAndReplaceState) {\n // TODO: remove onpopstate handler on uninstall()\n var oldOnPopState = _window.onpopstate;\n _window.onpopstate = function() {\n var currentHref = self._location.href;\n self._captureUrlChange(self._lastHref, currentHref);\n\n if (oldOnPopState) {\n return oldOnPopState.apply(this, arguments);\n }\n };\n\n var historyReplacementFunction = function(origHistFunction) {\n // note history.pushState.length is 0; intentionally not declaring\n // params to preserve 0 arity\n return function(/* state, title, url */) {\n var url = arguments.length > 2 ? arguments[2] : undefined;\n\n // url argument is optional\n if (url) {\n // coerce to string (this is what pushState does)\n self._captureUrlChange(self._lastHref, url + '');\n }\n\n return origHistFunction.apply(this, arguments);\n };\n };\n\n fill(history, 'pushState', historyReplacementFunction, wrappedBuiltIns);\n fill(history, 'replaceState', historyReplacementFunction, wrappedBuiltIns);\n }\n\n if (autoBreadcrumbs.console && 'console' in _window && console.log) {\n // console\n var consoleMethodCallback = function(msg, data) {\n self.captureBreadcrumb({\n message: msg,\n level: data.level,\n category: 'console'\n });\n };\n\n each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) {\n wrapConsoleMethod(console, level, consoleMethodCallback);\n });\n }\n },\n\n _restoreBuiltIns: function() {\n // restore any wrapped builtins\n var builtin;\n while (this._wrappedBuiltIns.length) {\n builtin = this._wrappedBuiltIns.shift();\n\n var obj = builtin[0],\n name = builtin[1],\n orig = builtin[2];\n\n obj[name] = orig;\n }\n },\n\n _restoreConsole: function() {\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsoleMethods) {\n this._originalConsole[method] = this._originalConsoleMethods[method];\n }\n },\n\n _drainPlugins: function() {\n var self = this;\n\n // FIX ME TODO\n each(this._plugins, function(_, plugin) {\n var installer = plugin[0];\n var args = plugin[1];\n installer.apply(self, [self].concat(args));\n });\n },\n\n _parseDSN: function(str) {\n var m = dsnPattern.exec(str),\n dsn = {},\n i = 7;\n\n try {\n while (i--) dsn[dsnKeys[i]] = m[i] || '';\n } catch (e) {\n throw new RavenConfigError('Invalid DSN: ' + str);\n }\n\n if (dsn.pass && !this._globalOptions.allowSecretKey) {\n throw new RavenConfigError(\n 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key'\n );\n }\n\n return dsn;\n },\n\n _getGlobalServer: function(uri) {\n // assemble the endpoint from the uri pieces\n var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : '');\n\n if (uri.protocol) {\n globalServer = uri.protocol + ':' + globalServer;\n }\n return globalServer;\n },\n\n _handleOnErrorStackInfo: function() {\n // if we are intentionally ignoring errors via onerror, bail out\n if (!this._ignoreOnError) {\n this._handleStackInfo.apply(this, arguments);\n }\n },\n\n _handleStackInfo: function(stackInfo, options) {\n var frames = this._prepareFrames(stackInfo, options);\n\n this._triggerEvent('handle', {\n stackInfo: stackInfo,\n options: options\n });\n\n this._processException(\n stackInfo.name,\n stackInfo.message,\n stackInfo.url,\n stackInfo.lineno,\n frames,\n options\n );\n },\n\n _prepareFrames: function(stackInfo, options) {\n var self = this;\n var frames = [];\n if (stackInfo.stack && stackInfo.stack.length) {\n each(stackInfo.stack, function(i, stack) {\n var frame = self._normalizeFrame(stack, stackInfo.url);\n if (frame) {\n frames.push(frame);\n }\n });\n\n // e.g. frames captured via captureMessage throw\n if (options && options.trimHeadFrames) {\n for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) {\n frames[j].in_app = false;\n }\n }\n }\n frames = frames.slice(0, this._globalOptions.stackTraceLimit);\n return frames;\n },\n\n _normalizeFrame: function(frame, stackInfoUrl) {\n // normalize the frames data\n var normalized = {\n filename: frame.url,\n lineno: frame.line,\n colno: frame.column,\n function: frame.func || '?'\n };\n\n // Case when we don't have any information about the error\n // E.g. throwing a string or raw object, instead of an `Error` in Firefox\n // Generating synthetic error doesn't add any value here\n //\n // We should probably somehow let a user know that they should fix their code\n if (!frame.url) {\n normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler\n }\n\n normalized.in_app = !// determine if an exception came from outside of our app\n // first we check the global includePaths list.\n (\n (!!this._globalOptions.includePaths.test &&\n !this._globalOptions.includePaths.test(normalized.filename)) ||\n // Now we check for fun, if the function name is Raven or TraceKit\n /(Raven|TraceKit)\\./.test(normalized['function']) ||\n // finally, we do a last ditch effort and check for raven.min.js\n /raven\\.(min\\.)?js$/.test(normalized.filename)\n );\n\n return normalized;\n },\n\n _processException: function(type, message, fileurl, lineno, frames, options) {\n var prefixedMessage = (type ? type + ': ' : '') + (message || '');\n if (\n !!this._globalOptions.ignoreErrors.test &&\n (this._globalOptions.ignoreErrors.test(message) ||\n this._globalOptions.ignoreErrors.test(prefixedMessage))\n ) {\n return;\n }\n\n var stacktrace;\n\n if (frames && frames.length) {\n fileurl = frames[0].filename || fileurl;\n // Sentry expects frames oldest to newest\n // and JS sends them as newest to oldest\n frames.reverse();\n stacktrace = {frames: frames};\n } else if (fileurl) {\n stacktrace = {\n frames: [\n {\n filename: fileurl,\n lineno: lineno,\n in_app: true\n }\n ]\n };\n }\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n var data = objectMerge(\n {\n // sentry.interfaces.Exception\n exception: {\n values: [\n {\n type: type,\n value: message,\n stacktrace: stacktrace\n }\n ]\n },\n culprit: fileurl\n },\n options\n );\n\n // Fire away!\n this._send(data);\n },\n\n _trimPacket: function(data) {\n // For now, we only want to truncate the two different messages\n // but this could/should be expanded to just trim everything\n var max = this._globalOptions.maxMessageLength;\n if (data.message) {\n data.message = truncate(data.message, max);\n }\n if (data.exception) {\n var exception = data.exception.values[0];\n exception.value = truncate(exception.value, max);\n }\n\n var request = data.request;\n if (request) {\n if (request.url) {\n request.url = truncate(request.url, this._globalOptions.maxUrlLength);\n }\n if (request.Referer) {\n request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);\n }\n }\n\n if (data.breadcrumbs && data.breadcrumbs.values)\n this._trimBreadcrumbs(data.breadcrumbs);\n\n return data;\n },\n\n /**\n * Truncate breadcrumb values (right now just URLs)\n */\n _trimBreadcrumbs: function(breadcrumbs) {\n // known breadcrumb properties with urls\n // TODO: also consider arbitrary prop values that start with (https?)?://\n var urlProps = ['to', 'from', 'url'],\n urlProp,\n crumb,\n data;\n\n for (var i = 0; i < breadcrumbs.values.length; ++i) {\n crumb = breadcrumbs.values[i];\n if (\n !crumb.hasOwnProperty('data') ||\n !isObject(crumb.data) ||\n objectFrozen(crumb.data)\n )\n continue;\n\n data = objectMerge({}, crumb.data);\n for (var j = 0; j < urlProps.length; ++j) {\n urlProp = urlProps[j];\n if (data.hasOwnProperty(urlProp) && data[urlProp]) {\n data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength);\n }\n }\n breadcrumbs.values[i].data = data;\n }\n },\n\n _getHttpData: function() {\n if (!this._hasNavigator && !this._hasDocument) return;\n var httpData = {};\n\n if (this._hasNavigator && _navigator.userAgent) {\n httpData.headers = {\n 'User-Agent': navigator.userAgent\n };\n }\n\n // Check in `window` instead of `document`, as we may be in ServiceWorker environment\n if (_window.location && _window.location.href) {\n httpData.url = _window.location.href;\n }\n\n if (this._hasDocument && _document.referrer) {\n if (!httpData.headers) httpData.headers = {};\n httpData.headers.Referer = _document.referrer;\n }\n\n return httpData;\n },\n\n _resetBackoff: function() {\n this._backoffDuration = 0;\n this._backoffStart = null;\n },\n\n _shouldBackoff: function() {\n return this._backoffDuration && now() - this._backoffStart < this._backoffDuration;\n },\n\n /**\n * Returns true if the in-process data payload matches the signature\n * of the previously-sent data\n *\n * NOTE: This has to be done at this level because TraceKit can generate\n * data from window.onerror WITHOUT an exception object (IE8, IE9,\n * other old browsers). This can take the form of an \"exception\"\n * data object with a single frame (derived from the onerror args).\n */\n _isRepeatData: function(current) {\n var last = this._lastData;\n\n if (\n !last ||\n current.message !== last.message || // defined for captureMessage\n current.culprit !== last.culprit // defined for captureException/onerror\n )\n return false;\n\n // Stacktrace interface (i.e. from captureMessage)\n if (current.stacktrace || last.stacktrace) {\n return isSameStacktrace(current.stacktrace, last.stacktrace);\n } else if (current.exception || last.exception) {\n // Exception interface (i.e. from captureException/onerror)\n return isSameException(current.exception, last.exception);\n }\n\n return true;\n },\n\n _setBackoffState: function(request) {\n // If we are already in a backoff state, don't change anything\n if (this._shouldBackoff()) {\n return;\n }\n\n var status = request.status;\n\n // 400 - project_id doesn't exist or some other fatal\n // 401 - invalid/revoked dsn\n // 429 - too many requests\n if (!(status === 400 || status === 401 || status === 429)) return;\n\n var retry;\n try {\n // If Retry-After is not in Access-Control-Expose-Headers, most\n // browsers will throw an exception trying to access it\n if (supportsFetch()) {\n retry = request.headers.get('Retry-After');\n } else {\n retry = request.getResponseHeader('Retry-After');\n }\n\n // Retry-After is returned in seconds\n retry = parseInt(retry, 10) * 1000;\n } catch (e) {\n /* eslint no-empty:0 */\n }\n\n this._backoffDuration = retry\n ? // If Sentry server returned a Retry-After value, use it\n retry\n : // Otherwise, double the last backoff duration (starts at 1 sec)\n this._backoffDuration * 2 || 1000;\n\n this._backoffStart = now();\n },\n\n _send: function(data) {\n var globalOptions = this._globalOptions;\n\n var baseData = {\n project: this._globalProject,\n logger: globalOptions.logger,\n platform: 'javascript'\n },\n httpData = this._getHttpData();\n\n if (httpData) {\n baseData.request = httpData;\n }\n\n // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload\n if (data.trimHeadFrames) delete data.trimHeadFrames;\n\n data = objectMerge(baseData, data);\n\n // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge\n data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags);\n data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra);\n\n // Send along our own collected metadata with extra\n data.extra['session:duration'] = now() - this._startTime;\n\n if (this._breadcrumbs && this._breadcrumbs.length > 0) {\n // intentionally make shallow copy so that additions\n // to breadcrumbs aren't accidentally sent in this request\n data.breadcrumbs = {\n values: [].slice.call(this._breadcrumbs, 0)\n };\n }\n\n if (this._globalContext.user) {\n // sentry.interfaces.User\n data.user = this._globalContext.user;\n }\n\n // Include the environment if it's defined in globalOptions\n if (globalOptions.environment) data.environment = globalOptions.environment;\n\n // Include the release if it's defined in globalOptions\n if (globalOptions.release) data.release = globalOptions.release;\n\n // Include server_name if it's defined in globalOptions\n if (globalOptions.serverName) data.server_name = globalOptions.serverName;\n\n data = this._sanitizeData(data);\n\n // Cleanup empty properties before sending them to the server\n Object.keys(data).forEach(function(key) {\n if (data[key] == null || data[key] === '' || isEmptyObject(data[key])) {\n delete data[key];\n }\n });\n\n if (isFunction(globalOptions.dataCallback)) {\n data = globalOptions.dataCallback(data) || data;\n }\n\n // Why??????????\n if (!data || isEmptyObject(data)) {\n return;\n }\n\n // Check if the request should be filtered or not\n if (\n isFunction(globalOptions.shouldSendCallback) &&\n !globalOptions.shouldSendCallback(data)\n ) {\n return;\n }\n\n // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests),\n // so drop requests until \"cool-off\" period has elapsed.\n if (this._shouldBackoff()) {\n this._logDebug('warn', 'Raven dropped error due to backoff: ', data);\n return;\n }\n\n if (typeof globalOptions.sampleRate === 'number') {\n if (Math.random() < globalOptions.sampleRate) {\n this._sendProcessedPayload(data);\n }\n } else {\n this._sendProcessedPayload(data);\n }\n },\n\n _sanitizeData: function(data) {\n return sanitize(data, this._globalOptions.sanitizeKeys);\n },\n\n _getUuid: function() {\n return uuid4();\n },\n\n _sendProcessedPayload: function(data, callback) {\n var self = this;\n var globalOptions = this._globalOptions;\n\n if (!this.isSetup()) return;\n\n // Try and clean up the packet before sending by truncating long values\n data = this._trimPacket(data);\n\n // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,\n // but this would require copying an un-truncated copy of the data packet, which can be\n // arbitrarily deep (extra_data) -- could be worthwhile? will revisit\n if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) {\n this._logDebug('warn', 'Raven dropped repeat event: ', data);\n return;\n }\n\n // Send along an event_id if not explicitly passed.\n // This event_id can be used to reference the error within Sentry itself.\n // Set lastEventId after we know the error should actually be sent\n this._lastEventId = data.event_id || (data.event_id = this._getUuid());\n\n // Store outbound payload after trim\n this._lastData = data;\n\n this._logDebug('debug', 'Raven about to send:', data);\n\n var auth = {\n sentry_version: '7',\n sentry_client: 'raven-js/' + this.VERSION,\n sentry_key: this._globalKey\n };\n\n if (this._globalSecret) {\n auth.sentry_secret = this._globalSecret;\n }\n\n var exception = data.exception && data.exception.values[0];\n\n // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy\n if (\n this._globalOptions.autoBreadcrumbs &&\n this._globalOptions.autoBreadcrumbs.sentry\n ) {\n this.captureBreadcrumb({\n category: 'sentry',\n message: exception\n ? (exception.type ? exception.type + ': ' : '') + exception.value\n : data.message,\n event_id: data.event_id,\n level: data.level || 'error' // presume error unless specified\n });\n }\n\n var url = this._globalEndpoint;\n (globalOptions.transport || this._makeRequest).call(this, {\n url: url,\n auth: auth,\n data: data,\n options: globalOptions,\n onSuccess: function success() {\n self._resetBackoff();\n\n self._triggerEvent('success', {\n data: data,\n src: url\n });\n callback && callback();\n },\n onError: function failure(error) {\n self._logDebug('error', 'Raven transport failed to send: ', error);\n\n if (error.request) {\n self._setBackoffState(error.request);\n }\n\n self._triggerEvent('failure', {\n data: data,\n src: url\n });\n error = error || new Error('Raven send failed (no additional details provided)');\n callback && callback(error);\n }\n });\n },\n\n _makeRequest: function(opts) {\n // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests\n var url = opts.url + '?' + urlencode(opts.auth);\n\n var evaluatedHeaders = null;\n var evaluatedFetchParameters = {};\n\n if (opts.options.headers) {\n evaluatedHeaders = this._evaluateHash(opts.options.headers);\n }\n\n if (opts.options.fetchParameters) {\n evaluatedFetchParameters = this._evaluateHash(opts.options.fetchParameters);\n }\n\n if (supportsFetch()) {\n evaluatedFetchParameters.body = stringify(opts.data);\n\n var defaultFetchOptions = objectMerge({}, this._fetchDefaults);\n var fetchOptions = objectMerge(defaultFetchOptions, evaluatedFetchParameters);\n\n if (evaluatedHeaders) {\n fetchOptions.headers = evaluatedHeaders;\n }\n\n return _window\n .fetch(url, fetchOptions)\n .then(function(response) {\n if (response.ok) {\n opts.onSuccess && opts.onSuccess();\n } else {\n var error = new Error('Sentry error code: ' + response.status);\n // It's called request only to keep compatibility with XHR interface\n // and not add more redundant checks in setBackoffState method\n error.request = response;\n opts.onError && opts.onError(error);\n }\n })\n ['catch'](function() {\n opts.onError &&\n opts.onError(new Error('Sentry error code: network unavailable'));\n });\n }\n\n var request = _window.XMLHttpRequest && new _window.XMLHttpRequest();\n if (!request) return;\n\n // if browser doesn't support CORS (e.g. IE7), we are out of luck\n var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined';\n\n if (!hasCORS) return;\n\n if ('withCredentials' in request) {\n request.onreadystatechange = function() {\n if (request.readyState !== 4) {\n return;\n } else if (request.status === 200) {\n opts.onSuccess && opts.onSuccess();\n } else if (opts.onError) {\n var err = new Error('Sentry error code: ' + request.status);\n err.request = request;\n opts.onError(err);\n }\n };\n } else {\n request = new XDomainRequest();\n // xdomainrequest cannot go http -> https (or vice versa),\n // so always use protocol relative\n url = url.replace(/^https?:/, '');\n\n // onreadystatechange not supported by XDomainRequest\n if (opts.onSuccess) {\n request.onload = opts.onSuccess;\n }\n if (opts.onError) {\n request.onerror = function() {\n var err = new Error('Sentry error code: XDomainRequest');\n err.request = request;\n opts.onError(err);\n };\n }\n }\n\n request.open('POST', url);\n\n if (evaluatedHeaders) {\n each(evaluatedHeaders, function(key, value) {\n request.setRequestHeader(key, value);\n });\n }\n\n request.send(stringify(opts.data));\n },\n\n _evaluateHash: function(hash) {\n var evaluated = {};\n\n for (var key in hash) {\n if (hash.hasOwnProperty(key)) {\n var value = hash[key];\n evaluated[key] = typeof value === 'function' ? value() : value;\n }\n }\n\n return evaluated;\n },\n\n _logDebug: function(level) {\n // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change\n if (\n this._originalConsoleMethods[level] &&\n (this.debug || this._globalOptions.debug)\n ) {\n // In IE<10 console methods do not have their own 'apply' method\n Function.prototype.apply.call(\n this._originalConsoleMethods[level],\n this._originalConsole,\n [].slice.call(arguments, 1)\n );\n }\n },\n\n _mergeContext: function(key, context) {\n if (isUndefined(context)) {\n delete this._globalContext[key];\n } else {\n this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context);\n }\n }\n};\n\n// Deprecations\nRaven.prototype.setUser = Raven.prototype.setUserContext;\nRaven.prototype.setReleaseContext = Raven.prototype.setRelease;\n\nmodule.exports = Raven;\n","/**\n * Enforces a single instance of the Raven client, and the\n * main entry point for Raven. If you are a consumer of the\n * Raven library, you SHOULD load this file (vs raven.js).\n **/\n\nvar RavenConstructor = require('./raven');\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _Raven = _window.Raven;\n\nvar Raven = new RavenConstructor();\n\n/*\n * Allow multiple versions of Raven to be installed.\n * Strip Raven from the global context and returns the instance.\n *\n * @return {Raven}\n */\nRaven.noConflict = function() {\n _window.Raven = _Raven;\n return Raven;\n};\n\nRaven.afterLoad();\n\nmodule.exports = Raven;\n\n/**\n * DISCLAIMER:\n *\n * Expose `Client` constructor for cases where user want to track multiple \"sub-applications\" in one larger app.\n * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it.\n * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug.\n *\n * It's called `Client' to be in-line with Raven Node implementation.\n *\n * HOWTO:\n *\n * import Raven from 'raven-js';\n *\n * const someAppReporter = new Raven.Client();\n * const someOtherAppReporter = new Raven.Client();\n *\n * someAppReporter.config('__DSN__', {\n * ...config goes here\n * });\n *\n * someOtherAppReporter.config('__OTHER_DSN__', {\n * ...config goes here\n * });\n *\n * someAppReporter.captureMessage(...);\n * someAppReporter.captureException(...);\n * someAppReporter.captureBreadcrumb(...);\n *\n * someOtherAppReporter.captureMessage(...);\n * someOtherAppReporter.captureException(...);\n * someOtherAppReporter.captureBreadcrumb(...);\n *\n * It should \"just work\".\n */\nmodule.exports.Client = RavenConstructor;\n","// ==========================================================================\n// Plyr.io demo\n// This code is purely for the https://plyr.io website\n// Please see readme.md in the root or github.com/sampotts/plyr\n// ==========================================================================\n\nimport Raven from 'raven-js';\n\n(() => {\n const isLive = window.location.host === 'plyr.io';\n\n // Raven / Sentry\n // For demo site (https://plyr.io) only\n if (isLive) {\n Raven.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install();\n }\n\n document.addEventListener('DOMContentLoaded', () => {\n Raven.context(() => {\n if (window.shr) {\n window.shr.setup({\n count: {\n classname: 'button__count',\n },\n });\n }\n\n // Setup tab focus\n const tabClassName = 'tab-focus';\n\n // Remove class on blur\n document.addEventListener('focusout', event => {\n event.target.classList.remove(tabClassName);\n });\n\n // Add classname to tabbed elements\n document.addEventListener('keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n document.activeElement.classList.add(tabClassName);\n }, 0);\n });\n\n // Setup the player\n const player = new Plyr('#player', {\n debug: true,\n title: 'View From A Blue Moon',\n iconUrl: '../dist/plyr.svg',\n keyboard: {\n global: true,\n },\n tooltips: {\n controls: true,\n },\n /* controls: [\n 'play-large',\n 'restart',\n 'rewind',\n 'play',\n 'fast-forward',\n 'progress',\n 'current-time',\n 'duration',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ], */\n /* i18n: {\n restart: '重新開始',\n rewind: '快退{seektime}秒',\n play: '播放',\n pause: '暫停',\n fastForward: '快進{seektime}秒',\n seek: '尋求',\n played: '發揮',\n buffered: '緩衝的',\n currentTime: '當前時間戳',\n duration: '長短',\n volume: '音量',\n mute: '靜音',\n unmute: '取消靜音',\n enableCaptions: '開啟字幕',\n disableCaptions: '關閉字幕',\n enterFullscreen: '進入全螢幕',\n exitFullscreen: '退出全螢幕',\n frameTitle: '球員為{title}',\n captions: '字幕',\n settings: '設定',\n speed: '速度',\n normal: '正常',\n quality: '質量',\n loop: '循環',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: '重啟',\n disabled: '殘',\n enabled: '啟用',\n advertisement: '廣告',\n }, */\n captions: {\n active: true,\n },\n keys: {\n google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c',\n },\n ads: {\n enabled: true,\n publisherId: '918848828995742',\n },\n });\n\n // Expose for tinkering in the console\n window.player = player;\n\n // Setup type toggle\n const buttons = document.querySelectorAll('[data-source]');\n const types = {\n video: 'video',\n audio: 'audio',\n youtube: 'youtube',\n vimeo: 'vimeo',\n };\n let currentType = window.location.hash.replace('#', '');\n const historySupport = window.history && window.history.pushState;\n\n // Toggle class on an element\n function toggleClass(element, className, state) {\n if (element) {\n element.classList[state ? 'add' : 'remove'](className);\n }\n }\n\n // Set a new source\n function newSource(type, init) {\n // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video\n if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) {\n return;\n }\n\n switch (type) {\n case types.video:\n player.source = {\n type: 'video',\n title: 'View From A Blue Moon',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',\n type: 'video/mp4',\n size: 576,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4',\n type: 'video/mp4',\n size: 720,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4',\n type: 'video/mp4',\n size: 1080,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4',\n type: 'video/mp4',\n size: 1440,\n },\n ],\n poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg',\n tracks: [\n {\n kind: 'captions',\n label: 'English',\n srclang: 'en',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n default: true,\n },\n {\n kind: 'captions',\n label: 'French',\n srclang: 'fr',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',\n },\n ],\n };\n\n break;\n\n case types.audio:\n player.source = {\n type: 'audio',\n title: 'Kishi Bashi – “It All Began With A Burst”',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',\n type: 'audio/mp3',\n },\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',\n type: 'audio/ogg',\n },\n ],\n };\n\n break;\n\n case types.youtube:\n player.source = {\n type: 'video',\n sources: [{\n src: 'https://youtube.com/watch?v=bTqVqk7FSmY',\n provider: 'youtube',\n }],\n };\n\n break;\n\n case types.vimeo:\n player.source = {\n type: 'video',\n sources: [{\n src: 'https://vimeo.com/76979871',\n provider: 'vimeo',\n }],\n };\n\n break;\n\n default:\n break;\n }\n\n // Set the current type for next time\n currentType = type;\n\n // Remove active classes\n Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));\n\n // Set active on parent\n toggleClass(document.querySelector(`[data-source=\"${type}\"]`), 'active', true);\n\n // Show cite\n Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {\n cite.setAttribute('hidden', '');\n });\n document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden');\n }\n\n // Bind to each button\n Array.from(buttons).forEach(button => {\n button.addEventListener('click', () => {\n const type = button.getAttribute('data-source');\n\n newSource(type);\n\n if (historySupport) {\n window.history.pushState({ type }, '', `#${type}`);\n }\n });\n });\n\n // List for backwards/forwards\n window.addEventListener('popstate', event => {\n if (event.state && 'type' in event.state) {\n newSource(event.state.type);\n }\n });\n\n // On load\n if (historySupport) {\n const video = !currentType.length;\n\n // If there's no current type set, assume video\n if (video) {\n currentType = types.video;\n }\n\n // Replace current history state\n if (currentType in types) {\n window.history.replaceState(\n {\n type: currentType,\n },\n '',\n video ? '' : `#${currentType}`,\n );\n }\n\n // If it's not video, load the source\n if (currentType !== types.video) {\n newSource(currentType, true);\n }\n }\n });\n });\n\n // Google analytics\n // For demo site (https://plyr.io) only\n /* eslint-disable */\n if (isLive) {\n (function(i, s, o, g, r, a, m) {\n i.GoogleAnalyticsObject = r;\n i[r] =\n i[r] ||\n function() {\n (i[r].q = i[r].q || []).push(arguments);\n };\n i[r].l = 1 * new Date();\n a = s.createElement(o);\n m = s.getElementsByTagName(o)[0];\n a.async = 1;\n a.src = g;\n m.parentNode.insertBefore(a, m);\n })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');\n window.ga('create', 'UA-40881672-11', 'auto');\n window.ga('send', 'pageview');\n }\n /* eslint-enable */\n})();\n"]}
\ No newline at end of file +{"version":3,"sources":["node_modules/raven-js/vendor/json-stringify-safe/stringify.js","node_modules/raven-js/src/utils.js","node_modules/raven-js/vendor/TraceKit/tracekit.js","node_modules/raven-js/vendor/md5/md5.js","node_modules/raven-js/src/configError.js","node_modules/raven-js/src/console.js","node_modules/raven-js/src/raven.js","node_modules/raven-js/src/singleton.js","src/js/utils/is.js","src/js/utils/events.js","src/js/utils/elements.js","src/js/utils/animation.js","src/js/utils/browser.js","src/js/support.js","src/js/html5.js","src/js/utils/arrays.js","src/js/utils/objects.js","src/js/utils/strings.js","src/js/utils/i18n.js","src/js/storage.js","src/js/utils/fetch.js","src/js/utils/loadSprite.js","src/js/utils/time.js","src/js/controls.js","src/js/utils/urls.js","src/js/captions.js","src/js/config/defaults.js","src/js/config/states.js","src/js/config/types.js","src/js/console.js","src/js/fullscreen.js","src/js/utils/loadImage.js","src/js/ui.js","src/js/utils/style.js","src/js/listeners.js","node_modules/loadjs/dist/loadjs.umd.js","src/js/utils/loadScript.js","src/js/plugins/vimeo.js","src/js/plugins/youtube.js","demo/src/js/demo.js","src/js/media.js","src/js/plugins/ads.js","src/js/plugins/previewThumbnails.js","src/js/source.js","src/js/plyr.js"],"names":["indexOf","haystack","needle","i","length","serializer","replacer","cycleReplacer","stack","keys","key","value","slice","join","thisPos","this","splice","push","Infinity","call","Error","err","message","name","Object","prototype","hasOwnProperty","stringifyError","module","exports","obj","spaces","JSON","stringify","getSerialize","_window","window","global","self","isUndefined","what","isPlainObject","toString","isString","isArray","supportsFetch","Headers","Request","Response","e","each","callback","j","hasKey","truncate","str","max","substr","object","joinRegExp","patterns","pattern","sources","len","replace","source","RegExp","htmlElementAsString","elem","className","classes","attr","out","tagName","toLowerCase","id","split","attrWhitelist","getAttribute","isOnlyOneTruthy","a","b","isSameStacktrace","stack1","stack2","frames1","frames","frames2","undefined","filename","lineno","colno","MAX_SERIALIZE_EXCEPTION_DEPTH","MAX_SERIALIZE_EXCEPTION_SIZE","MAX_SERIALIZE_KEYS_LENGTH","jsonSize","encodeURI","utf8Length","serializeValue","type","utils","isObject","isError","isErrorEvent","isDOMError","isDOMException","isFunction","isEmptyObject","_","supportsErrorEvent","ErrorEvent","supportsDOMError","DOMError","supportsDOMException","DOMException","supportsReferrerPolicy","referrerPolicy","supportsPromiseRejectionEvent","PromiseRejectionEvent","wrappedCallback","data","original","normalizedData","objectMerge","obj1","obj2","objectFrozen","isFrozen","urlencode","o","pairs","encodeURIComponent","uuid4","crypto","msCrypto","getRandomValues","arr","Uint16Array","pad","num","v","c","r","Math","random","htmlTreeAsString","nextStr","height","sepLength","parentNode","reverse","isSameException","ex1","ex2","values","stacktrace","parseUrl","url","match","query","fragment","protocol","host","path","relative","fill","replacement","track","orig","__raven__","__orig__","safeJoin","input","delimiter","output","String","serializeException","ex","depth","maxSize","serialized","serializeObject","reduce","acc","Array","map","val","serializeKeysForMessage","maxLength","filter","usedKeys","sanitize","sanitizeKeys","safeInput","sanitizeRegExp","sanitizeMask","parse","o_O","sanitizeWorker","workerInput","k","test","TraceKit","collectWindowErrors","debug","_slice","UNKNOWN_FUNCTION","ERROR_TYPES_RE","getLocationHref","document","location","href","report","_oldOnerrorHandler","_onErrorHandlerInstalled","handlers","lastArgs","lastException","lastExceptionStack","notifyHandlers","isWindowError","exception","apply","concat","arguments","inner","traceKitWindowOnError","msg","lineNo","colNo","error","computeStackTrace","augmentStackTraceWithInitialElement","processLastException","groups","line","column","func","_lastExceptionStack","_lastArgs","rethrow","args","setTimeout","incomplete","subscribe","handler","onerror","unsubscribe","uninstall","computeStackTraceFromStackProp","submatch","parts","element","chrome","winjs","gecko","geckoEval","chromeEval","lines","exec","isNative","columnNumber","xhr","XMLHttpRequest","open","send","status","responseText","sourceMaps","sourceMapAddress","charAt","origin","hostname","port","stackInfo","initial","unshift","partial","computeStackTraceByWalkingCallerChain","item","functionName","funcs","recursion","curr","caller","substring","result","sourceURL","fileName","lineNumber","description","tracekit","safeAdd","x","y","lsw","md5cmn","q","s","t","cnt","md5ff","d","md5gg","md5hh","md5ii","binlMD5","olda","oldb","oldc","oldd","binl2rstr","length32","fromCharCode","rstr2binl","length8","charCodeAt","rstr2hex","str2rstrUTF8","unescape","rawMD5","rstrMD5","rawHMACMD5","hash","bkey","ipad","opad","rstrHMACMD5","md5_1","string","raw","RavenConfigError","constructor","configError","console$1","console","level","originalConsoleLevel","originalConsole","sentryLevel","logger","extra","Function","wrapConsoleMethod","require$$0","dsnKeys","dsnPattern","now","Date","_document","_navigator","navigator","keepOriginalCallback","Raven","method","_hasJSON","_hasDocument","_hasNavigator","_lastCapturedException","_lastData","_lastEventId","_globalServer","_globalKey","_globalProject","_globalContext","_globalOptions","release","SENTRY_RELEASE","ignoreErrors","ignoreUrls","whitelistUrls","includePaths","headers","captureUnhandledRejections","maxMessageLength","maxUrlLength","stackTraceLimit","autoBreadcrumbs","instrument","sampleRate","_fetchDefaults","_ignoreOnError","_isRavenInstalled","_originalErrorStackTraceLimit","_originalConsole","_originalConsoleMethods","_plugins","_startTime","_wrappedBuiltIns","_breadcrumbs","_lastCapturedEvent","_keypressTimeout","_location","_lastHref","_resetBackoff","VERSION","config","dsn","options","_logDebug","globalOptions","setDSN","maxBreadcrumbs","min","autoBreadcrumbDefaults","dom","sentry","instrumentDefaults","tryCatch","install","isSetup","_handleOnErrorStackInfo","_attachPromiseRejectionHandler","_patchFunctionToString","_instrumentTryCatch","_instrumentBreadcrumbs","_drainPlugins","uri","_parseDSN","lastSlash","lastIndexOf","_dsn","user","_globalSecret","pass","_getGlobalServer","_globalEndpoint","context","wrap","_before","__raven_wrapper__","wrapped","deep","_ignoreNextOnError","captureException","property","_detachPromiseRejectionHandler","_unpatchFunctionToString","_restoreBuiltIns","_restoreConsole","_promiseRejectionHandler","event","reason","mechanism","handled","bind","addEventListener","removeEventListener","trimHeadFrames","captureMessage","_getCaptureExceptionOptionsFromPlainObject","_handleStackInfo","currentOptions","exKeys","sort","fingerprint","md5","__serialized__","initialCall","fileurl","_prepareFrames","_send","captureBreadcrumb","crumb","timestamp","breadcrumbCallback","shift","addPlugin","plugin","pluginArgs","setUserContext","setExtraContext","_mergeContext","setTagsContext","tags","clearContext","getContext","setEnvironment","environment","setRelease","setDataCallback","dataCallback","setBreadcrumbCallback","setShouldSendCallback","shouldSendCallback","setTransport","transport","lastEventId","ravenNotConfiguredError","afterLoad","RavenConfig","showReportDialog","eventId","encode","encodedOptions","email","globalServer","script","createElement","async","src","head","body","appendChild","_triggerEvent","eventType","evt","toUpperCase","createEvent","initEvent","createEventObject","dispatchEvent","fireEvent","_breadcrumbEventHandler","evtName","target","category","_keypressEventHandler","isContentEditable","timeout","clearTimeout","_captureUrlChange","from","to","parsedLoc","parsedTo","parsedFrom","_originalFunctionToString","wrappedBuiltIns","wrapTimeFn","fn","originalCallback","function","wrapEventTarget","proto","capture","secure","handleEvent","before","clickHandler","keypressHandler","requestAnimationFrame","cb","eventTargets","wrapProp","prop","xhrproto","origOpen","__raven_xhr","status_code","origSend","onreadystatechangeHandler","readyState","props","onreadystatechange","origFetch","fetchInput","fetchData","then","response","attachEvent","hasPushAndReplaceState","app","runtime","history","pushState","replaceState","oldOnPopState","onpopstate","currentHref","historyReplacementFunction","origHistFunction","log","consoleMethodCallback","builtin","installer","m","allowSecretKey","_processException","frame","_normalizeFrame","in_app","stackInfoUrl","normalized","prefixedMessage","transaction","_trimPacket","request","Referer","breadcrumbs","_trimBreadcrumbs","urlProp","urlProps","_getHttpData","httpData","userAgent","User-Agent","referrer","_backoffDuration","_backoffStart","_shouldBackoff","_isRepeatData","current","last","_setBackoffState","retry","get","getResponseHeader","parseInt","baseData","project","platform","serverName","server_name","_sanitizeData","forEach","_sendProcessedPayload","_getUuid","allowDuplicates","event_id","auth","sentry_version","sentry_client","sentry_key","sentry_secret","_makeRequest","onSuccess","onError","opts","evaluatedHeaders","evaluatedFetchParameters","_evaluateHash","fetchParameters","defaultFetchOptions","fetchOptions","fetch","ok","XDomainRequest","onload","setRequestHeader","evaluated","setUser","setReleaseContext","raven","_Raven","RavenConstructor","noConflict","singleton","Client","getConstructor","instanceOf","Boolean","isNullOrUndefined","isNodeList","NodeList","isEmpty","is","nullOrUndefined","number","Number","isNaN","boolean","array","weakMap","WeakMap","nodeList","Element","textNode","Text","Event","keyboardEvent","KeyboardEvent","cue","TextTrackCue","VTTCue","TextTrack","kind","URL","startsWith","empty","supportsPassiveListeners","supported","defineProperty","toggleListener","_this","toggle","passive","events","eventListeners","on","off","once","_this2","onceCallback","_len","_key","triggerEvent","bubbles","detail","CustomEvent","assign","plyr","elements","wrapper","targets","index","child","cloneNode","parent","sibling","nextSibling","insertBefore","setAttributes","attributes","entries","_ref","_slicedToArray","_ref3","_ref4","setAttribute","text","innerText","insertElement","removeElement","removeChild","emptyElement","childNodes","lastChild","replaceElement","newChild","oldChild","replaceChild","getAttributesFromSelector","sel","existingAttributes","existing","selector","trim","class","toggleHidden","hidden","hide","removeAttribute","toggleClass","force","classList","contains","hasClass","matches","querySelectorAll","includes","getElements","container","getElement","querySelector","setFocus","tabFocus","focus","preventScroll","classNames","transitionEndEvent","WebkitTransition","MozTransition","OTransition","transition","find","style","repaint","offsetHeight","range","browser","isIE","documentMode","isEdge","isWebkit","documentElement","isIPhone","isIos","defaultCodecs","audio/ogg","audio/wav","video/webm","video/mp4","video/ogg","support","audio","video","check","provider","playsinline","canPlayInline","api","ui","rangeInput","pip","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","mime","mediaType","isHTML5","media","canPlayType","textTracks","touch","transitions","reducedMotion","matchMedia","html5","getSources","getQualityOptions","extend","player","set","_player$media","currentTime","paused","preload","play","load","quality","cancelRequests","blankVideo","dedupe","getDeep","_defineProperty","format","replaceAll","toTitleCase","toCamelCase","toPascalCase","getHTML","innerHTML","resources","vimeo","youtube","i18n","{seektime}","seekTime","{title}","title","_ref2","Storage","_classCallCheck","enabled","storage","store","localStorage","getItem","json","setItem","removeItem","responseType","Promise","resolve","reject","loadSprite","hasId","exists","getElementById","update","insertAdjacentElement","useStorage","cached","content","catch","getHours","trunc","getMinutes","getSeconds","formatTime","time","displayHours","inverted","hours","mins","secs","controls","getIconUrl","cors","iconUrl","svg4everybody","findElements","selectors","buttons","pause","restart","rewind","fastForward","mute","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","seekTooltip","tooltip","warn","toggleNativeControls","createIcon","iconPath","iconPrefix","icon","createElementNS","role","focusable","use","setAttributeNS","createLabel","createBadge","badge","menu","createButton","buttonType","label","labelPressed","iconPressed","control","button","createRange","step","autocomplete","aria-label","aria-valuemin","aria-valuemax","aria-valuenow","updateRangeFill","createProgress","aria-hidden","suffixKey","played","suffix","createTime","bindMenuItemShortcuts","menuItem","which","preventDefault","stopPropagation","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","list","_ref$badge","_ref$checked","checked","aria-checked","flex","enumerable","children","node","listeners","currentTrack","speed","parseFloat","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","_this3","toFixed","getElementsByTagName","nodeValue","setProgress","buffered","percent","setProperty","updateSeekTooltip","_this4","tooltips","clientRect","getBoundingClientRect","visible","width","pageX","left","timeUpdate","invert","invertTime","seeking","durationUpdate","pow","hasDuration","displayDuration","toggleMenuButton","setting","updateSetting","pane","panels","default","getLabel","setQualityMenu","_this5","checkMenu","getBadge","sorting","setCaptionsMenu","_this6","tracks","getTracks","toggled","language","setSpeedMenu","_this7","isVimeo","some","popup","firstItem","toggleMenu","show","isMenuItem","getMenuSize","tab","clone","position","opacity","scrollWidth","scrollHeight","_this8","size","restore","propertyName","setDownloadLink","download","create","_this9","aria-haspopup","aria-controls","aria-expanded","home","backButton","urls","isEmbed","inject","_this10","floor","seektime","addProperty","controlPressed","_this$config","labels","parser","buildUrlParams","params","URLSearchParams","setup","isVideo","isYouTube","blob","createObjectURL","languages","userLanguage","active","trackEvents","_this$captions","meta","currentTrackNode","languageExists","mode","updateCues","setLanguage","activeClass","findTrack","_toConsumableArray","embed","enableTextTrack","has","sortIsDefault","sorted","every","getCurrentTrack","cues","activeCues","getCueAsHTML","cueText","caption","defaults","autoplay","autopause","toggleInvert","ratio","clickToPlay","hideControls","resetOnEnd","disableContextMenu","loop","selected","keyboard","focused","fallback","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","start","end","all","reset","disabled","advertisement","qualityBadge","2160","1440","1080","720","576","480","sdk","iframe","googleIMA","editable","embedContainer","poster","posterEnabled","ads","playing","stopped","loading","hover","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","google","publisherId","tagUrl","byline","portrait","transparent","noCookie","rel","showinfo","iv_load_policy","modestbranding","providers","types","noop","Console","onChange","first","keyCode","activeElement","shiftKey","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","overflow","viewport","hasProperty","cleanupViewport","part","Fullscreen","prefix","forceFallback","native","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","exit","enter","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","loadImage","minWidth","image","Image","naturalWidth","addStyleHook","build","checkPlaying","ready","setTitle","setPoster","togglePoster","enable","backgroundImage","backgroundSize","toggleControls","checkLoading","timers","recentTouchSeek","lastSeekTime","setAspectRatio","_ratio$split$map2","padding","paddingBottom","offset","transform","Listeners","lastKey","focusTimer","lastKeyDown","handleKey","setTabFocus","firstTouch","code","repeat","altKey","ctrlKey","metaKey","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","usingNative","timeStamp","wasKeyDown","delay","setPlayerSize","measure","rect","resized","_player$fullscreen","isEnter","_setPlayerSize","firstChild","_player$embed$ratio$s2","videoWidth","videoHeight","maxWidth","margin","setGutter","hasAudio","initialized","managerPromise","isAudio","ended","proxy","proxyEvents","_event$detail","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","currentTarget","hasAttribute","done","seekTo","loaded","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","_map2","deltaX","deltaY","direction","sign","abs","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","executeCallbacks","depsNotFound","success","loadFile","callbackFn","numTries","isCss","doc","maxTries","numRetries","beforeCallbackFn","pathStripped","onbeforeload","ev","sheet","cssText","defaultPrevented","loadjs","paths","arg1","arg2","numWaiting","loadFiles","deps","bundleIds","isDefined","factory","loadScript","assurePlaybackState","hasPlayed","Vimeo","gesture","$2","thumbnail_large","pathname","Player","disableTextTrack","stop","restorePause","setVolume","setCurrentTime","setPlaybackRate","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","_dimensions","setAutopause","state","getVideoTitle","getCurrentTime","getDuration","getTextTracks","_ref$cues","strippedCues","createDocumentFragment","getPaused","seconds","env","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getTitle","videoId","getVideoData","items","snippet","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","2","5","100","101","150","onPlaybackRateChange","instance","playbackRate","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","getAvailablePlaybackRates","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","displayContainer","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","LOG","adError","getMessage","cancel","contentComplete","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","init","zIndex","destroy","_this11","_this12","AV_PUBLISHERID","AV_CHANNELID","AV_URL","AV_WIDTH","AV_HEIGHT","AV_CDIM2","PreviewThumbnails","thumbnails","lastMouseMoveTime","mouseDown","loadedImages","thumb","scrubbing","getThumbnails","render","determineContainerAutoSizing","promises","u","getThumbnail","vttDataString","processedList","thumbnail","startTime","lineSplit","_lineSplit","_lineSplit$1$split2","w","h","matchTimes","endTime","urlPrefix","tempImage","naturalHeight","percentage","mousePosX","showImageAtCurrentTime","toggleThumbContainer","toggleScrubbingContainer","ceil","lastTime","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","findIndex","hasThumb","qualityIndex","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","clientHeight","sizeSpecifiedInCSS","thumbWidth","thumbAspectRatio","setThumbContainerPos","seekbarRect","plyrRect","minVal","maxVal","right","clientWidth","previewPos","multiplier","top","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","attribute","change","_sources$","_sources$$provider","crossorigin","Plyr","failed","jQuery","getProviderByUrl","search","truthy","searchParams","tabindex","webkitShowPlaybackTargetPicker","isHidden","hiding","eventName","soft","unload","inputIsValid","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","updateStorage","prev","closest","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","inline","prod","dev","shr","count","classname","remove","add","currentType","historySupport","newSource","srclang","parentElement","cite"],"mappings":"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","file":"demo.min.js","sourcesContent":["/*\n json-stringify-safe\n Like JSON.stringify, but doesn't throw on circular references.\n\n Originally forked from https://github.com/isaacs/json-stringify-safe\n version 5.0.1 on 3/8/2017 and modified to handle Errors serialization\n and IE8 compatibility. Tests for this are in test/vendor.\n\n ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE\n*/\n\nexports = module.exports = stringify;\nexports.getSerialize = serializer;\n\nfunction indexOf(haystack, needle) {\n for (var i = 0; i < haystack.length; ++i) {\n if (haystack[i] === needle) return i;\n }\n return -1;\n}\n\nfunction stringify(obj, replacer, spaces, cycleReplacer) {\n return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);\n}\n\n// https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106\nfunction stringifyError(value) {\n var err = {\n // These properties are implemented as magical getters and don't show up in for in\n stack: value.stack,\n message: value.message,\n name: value.name\n };\n\n for (var i in value) {\n if (Object.prototype.hasOwnProperty.call(value, i)) {\n err[i] = value[i];\n }\n }\n\n return err;\n}\n\nfunction serializer(replacer, cycleReplacer) {\n var stack = [];\n var keys = [];\n\n if (cycleReplacer == null) {\n cycleReplacer = function(key, value) {\n if (stack[0] === value) {\n return '[Circular ~]';\n }\n return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']';\n };\n }\n\n return function(key, value) {\n if (stack.length > 0) {\n var thisPos = indexOf(stack, this);\n ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);\n ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);\n\n if (~indexOf(stack, value)) {\n value = cycleReplacer.call(this, key, value);\n }\n } else {\n stack.push(value);\n }\n\n return replacer == null\n ? value instanceof Error ? stringifyError(value) : value\n : replacer.call(this, key, value);\n };\n}\n","var stringify = require('../vendor/json-stringify-safe/stringify');\n\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : typeof self !== 'undefined'\n ? self\n : {};\n\nfunction isObject(what) {\n return typeof what === 'object' && what !== null;\n}\n\n// Yanked from https://git.io/vS8DV re-used under CC0\n// with some tiny modifications\nfunction isError(value) {\n switch (Object.prototype.toString.call(value)) {\n case '[object Error]':\n return true;\n case '[object Exception]':\n return true;\n case '[object DOMException]':\n return true;\n default:\n return value instanceof Error;\n }\n}\n\nfunction isErrorEvent(value) {\n return Object.prototype.toString.call(value) === '[object ErrorEvent]';\n}\n\nfunction isDOMError(value) {\n return Object.prototype.toString.call(value) === '[object DOMError]';\n}\n\nfunction isDOMException(value) {\n return Object.prototype.toString.call(value) === '[object DOMException]';\n}\n\nfunction isUndefined(what) {\n return what === void 0;\n}\n\nfunction isFunction(what) {\n return typeof what === 'function';\n}\n\nfunction isPlainObject(what) {\n return Object.prototype.toString.call(what) === '[object Object]';\n}\n\nfunction isString(what) {\n return Object.prototype.toString.call(what) === '[object String]';\n}\n\nfunction isArray(what) {\n return Object.prototype.toString.call(what) === '[object Array]';\n}\n\nfunction isEmptyObject(what) {\n if (!isPlainObject(what)) return false;\n\n for (var _ in what) {\n if (what.hasOwnProperty(_)) {\n return false;\n }\n }\n return true;\n}\n\nfunction supportsErrorEvent() {\n try {\n new ErrorEvent(''); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsDOMError() {\n try {\n new DOMError(''); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsDOMException() {\n try {\n new DOMException(''); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsFetch() {\n if (!('fetch' in _window)) return false;\n\n try {\n new Headers(); // eslint-disable-line no-new\n new Request(''); // eslint-disable-line no-new\n new Response(); // eslint-disable-line no-new\n return true;\n } catch (e) {\n return false;\n }\n}\n\n// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n// https://caniuse.com/#feat=referrer-policy\n// It doesn't. And it throw exception instead of ignoring this parameter...\n// REF: https://github.com/getsentry/raven-js/issues/1233\nfunction supportsReferrerPolicy() {\n if (!supportsFetch()) return false;\n\n try {\n // eslint-disable-next-line no-new\n new Request('pickleRick', {\n referrerPolicy: 'origin'\n });\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction supportsPromiseRejectionEvent() {\n return typeof PromiseRejectionEvent === 'function';\n}\n\nfunction wrappedCallback(callback) {\n function dataCallback(data, original) {\n var normalizedData = callback(data) || data;\n if (original) {\n return original(normalizedData) || normalizedData;\n }\n return normalizedData;\n }\n\n return dataCallback;\n}\n\nfunction each(obj, callback) {\n var i, j;\n\n if (isUndefined(obj.length)) {\n for (i in obj) {\n if (hasKey(obj, i)) {\n callback.call(null, i, obj[i]);\n }\n }\n } else {\n j = obj.length;\n if (j) {\n for (i = 0; i < j; i++) {\n callback.call(null, i, obj[i]);\n }\n }\n }\n}\n\nfunction objectMerge(obj1, obj2) {\n if (!obj2) {\n return obj1;\n }\n each(obj2, function(key, value) {\n obj1[key] = value;\n });\n return obj1;\n}\n\n/**\n * This function is only used for react-native.\n * react-native freezes object that have already been sent over the\n * js bridge. We need this function in order to check if the object is frozen.\n * So it's ok that objectFrozen returns false if Object.isFrozen is not\n * supported because it's not relevant for other \"platforms\". See related issue:\n * https://github.com/getsentry/react-native-sentry/issues/57\n */\nfunction objectFrozen(obj) {\n if (!Object.isFrozen) {\n return false;\n }\n return Object.isFrozen(obj);\n}\n\nfunction truncate(str, max) {\n if (typeof max !== 'number') {\n throw new Error('2nd argument to `truncate` function should be a number');\n }\n if (typeof str !== 'string' || max === 0) {\n return str;\n }\n return str.length <= max ? str : str.substr(0, max) + '\\u2026';\n}\n\n/**\n * hasKey, a better form of hasOwnProperty\n * Example: hasKey(MainHostObject, property) === true/false\n *\n * @param {Object} host object to check property\n * @param {string} key to check\n */\nfunction hasKey(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\nfunction joinRegExp(patterns) {\n // Combine an array of regular expressions and strings into one large regexp\n // Be mad.\n var sources = [],\n i = 0,\n len = patterns.length,\n pattern;\n\n for (; i < len; i++) {\n pattern = patterns[i];\n if (isString(pattern)) {\n // If it's a string, we need to escape it\n // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n sources.push(pattern.replace(/([.*+?^=!:${}()|\\[\\]\\/\\\\])/g, '\\\\$1'));\n } else if (pattern && pattern.source) {\n // If it's a regexp already, we want to extract the source\n sources.push(pattern.source);\n }\n // Intentionally skip other cases\n }\n return new RegExp(sources.join('|'), 'i');\n}\n\nfunction urlencode(o) {\n var pairs = [];\n each(o, function(key, value) {\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n });\n return pairs.join('&');\n}\n\n// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B\n// intentionally using regex and not <a/> href parsing trick because React Native and other\n// environments where DOM might not be available\nfunction parseUrl(url) {\n if (typeof url !== 'string') return {};\n var match = url.match(/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$/);\n\n // coerce to undefined values to empty string so we don't get 'undefined'\n var query = match[6] || '';\n var fragment = match[8] || '';\n return {\n protocol: match[2],\n host: match[4],\n path: match[5],\n relative: match[5] + query + fragment // everything minus origin\n };\n}\nfunction uuid4() {\n var crypto = _window.crypto || _window.msCrypto;\n\n if (!isUndefined(crypto) && crypto.getRandomValues) {\n // Use window.crypto API if available\n // eslint-disable-next-line no-undef\n var arr = new Uint16Array(8);\n crypto.getRandomValues(arr);\n\n // set 4 in byte 7\n arr[3] = (arr[3] & 0xfff) | 0x4000;\n // set 2 most significant bits of byte 9 to '10'\n arr[4] = (arr[4] & 0x3fff) | 0x8000;\n\n var pad = function(num) {\n var v = num.toString(16);\n while (v.length < 4) {\n v = '0' + v;\n }\n return v;\n };\n\n return (\n pad(arr[0]) +\n pad(arr[1]) +\n pad(arr[2]) +\n pad(arr[3]) +\n pad(arr[4]) +\n pad(arr[5]) +\n pad(arr[6]) +\n pad(arr[7])\n );\n } else {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523\n return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (Math.random() * 16) | 0,\n v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @param elem\n * @returns {string}\n */\nfunction htmlTreeAsString(elem) {\n /* eslint no-extra-parens:0*/\n var MAX_TRAVERSE_HEIGHT = 5,\n MAX_OUTPUT_LEN = 80,\n out = [],\n height = 0,\n len = 0,\n separator = ' > ',\n sepLength = separator.length,\n nextStr;\n\n while (elem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = htmlElementAsString(elem);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds MAX_OUTPUT_LEN\n // (ignore this limit if we are on the first iteration)\n if (\n nextStr === 'html' ||\n (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)\n ) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n elem = elem.parentNode;\n }\n\n return out.reverse().join(separator);\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @param HTMLElement\n * @returns {string}\n */\nfunction htmlElementAsString(elem) {\n var out = [],\n className,\n classes,\n key,\n attr,\n i;\n\n if (!elem || !elem.tagName) {\n return '';\n }\n\n out.push(elem.tagName.toLowerCase());\n if (elem.id) {\n out.push('#' + elem.id);\n }\n\n className = elem.className;\n if (className && isString(className)) {\n classes = className.split(/\\s+/);\n for (i = 0; i < classes.length; i++) {\n out.push('.' + classes[i]);\n }\n }\n var attrWhitelist = ['type', 'name', 'title', 'alt'];\n for (i = 0; i < attrWhitelist.length; i++) {\n key = attrWhitelist[i];\n attr = elem.getAttribute(key);\n if (attr) {\n out.push('[' + key + '=\"' + attr + '\"]');\n }\n }\n return out.join('');\n}\n\n/**\n * Returns true if either a OR b is truthy, but not both\n */\nfunction isOnlyOneTruthy(a, b) {\n return !!(!!a ^ !!b);\n}\n\n/**\n * Returns true if both parameters are undefined\n */\nfunction isBothUndefined(a, b) {\n return isUndefined(a) && isUndefined(b);\n}\n\n/**\n * Returns true if the two input exception interfaces have the same content\n */\nfunction isSameException(ex1, ex2) {\n if (isOnlyOneTruthy(ex1, ex2)) return false;\n\n ex1 = ex1.values[0];\n ex2 = ex2.values[0];\n\n if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false;\n\n // in case both stacktraces are undefined, we can't decide so default to false\n if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false;\n\n return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);\n}\n\n/**\n * Returns true if the two input stack trace interfaces have the same content\n */\nfunction isSameStacktrace(stack1, stack2) {\n if (isOnlyOneTruthy(stack1, stack2)) return false;\n\n var frames1 = stack1.frames;\n var frames2 = stack2.frames;\n\n // Exit early if stacktrace is malformed\n if (frames1 === undefined || frames2 === undefined) return false;\n\n // Exit early if frame count differs\n if (frames1.length !== frames2.length) return false;\n\n // Iterate through every frame; bail out if anything differs\n var a, b;\n for (var i = 0; i < frames1.length; i++) {\n a = frames1[i];\n b = frames2[i];\n if (\n a.filename !== b.filename ||\n a.lineno !== b.lineno ||\n a.colno !== b.colno ||\n a['function'] !== b['function']\n )\n return false;\n }\n return true;\n}\n\n/**\n * Polyfill a method\n * @param obj object e.g. `document`\n * @param name method name present on object e.g. `addEventListener`\n * @param replacement replacement function\n * @param track {optional} record instrumentation to an array\n */\nfunction fill(obj, name, replacement, track) {\n if (obj == null) return;\n var orig = obj[name];\n obj[name] = replacement(orig);\n obj[name].__raven__ = true;\n obj[name].__orig__ = orig;\n if (track) {\n track.push([obj, name, orig]);\n }\n}\n\n/**\n * Join values in array\n * @param input array of values to be joined together\n * @param delimiter string to be placed in-between values\n * @returns {string}\n */\nfunction safeJoin(input, delimiter) {\n if (!isArray(input)) return '';\n\n var output = [];\n\n for (var i = 0; i < input.length; i++) {\n try {\n output.push(String(input[i]));\n } catch (e) {\n output.push('[value cannot be serialized]');\n }\n }\n\n return output.join(delimiter);\n}\n\n// Default Node.js REPL depth\nvar MAX_SERIALIZE_EXCEPTION_DEPTH = 3;\n// 50kB, as 100kB is max payload size, so half sounds reasonable\nvar MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024;\nvar MAX_SERIALIZE_KEYS_LENGTH = 40;\n\nfunction utf8Length(value) {\n return ~-encodeURI(value).split(/%..|./).length;\n}\n\nfunction jsonSize(value) {\n return utf8Length(JSON.stringify(value));\n}\n\nfunction serializeValue(value) {\n if (typeof value === 'string') {\n var maxLength = 40;\n return truncate(value, maxLength);\n } else if (\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'undefined'\n ) {\n return value;\n }\n\n var type = Object.prototype.toString.call(value);\n\n // Node.js REPL notation\n if (type === '[object Object]') return '[Object]';\n if (type === '[object Array]') return '[Array]';\n if (type === '[object Function]')\n return value.name ? '[Function: ' + value.name + ']' : '[Function]';\n\n return value;\n}\n\nfunction serializeObject(value, depth) {\n if (depth === 0) return serializeValue(value);\n\n if (isPlainObject(value)) {\n return Object.keys(value).reduce(function(acc, key) {\n acc[key] = serializeObject(value[key], depth - 1);\n return acc;\n }, {});\n } else if (Array.isArray(value)) {\n return value.map(function(val) {\n return serializeObject(val, depth - 1);\n });\n }\n\n return serializeValue(value);\n}\n\nfunction serializeException(ex, depth, maxSize) {\n if (!isPlainObject(ex)) return ex;\n\n depth = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_DEPTH : depth;\n maxSize = typeof depth !== 'number' ? MAX_SERIALIZE_EXCEPTION_SIZE : maxSize;\n\n var serialized = serializeObject(ex, depth);\n\n if (jsonSize(stringify(serialized)) > maxSize) {\n return serializeException(ex, depth - 1);\n }\n\n return serialized;\n}\n\nfunction serializeKeysForMessage(keys, maxLength) {\n if (typeof keys === 'number' || typeof keys === 'string') return keys.toString();\n if (!Array.isArray(keys)) return '';\n\n keys = keys.filter(function(key) {\n return typeof key === 'string';\n });\n if (keys.length === 0) return '[object has no keys]';\n\n maxLength = typeof maxLength !== 'number' ? MAX_SERIALIZE_KEYS_LENGTH : maxLength;\n if (keys[0].length >= maxLength) return keys[0];\n\n for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) {\n var serialized = keys.slice(0, usedKeys).join(', ');\n if (serialized.length > maxLength) continue;\n if (usedKeys === keys.length) return serialized;\n return serialized + '\\u2026';\n }\n\n return '';\n}\n\nfunction sanitize(input, sanitizeKeys) {\n if (!isArray(sanitizeKeys) || (isArray(sanitizeKeys) && sanitizeKeys.length === 0))\n return input;\n\n var sanitizeRegExp = joinRegExp(sanitizeKeys);\n var sanitizeMask = '********';\n var safeInput;\n\n try {\n safeInput = JSON.parse(stringify(input));\n } catch (o_O) {\n return input;\n }\n\n function sanitizeWorker(workerInput) {\n if (isArray(workerInput)) {\n return workerInput.map(function(val) {\n return sanitizeWorker(val);\n });\n }\n\n if (isPlainObject(workerInput)) {\n return Object.keys(workerInput).reduce(function(acc, k) {\n if (sanitizeRegExp.test(k)) {\n acc[k] = sanitizeMask;\n } else {\n acc[k] = sanitizeWorker(workerInput[k]);\n }\n return acc;\n }, {});\n }\n\n return workerInput;\n }\n\n return sanitizeWorker(safeInput);\n}\n\nmodule.exports = {\n isObject: isObject,\n isError: isError,\n isErrorEvent: isErrorEvent,\n isDOMError: isDOMError,\n isDOMException: isDOMException,\n isUndefined: isUndefined,\n isFunction: isFunction,\n isPlainObject: isPlainObject,\n isString: isString,\n isArray: isArray,\n isEmptyObject: isEmptyObject,\n supportsErrorEvent: supportsErrorEvent,\n supportsDOMError: supportsDOMError,\n supportsDOMException: supportsDOMException,\n supportsFetch: supportsFetch,\n supportsReferrerPolicy: supportsReferrerPolicy,\n supportsPromiseRejectionEvent: supportsPromiseRejectionEvent,\n wrappedCallback: wrappedCallback,\n each: each,\n objectMerge: objectMerge,\n truncate: truncate,\n objectFrozen: objectFrozen,\n hasKey: hasKey,\n joinRegExp: joinRegExp,\n urlencode: urlencode,\n uuid4: uuid4,\n htmlTreeAsString: htmlTreeAsString,\n htmlElementAsString: htmlElementAsString,\n isSameException: isSameException,\n isSameStacktrace: isSameStacktrace,\n parseUrl: parseUrl,\n fill: fill,\n safeJoin: safeJoin,\n serializeException: serializeException,\n serializeKeysForMessage: serializeKeysForMessage,\n sanitize: sanitize\n};\n","var utils = require('../../src/utils');\n\n/*\n TraceKit - Cross brower stack traces\n\n This was originally forked from github.com/occ/TraceKit, but has since been\n largely re-written and is now maintained as part of raven-js. Tests for\n this are in test/vendor.\n\n MIT license\n*/\n\nvar TraceKit = {\n collectWindowErrors: true,\n debug: false\n};\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n// global reference to slice\nvar _slice = [].slice;\nvar UNKNOWN_FUNCTION = '?';\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types\nvar ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;\n\nfunction getLocationHref() {\n if (typeof document === 'undefined' || document.location == null) return '';\n return document.location.href;\n}\n\nfunction getLocationOrigin() {\n if (typeof document === 'undefined' || document.location == null) return '';\n\n // Oh dear IE10...\n if (!document.location.origin) {\n return (\n document.location.protocol +\n '//' +\n document.location.hostname +\n (document.location.port ? ':' + document.location.port : '')\n );\n }\n\n return document.location.origin;\n}\n\n/**\n * TraceKit.report: cross-browser processing of unhandled exceptions\n *\n * Syntax:\n * TraceKit.report.subscribe(function(stackInfo) { ... })\n * TraceKit.report.unsubscribe(function(stackInfo) { ... })\n * TraceKit.report(exception)\n * try { ...code... } catch(ex) { TraceKit.report(ex); }\n *\n * Supports:\n * - Firefox: full stack trace with line numbers, plus column number\n * on top frame; column number is not guaranteed\n * - Opera: full stack trace with line and column numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n * - IE: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n *\n * In theory, TraceKit should work on all of the following versions:\n * - IE5.5+ (only 8.0 tested)\n * - Firefox 0.9+ (only 3.5+ tested)\n * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require\n * Exceptions Have Stacktrace to be enabled in opera:config)\n * - Safari 3+ (only 4+ tested)\n * - Chrome 1+ (only 5+ tested)\n * - Konqueror 3.5+ (untested)\n *\n * Requires TraceKit.computeStackTrace.\n *\n * Tries to catch all unhandled exceptions and report them to the\n * subscribed handlers. Please note that TraceKit.report will rethrow the\n * exception. This is REQUIRED in order to get a useful stack trace in IE.\n * If the exception does not reach the top of the browser, you will only\n * get a stack trace from the point where TraceKit.report was called.\n *\n * Handlers receive a stackInfo object as described in the\n * TraceKit.computeStackTrace docs.\n */\nTraceKit.report = (function reportModuleWrapper() {\n var handlers = [],\n lastArgs = null,\n lastException = null,\n lastExceptionStack = null;\n\n /**\n * Add a crash handler.\n * @param {Function} handler\n */\n function subscribe(handler) {\n installGlobalHandler();\n handlers.push(handler);\n }\n\n /**\n * Remove a crash handler.\n * @param {Function} handler\n */\n function unsubscribe(handler) {\n for (var i = handlers.length - 1; i >= 0; --i) {\n if (handlers[i] === handler) {\n handlers.splice(i, 1);\n }\n }\n }\n\n /**\n * Remove all crash handlers.\n */\n function unsubscribeAll() {\n uninstallGlobalHandler();\n handlers = [];\n }\n\n /**\n * Dispatch stack information to all handlers.\n * @param {Object.<string, *>} stack\n */\n function notifyHandlers(stack, isWindowError) {\n var exception = null;\n if (isWindowError && !TraceKit.collectWindowErrors) {\n return;\n }\n for (var i in handlers) {\n if (handlers.hasOwnProperty(i)) {\n try {\n handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));\n } catch (inner) {\n exception = inner;\n }\n }\n }\n\n if (exception) {\n throw exception;\n }\n }\n\n var _oldOnerrorHandler, _onErrorHandlerInstalled;\n\n /**\n * Ensures all global unhandled exceptions are recorded.\n * Supported by Gecko and IE.\n * @param {string} msg Error message.\n * @param {string} url URL of script that generated the exception.\n * @param {(number|string)} lineNo The line number at which the error\n * occurred.\n * @param {?(number|string)} colNo The column number at which the error\n * occurred.\n * @param {?Error} ex The actual Error object.\n */\n function traceKitWindowOnError(msg, url, lineNo, colNo, ex) {\n var stack = null;\n // If 'ex' is ErrorEvent, get real Error from inside\n var exception = utils.isErrorEvent(ex) ? ex.error : ex;\n // If 'msg' is ErrorEvent, get real message from inside\n var message = utils.isErrorEvent(msg) ? msg.message : msg;\n\n if (lastExceptionStack) {\n TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(\n lastExceptionStack,\n url,\n lineNo,\n message\n );\n processLastException();\n } else if (exception && utils.isError(exception)) {\n // non-string `exception` arg; attempt to extract stack trace\n\n // New chrome and blink send along a real error object\n // Let's just report that like a normal error.\n // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror\n stack = TraceKit.computeStackTrace(exception);\n notifyHandlers(stack, true);\n } else {\n var location = {\n url: url,\n line: lineNo,\n column: colNo\n };\n\n var name = undefined;\n var groups;\n\n if ({}.toString.call(message) === '[object String]') {\n var groups = message.match(ERROR_TYPES_RE);\n if (groups) {\n name = groups[1];\n message = groups[2];\n }\n }\n\n location.func = UNKNOWN_FUNCTION;\n\n stack = {\n name: name,\n message: message,\n url: getLocationHref(),\n stack: [location]\n };\n notifyHandlers(stack, true);\n }\n\n if (_oldOnerrorHandler) {\n return _oldOnerrorHandler.apply(this, arguments);\n }\n\n return false;\n }\n\n function installGlobalHandler() {\n if (_onErrorHandlerInstalled) {\n return;\n }\n _oldOnerrorHandler = _window.onerror;\n _window.onerror = traceKitWindowOnError;\n _onErrorHandlerInstalled = true;\n }\n\n function uninstallGlobalHandler() {\n if (!_onErrorHandlerInstalled) {\n return;\n }\n _window.onerror = _oldOnerrorHandler;\n _onErrorHandlerInstalled = false;\n _oldOnerrorHandler = undefined;\n }\n\n function processLastException() {\n var _lastExceptionStack = lastExceptionStack,\n _lastArgs = lastArgs;\n lastArgs = null;\n lastExceptionStack = null;\n lastException = null;\n notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));\n }\n\n /**\n * Reports an unhandled Error to TraceKit.\n * @param {Error} ex\n * @param {?boolean} rethrow If false, do not re-throw the exception.\n * Only used for window.onerror to not cause an infinite loop of\n * rethrowing.\n */\n function report(ex, rethrow) {\n var args = _slice.call(arguments, 1);\n if (lastExceptionStack) {\n if (lastException === ex) {\n return; // already caught by an inner catch block, ignore\n } else {\n processLastException();\n }\n }\n\n var stack = TraceKit.computeStackTrace(ex);\n lastExceptionStack = stack;\n lastException = ex;\n lastArgs = args;\n\n // If the stack trace is incomplete, wait for 2 seconds for\n // slow slow IE to see if onerror occurs or not before reporting\n // this exception; otherwise, we will end up with an incomplete\n // stack trace\n setTimeout(function() {\n if (lastException === ex) {\n processLastException();\n }\n }, stack.incomplete ? 2000 : 0);\n\n if (rethrow !== false) {\n throw ex; // re-throw to propagate to the top level (and cause window.onerror)\n }\n }\n\n report.subscribe = subscribe;\n report.unsubscribe = unsubscribe;\n report.uninstall = unsubscribeAll;\n return report;\n})();\n\n/**\n * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript\n *\n * Syntax:\n * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)\n * Returns:\n * s.name - exception name\n * s.message - exception message\n * s.stack[i].url - JavaScript or HTML file URL\n * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)\n * s.stack[i].args - arguments passed to the function, if known\n * s.stack[i].line - line number, if known\n * s.stack[i].column - column number, if known\n *\n * Supports:\n * - Firefox: full stack trace with line numbers and unreliable column\n * number on top frame\n * - Opera 10: full stack trace with line and column numbers\n * - Opera 9-: full stack trace with line numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the topmost stacktrace element\n * only\n * - IE: no line numbers whatsoever\n *\n * Tries to guess names of anonymous functions by looking for assignments\n * in the source code. In IE and Safari, we have to guess source file names\n * by searching for function bodies inside all page scripts. This will not\n * work for scripts that are loaded cross-domain.\n * Here be dragons: some function names may be guessed incorrectly, and\n * duplicate functions may be mismatched.\n *\n * TraceKit.computeStackTrace should only be used for tracing purposes.\n * Logging of unhandled exceptions should be done with TraceKit.report,\n * which builds on top of TraceKit.computeStackTrace and provides better\n * IE support by utilizing the window.onerror event to retrieve information\n * about the top of the stack.\n *\n * Note: In IE and Safari, no stack trace is recorded on the Error object,\n * so computeStackTrace instead walks its *own* chain of callers.\n * This means that:\n * * in Safari, some methods may be missing from the stack trace;\n * * in IE, the topmost function in the stack trace will always be the\n * caller of computeStackTrace.\n *\n * This is okay for tracing (because you are likely to be calling\n * computeStackTrace from the function you want to be the topmost element\n * of the stack trace anyway), but not okay for logging unhandled\n * exceptions (because your catch block will likely be far away from the\n * inner function that actually caused the exception).\n *\n */\nTraceKit.computeStackTrace = (function computeStackTraceWrapper() {\n // Contents of Exception in various browsers.\n //\n // SAFARI:\n // ex.message = Can't find variable: qq\n // ex.line = 59\n // ex.sourceId = 580238192\n // ex.sourceURL = http://...\n // ex.expressionBeginOffset = 96\n // ex.expressionCaretOffset = 98\n // ex.expressionEndOffset = 98\n // ex.name = ReferenceError\n //\n // FIREFOX:\n // ex.message = qq is not defined\n // ex.fileName = http://...\n // ex.lineNumber = 59\n // ex.columnNumber = 69\n // ex.stack = ...stack trace... (see the example below)\n // ex.name = ReferenceError\n //\n // CHROME:\n // ex.message = qq is not defined\n // ex.name = ReferenceError\n // ex.type = not_defined\n // ex.arguments = ['aa']\n // ex.stack = ...stack trace...\n //\n // INTERNET EXPLORER:\n // ex.message = ...\n // ex.name = ReferenceError\n //\n // OPERA:\n // ex.message = ...message... (see the example below)\n // ex.name = ReferenceError\n // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)\n // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'\n\n /**\n * Computes stack trace information from the stack property.\n * Chrome and Gecko use this property.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceFromStackProp(ex) {\n if (typeof ex.stack === 'undefined' || !ex.stack) return;\n\n var chrome = /^\\s*at (?:(.*?) ?\\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\\/).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i;\n var winjs = /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i;\n // NOTE: blob urls are now supposed to always have an origin, therefore it's format\n // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\\/` as well\n var gecko = /^\\s*(.*?)(?:\\((.*?)\\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\\/.*?|\\[native code\\]|[^@]*bundle)(?::(\\d+))?(?::(\\d+))?\\s*$/i;\n // Used to additionally parse URL/line/column from eval frames\n var geckoEval = /(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i;\n var chromeEval = /\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/;\n var lines = ex.stack.split('\\n');\n var stack = [];\n var submatch;\n var parts;\n var element;\n var reference = /^(.*) is undefined$/.exec(ex.message);\n\n for (var i = 0, j = lines.length; i < j; ++i) {\n if ((parts = chrome.exec(lines[i]))) {\n var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line\n var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line\n if (isEval && (submatch = chromeEval.exec(parts[2]))) {\n // throw out eval line/column and use top-most line/column number\n parts[2] = submatch[1]; // url\n parts[3] = submatch[2]; // line\n parts[4] = submatch[3]; // column\n }\n element = {\n url: !isNative ? parts[2] : null,\n func: parts[1] || UNKNOWN_FUNCTION,\n args: isNative ? [parts[2]] : [],\n line: parts[3] ? +parts[3] : null,\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = winjs.exec(lines[i]))) {\n element = {\n url: parts[2],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: [],\n line: +parts[3],\n column: parts[4] ? +parts[4] : null\n };\n } else if ((parts = gecko.exec(lines[i]))) {\n var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;\n if (isEval && (submatch = geckoEval.exec(parts[3]))) {\n // throw out eval line/column and use top-most line number\n parts[3] = submatch[1];\n parts[4] = submatch[2];\n parts[5] = null; // no column when eval\n } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {\n // FireFox uses this awesome columnNumber property for its top frame\n // Also note, Firefox's column number is 0-based and everything else expects 1-based,\n // so adding 1\n // NOTE: this hack doesn't work if top-most frame is eval\n stack[0].column = ex.columnNumber + 1;\n }\n element = {\n url: parts[3],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: parts[2] ? parts[2].split(',') : [],\n line: parts[4] ? +parts[4] : null,\n column: parts[5] ? +parts[5] : null\n };\n } else {\n continue;\n }\n\n if (!element.func && element.line) {\n element.func = UNKNOWN_FUNCTION;\n }\n\n if (element.url && element.url.substr(0, 5) === 'blob:') {\n // Special case for handling JavaScript loaded into a blob.\n // We use a synchronous AJAX request here as a blob is already in\n // memory - it's not making a network request. This will generate a warning\n // in the browser console, but there has already been an error so that's not\n // that much of an issue.\n var xhr = new XMLHttpRequest();\n xhr.open('GET', element.url, false);\n xhr.send(null);\n\n // If we failed to download the source, skip this patch\n if (xhr.status === 200) {\n var source = xhr.responseText || '';\n\n // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file.\n // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175\n source = source.slice(-300);\n\n // Now we dig out the source map URL\n var sourceMaps = source.match(/\\/\\/# sourceMappingURL=(.*)$/);\n\n // If we don't find a source map comment or we find more than one, continue on to the next element.\n if (sourceMaps) {\n var sourceMapAddress = sourceMaps[1];\n\n // Now we check to see if it's a relative URL.\n // If it is, convert it to an absolute one.\n if (sourceMapAddress.charAt(0) === '~') {\n sourceMapAddress = getLocationOrigin() + sourceMapAddress.slice(1);\n }\n\n // Now we strip the '.map' off of the end of the URL and update the\n // element so that Sentry can match the map to the blob.\n element.url = sourceMapAddress.slice(0, -4);\n }\n }\n }\n\n stack.push(element);\n }\n\n if (!stack.length) {\n return null;\n }\n\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n }\n\n /**\n * Adds information about the first frame to incomplete stack traces.\n * Safari and IE require this to get complete data on the first frame.\n * @param {Object.<string, *>} stackInfo Stack trace information from\n * one of the compute* methods.\n * @param {string} url The URL of the script that caused an error.\n * @param {(number|string)} lineNo The line number of the script that\n * caused an error.\n * @param {string=} message The error generated by the browser, which\n * hopefully contains the name of the object that caused the error.\n * @return {boolean} Whether or not the stack information was\n * augmented.\n */\n function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {\n var initial = {\n url: url,\n line: lineNo\n };\n\n if (initial.url && initial.line) {\n stackInfo.incomplete = false;\n\n if (!initial.func) {\n initial.func = UNKNOWN_FUNCTION;\n }\n\n if (stackInfo.stack.length > 0) {\n if (stackInfo.stack[0].url === initial.url) {\n if (stackInfo.stack[0].line === initial.line) {\n return false; // already in stack trace\n } else if (\n !stackInfo.stack[0].line &&\n stackInfo.stack[0].func === initial.func\n ) {\n stackInfo.stack[0].line = initial.line;\n return false;\n }\n }\n }\n\n stackInfo.stack.unshift(initial);\n stackInfo.partial = true;\n return true;\n } else {\n stackInfo.incomplete = true;\n }\n\n return false;\n }\n\n /**\n * Computes stack trace information by walking the arguments.caller\n * chain at the time the exception occurred. This will cause earlier\n * frames to be missed but is the only way to get any stack trace in\n * Safari and IE. The top frame is restored by\n * {@link augmentStackTraceWithInitialElement}.\n * @param {Error} ex\n * @return {?Object.<string, *>} Stack trace information.\n */\n function computeStackTraceByWalkingCallerChain(ex, depth) {\n var functionName = /function\\s+([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*)?\\s*\\(/i,\n stack = [],\n funcs = {},\n recursion = false,\n parts,\n item,\n source;\n\n for (\n var curr = computeStackTraceByWalkingCallerChain.caller;\n curr && !recursion;\n curr = curr.caller\n ) {\n if (curr === computeStackTrace || curr === TraceKit.report) {\n // console.log('skipping internal function');\n continue;\n }\n\n item = {\n url: null,\n func: UNKNOWN_FUNCTION,\n line: null,\n column: null\n };\n\n if (curr.name) {\n item.func = curr.name;\n } else if ((parts = functionName.exec(curr.toString()))) {\n item.func = parts[1];\n }\n\n if (typeof item.func === 'undefined') {\n try {\n item.func = parts.input.substring(0, parts.input.indexOf('{'));\n } catch (e) {}\n }\n\n if (funcs['' + curr]) {\n recursion = true;\n } else {\n funcs['' + curr] = true;\n }\n\n stack.push(item);\n }\n\n if (depth) {\n // console.log('depth is ' + depth);\n // console.log('stack is ' + stack.length);\n stack.splice(0, depth);\n }\n\n var result = {\n name: ex.name,\n message: ex.message,\n url: getLocationHref(),\n stack: stack\n };\n augmentStackTraceWithInitialElement(\n result,\n ex.sourceURL || ex.fileName,\n ex.line || ex.lineNumber,\n ex.message || ex.description\n );\n return result;\n }\n\n /**\n * Computes a stack trace for an exception.\n * @param {Error} ex\n * @param {(string|number)=} depth\n */\n function computeStackTrace(ex, depth) {\n var stack = null;\n depth = depth == null ? 0 : +depth;\n\n try {\n stack = computeStackTraceFromStackProp(ex);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n\n try {\n stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);\n if (stack) {\n return stack;\n }\n } catch (e) {\n if (TraceKit.debug) {\n throw e;\n }\n }\n return {\n name: ex.name,\n message: ex.message,\n url: getLocationHref()\n };\n }\n\n computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;\n computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp;\n\n return computeStackTrace;\n})();\n\nmodule.exports = TraceKit;\n","/*\n * JavaScript MD5\n * https://github.com/blueimp/JavaScript-MD5\n *\n * Copyright 2011, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * https://opensource.org/licenses/MIT\n *\n * Based on\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for more info.\n */\n\n/*\n* Add integers, wrapping at 2^32. This uses 16-bit operations internally\n* to work around bugs in some JS interpreters.\n*/\nfunction safeAdd(x, y) {\n var lsw = (x & 0xffff) + (y & 0xffff);\n var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n}\n\n/*\n* Bitwise rotate a 32-bit number to the left.\n*/\nfunction bitRotateLeft(num, cnt) {\n return (num << cnt) | (num >>> (32 - cnt));\n}\n\n/*\n* These functions implement the four basic operations the algorithm uses.\n*/\nfunction md5cmn(q, a, b, x, s, t) {\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n}\nfunction md5ff(a, b, c, d, x, s, t) {\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\n}\nfunction md5gg(a, b, c, d, x, s, t) {\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\n}\nfunction md5hh(a, b, c, d, x, s, t) {\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\n}\nfunction md5ii(a, b, c, d, x, s, t) {\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\n/*\n* Calculate the MD5 of an array of little-endian words, and a bit length.\n*/\nfunction binlMD5(x, len) {\n /* append padding */\n x[len >> 5] |= 0x80 << (len % 32);\n x[(((len + 64) >>> 9) << 4) + 14] = len;\n\n var i;\n var olda;\n var oldb;\n var oldc;\n var oldd;\n var a = 1732584193;\n var b = -271733879;\n var c = -1732584194;\n var d = 271733878;\n\n for (i = 0; i < x.length; i += 16) {\n olda = a;\n oldb = b;\n oldc = c;\n oldd = d;\n\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\n\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\n\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\n\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\n\n a = safeAdd(a, olda);\n b = safeAdd(b, oldb);\n c = safeAdd(c, oldc);\n d = safeAdd(d, oldd);\n }\n return [a, b, c, d];\n}\n\n/*\n* Convert an array of little-endian words to a string\n*/\nfunction binl2rstr(input) {\n var i;\n var output = '';\n var length32 = input.length * 32;\n for (i = 0; i < length32; i += 8) {\n output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff);\n }\n return output;\n}\n\n/*\n* Convert a raw string to an array of little-endian words\n* Characters >255 have their high-byte silently ignored.\n*/\nfunction rstr2binl(input) {\n var i;\n var output = [];\n output[(input.length >> 2) - 1] = undefined;\n for (i = 0; i < output.length; i += 1) {\n output[i] = 0;\n }\n var length8 = input.length * 8;\n for (i = 0; i < length8; i += 8) {\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32);\n }\n return output;\n}\n\n/*\n* Calculate the MD5 of a raw string\n*/\nfunction rstrMD5(s) {\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\n}\n\n/*\n* Calculate the HMAC-MD5, of a key and some data (raw strings)\n*/\nfunction rstrHMACMD5(key, data) {\n var i;\n var bkey = rstr2binl(key);\n var ipad = [];\n var opad = [];\n var hash;\n ipad[15] = opad[15] = undefined;\n if (bkey.length > 16) {\n bkey = binlMD5(bkey, key.length * 8);\n }\n for (i = 0; i < 16; i += 1) {\n ipad[i] = bkey[i] ^ 0x36363636;\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\n }\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\n}\n\n/*\n* Convert a raw string to a hex string\n*/\nfunction rstr2hex(input) {\n var hexTab = '0123456789abcdef';\n var output = '';\n var x;\n var i;\n for (i = 0; i < input.length; i += 1) {\n x = input.charCodeAt(i);\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\n }\n return output;\n}\n\n/*\n* Encode a string as utf-8\n*/\nfunction str2rstrUTF8(input) {\n return unescape(encodeURIComponent(input));\n}\n\n/*\n* Take string arguments and return either raw or hex encoded strings\n*/\nfunction rawMD5(s) {\n return rstrMD5(str2rstrUTF8(s));\n}\nfunction hexMD5(s) {\n return rstr2hex(rawMD5(s));\n}\nfunction rawHMACMD5(k, d) {\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\n}\nfunction hexHMACMD5(k, d) {\n return rstr2hex(rawHMACMD5(k, d));\n}\n\nfunction md5(string, key, raw) {\n if (!key) {\n if (!raw) {\n return hexMD5(string);\n }\n return rawMD5(string);\n }\n if (!raw) {\n return hexHMACMD5(key, string);\n }\n return rawHMACMD5(key, string);\n}\n\nmodule.exports = md5;\n","function RavenConfigError(message) {\n this.name = 'RavenConfigError';\n this.message = message;\n}\nRavenConfigError.prototype = new Error();\nRavenConfigError.prototype.constructor = RavenConfigError;\n\nmodule.exports = RavenConfigError;\n","var utils = require('./utils');\n\nvar wrapMethod = function(console, level, callback) {\n var originalConsoleLevel = console[level];\n var originalConsole = console;\n\n if (!(level in console)) {\n return;\n }\n\n var sentryLevel = level === 'warn' ? 'warning' : level;\n\n console[level] = function() {\n var args = [].slice.call(arguments);\n\n var msg = utils.safeJoin(args, ' ');\n var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}};\n\n if (level === 'assert') {\n if (args[0] === false) {\n // Default browsers message\n msg =\n 'Assertion failed: ' + (utils.safeJoin(args.slice(1), ' ') || 'console.assert');\n data.extra.arguments = args.slice(1);\n callback && callback(msg, data);\n }\n } else {\n callback && callback(msg, data);\n }\n\n // this fails for some browsers. :(\n if (originalConsoleLevel) {\n // IE9 doesn't allow calling apply on console functions directly\n // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193\n Function.prototype.apply.call(originalConsoleLevel, originalConsole, args);\n }\n };\n};\n\nmodule.exports = {\n wrapMethod: wrapMethod\n};\n","/*global XDomainRequest:false */\n\nvar TraceKit = require('../vendor/TraceKit/tracekit');\nvar stringify = require('../vendor/json-stringify-safe/stringify');\nvar md5 = require('../vendor/md5/md5');\nvar RavenConfigError = require('./configError');\n\nvar utils = require('./utils');\nvar isErrorEvent = utils.isErrorEvent;\nvar isDOMError = utils.isDOMError;\nvar isDOMException = utils.isDOMException;\nvar isError = utils.isError;\nvar isObject = utils.isObject;\nvar isPlainObject = utils.isPlainObject;\nvar isUndefined = utils.isUndefined;\nvar isFunction = utils.isFunction;\nvar isString = utils.isString;\nvar isArray = utils.isArray;\nvar isEmptyObject = utils.isEmptyObject;\nvar each = utils.each;\nvar objectMerge = utils.objectMerge;\nvar truncate = utils.truncate;\nvar objectFrozen = utils.objectFrozen;\nvar hasKey = utils.hasKey;\nvar joinRegExp = utils.joinRegExp;\nvar urlencode = utils.urlencode;\nvar uuid4 = utils.uuid4;\nvar htmlTreeAsString = utils.htmlTreeAsString;\nvar isSameException = utils.isSameException;\nvar isSameStacktrace = utils.isSameStacktrace;\nvar parseUrl = utils.parseUrl;\nvar fill = utils.fill;\nvar supportsFetch = utils.supportsFetch;\nvar supportsReferrerPolicy = utils.supportsReferrerPolicy;\nvar serializeKeysForMessage = utils.serializeKeysForMessage;\nvar serializeException = utils.serializeException;\nvar sanitize = utils.sanitize;\n\nvar wrapConsoleMethod = require('./console').wrapMethod;\n\nvar dsnKeys = 'source protocol user pass host port path'.split(' '),\n dsnPattern = /^(?:(\\w+):)?\\/\\/(?:(\\w+)(:\\w+)?@)?([\\w\\.-]+)(?::(\\d+))?(\\/.*)/;\n\nfunction now() {\n return +new Date();\n}\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _document = _window.document;\nvar _navigator = _window.navigator;\n\nfunction keepOriginalCallback(original, callback) {\n return isFunction(callback)\n ? function(data) {\n return callback(data, original);\n }\n : callback;\n}\n\n// First, check for JSON support\n// If there is no JSON, we no-op the core features of Raven\n// since JSON is required to encode the payload\nfunction Raven() {\n this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify);\n // Raven can run in contexts where there's no document (react-native)\n this._hasDocument = !isUndefined(_document);\n this._hasNavigator = !isUndefined(_navigator);\n this._lastCapturedException = null;\n this._lastData = null;\n this._lastEventId = null;\n this._globalServer = null;\n this._globalKey = null;\n this._globalProject = null;\n this._globalContext = {};\n this._globalOptions = {\n // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin\n release: _window.SENTRY_RELEASE && _window.SENTRY_RELEASE.id,\n logger: 'javascript',\n ignoreErrors: [],\n ignoreUrls: [],\n whitelistUrls: [],\n includePaths: [],\n headers: null,\n collectWindowErrors: true,\n captureUnhandledRejections: true,\n maxMessageLength: 0,\n // By default, truncates URL values to 250 chars\n maxUrlLength: 250,\n stackTraceLimit: 50,\n autoBreadcrumbs: true,\n instrument: true,\n sampleRate: 1,\n sanitizeKeys: []\n };\n this._fetchDefaults = {\n method: 'POST',\n // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n // https://caniuse.com/#feat=referrer-policy\n // It doesn't. And it throw exception instead of ignoring this parameter...\n // REF: https://github.com/getsentry/raven-js/issues/1233\n referrerPolicy: supportsReferrerPolicy() ? 'origin' : ''\n };\n this._ignoreOnError = 0;\n this._isRavenInstalled = false;\n this._originalErrorStackTraceLimit = Error.stackTraceLimit;\n // capture references to window.console *and* all its methods first\n // before the console plugin has a chance to monkey patch\n this._originalConsole = _window.console || {};\n this._originalConsoleMethods = {};\n this._plugins = [];\n this._startTime = now();\n this._wrappedBuiltIns = [];\n this._breadcrumbs = [];\n this._lastCapturedEvent = null;\n this._keypressTimeout;\n this._location = _window.location;\n this._lastHref = this._location && this._location.href;\n this._resetBackoff();\n\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsole) {\n this._originalConsoleMethods[method] = this._originalConsole[method];\n }\n}\n\n/*\n * The core Raven singleton\n *\n * @this {Raven}\n */\n\nRaven.prototype = {\n // Hardcode version string so that raven source can be loaded directly via\n // webpack (using a build step causes webpack #1617). Grunt verifies that\n // this value matches package.json during build.\n // See: https://github.com/getsentry/raven-js/issues/465\n VERSION: '3.27.0',\n\n debug: false,\n\n TraceKit: TraceKit, // alias to TraceKit\n\n /*\n * Configure Raven with a DSN and extra options\n *\n * @param {string} dsn The public Sentry DSN\n * @param {object} options Set of global options [optional]\n * @return {Raven}\n */\n config: function(dsn, options) {\n var self = this;\n\n if (self._globalServer) {\n this._logDebug('error', 'Error: Raven has already been configured');\n return self;\n }\n if (!dsn) return self;\n\n var globalOptions = self._globalOptions;\n\n // merge in options\n if (options) {\n each(options, function(key, value) {\n // tags and extra are special and need to be put into context\n if (key === 'tags' || key === 'extra' || key === 'user') {\n self._globalContext[key] = value;\n } else {\n globalOptions[key] = value;\n }\n });\n }\n\n self.setDSN(dsn);\n\n // \"Script error.\" is hard coded into browsers for errors that it can't read.\n // this is the result of a script being pulled in from an external domain and CORS.\n globalOptions.ignoreErrors.push(/^Script error\\.?$/);\n globalOptions.ignoreErrors.push(/^Javascript error: Script error\\.? on line 0$/);\n\n // join regexp rules into one big rule\n globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);\n globalOptions.ignoreUrls = globalOptions.ignoreUrls.length\n ? joinRegExp(globalOptions.ignoreUrls)\n : false;\n globalOptions.whitelistUrls = globalOptions.whitelistUrls.length\n ? joinRegExp(globalOptions.whitelistUrls)\n : false;\n globalOptions.includePaths = joinRegExp(globalOptions.includePaths);\n globalOptions.maxBreadcrumbs = Math.max(\n 0,\n Math.min(globalOptions.maxBreadcrumbs || 100, 100)\n ); // default and hard limit is 100\n\n var autoBreadcrumbDefaults = {\n xhr: true,\n console: true,\n dom: true,\n location: true,\n sentry: true\n };\n\n var autoBreadcrumbs = globalOptions.autoBreadcrumbs;\n if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {\n autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);\n } else if (autoBreadcrumbs !== false) {\n autoBreadcrumbs = autoBreadcrumbDefaults;\n }\n globalOptions.autoBreadcrumbs = autoBreadcrumbs;\n\n var instrumentDefaults = {\n tryCatch: true\n };\n\n var instrument = globalOptions.instrument;\n if ({}.toString.call(instrument) === '[object Object]') {\n instrument = objectMerge(instrumentDefaults, instrument);\n } else if (instrument !== false) {\n instrument = instrumentDefaults;\n }\n globalOptions.instrument = instrument;\n\n TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;\n\n // return for chaining\n return self;\n },\n\n /*\n * Installs a global window.onerror error handler\n * to capture and report uncaught exceptions.\n * At this point, install() is required to be called due\n * to the way TraceKit is set up.\n *\n * @return {Raven}\n */\n install: function() {\n var self = this;\n if (self.isSetup() && !self._isRavenInstalled) {\n TraceKit.report.subscribe(function() {\n self._handleOnErrorStackInfo.apply(self, arguments);\n });\n\n if (self._globalOptions.captureUnhandledRejections) {\n self._attachPromiseRejectionHandler();\n }\n\n self._patchFunctionToString();\n\n if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) {\n self._instrumentTryCatch();\n }\n\n if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs();\n\n // Install all of the plugins\n self._drainPlugins();\n\n self._isRavenInstalled = true;\n }\n\n Error.stackTraceLimit = self._globalOptions.stackTraceLimit;\n return this;\n },\n\n /*\n * Set the DSN (can be called multiple time unlike config)\n *\n * @param {string} dsn The public Sentry DSN\n */\n setDSN: function(dsn) {\n var self = this,\n uri = self._parseDSN(dsn),\n lastSlash = uri.path.lastIndexOf('/'),\n path = uri.path.substr(1, lastSlash);\n\n self._dsn = dsn;\n self._globalKey = uri.user;\n self._globalSecret = uri.pass && uri.pass.substr(1);\n self._globalProject = uri.path.substr(lastSlash + 1);\n\n self._globalServer = self._getGlobalServer(uri);\n\n self._globalEndpoint =\n self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/';\n\n // Reset backoff state since we may be pointing at a\n // new project/server\n this._resetBackoff();\n },\n\n /*\n * Wrap code within a context so Raven can capture errors\n * reliably across domains that is executed immediately.\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The callback to be immediately executed within the context\n * @param {array} args An array of arguments to be called with the callback [optional]\n */\n context: function(options, func, args) {\n if (isFunction(options)) {\n args = func || [];\n func = options;\n options = {};\n }\n\n return this.wrap(options, func).apply(this, args);\n },\n\n /*\n * Wrap code within a context and returns back a new function to be executed\n *\n * @param {object} options A specific set of options for this context [optional]\n * @param {function} func The function to be wrapped in a new context\n * @param {function} _before A function to call before the try/catch wrapper [optional, private]\n * @return {function} The newly wrapped functions with a context\n */\n wrap: function(options, func, _before) {\n var self = this;\n // 1 argument has been passed, and it's not a function\n // so just return it\n if (isUndefined(func) && !isFunction(options)) {\n return options;\n }\n\n // options is optional\n if (isFunction(options)) {\n func = options;\n options = undefined;\n }\n\n // At this point, we've passed along 2 arguments, and the second one\n // is not a function either, so we'll just return the second argument.\n if (!isFunction(func)) {\n return func;\n }\n\n // We don't wanna wrap it twice!\n try {\n if (func.__raven__) {\n return func;\n }\n\n // If this has already been wrapped in the past, return that\n if (func.__raven_wrapper__) {\n return func.__raven_wrapper__;\n }\n } catch (e) {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return func;\n }\n\n function wrapped() {\n var args = [],\n i = arguments.length,\n deep = !options || (options && options.deep !== false);\n\n if (_before && isFunction(_before)) {\n _before.apply(this, arguments);\n }\n\n // Recursively wrap all of a function's arguments that are\n // functions themselves.\n while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i];\n\n try {\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means Raven caught an error invoking your application code. This is\n // expected behavior and NOT indicative of a bug with Raven.js.\n return func.apply(this, args);\n } catch (e) {\n self._ignoreNextOnError();\n self.captureException(e, options);\n throw e;\n }\n }\n\n // copy over properties of the old function\n for (var property in func) {\n if (hasKey(func, property)) {\n wrapped[property] = func[property];\n }\n }\n wrapped.prototype = func.prototype;\n\n func.__raven_wrapper__ = wrapped;\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n wrapped.__raven__ = true;\n wrapped.__orig__ = func;\n\n return wrapped;\n },\n\n /**\n * Uninstalls the global error handler.\n *\n * @return {Raven}\n */\n uninstall: function() {\n TraceKit.report.uninstall();\n\n this._detachPromiseRejectionHandler();\n this._unpatchFunctionToString();\n this._restoreBuiltIns();\n this._restoreConsole();\n\n Error.stackTraceLimit = this._originalErrorStackTraceLimit;\n this._isRavenInstalled = false;\n\n return this;\n },\n\n /**\n * Callback used for `unhandledrejection` event\n *\n * @param {PromiseRejectionEvent} event An object containing\n * promise: the Promise that was rejected\n * reason: the value with which the Promise was rejected\n * @return void\n */\n _promiseRejectionHandler: function(event) {\n this._logDebug('debug', 'Raven caught unhandled promise rejection:', event);\n this.captureException(event.reason, {\n mechanism: {\n type: 'onunhandledrejection',\n handled: false\n }\n });\n },\n\n /**\n * Installs the global promise rejection handler.\n *\n * @return {raven}\n */\n _attachPromiseRejectionHandler: function() {\n this._promiseRejectionHandler = this._promiseRejectionHandler.bind(this);\n _window.addEventListener &&\n _window.addEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Uninstalls the global promise rejection handler.\n *\n * @return {raven}\n */\n _detachPromiseRejectionHandler: function() {\n _window.removeEventListener &&\n _window.removeEventListener('unhandledrejection', this._promiseRejectionHandler);\n return this;\n },\n\n /**\n * Manually capture an exception and send it over to Sentry\n *\n * @param {error} ex An exception to be logged\n * @param {object} options A specific set of options for this error [optional]\n * @return {Raven}\n */\n captureException: function(ex, options) {\n options = objectMerge({trimHeadFrames: 0}, options ? options : {});\n\n if (isErrorEvent(ex) && ex.error) {\n // If it is an ErrorEvent with `error` property, extract it to get actual Error\n ex = ex.error;\n } else if (isDOMError(ex) || isDOMException(ex)) {\n // If it is a DOMError or DOMException (which are legacy APIs, but still supported in some browsers)\n // then we just extract the name and message, as they don't provide anything else\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMError\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n var name = ex.name || (isDOMError(ex) ? 'DOMError' : 'DOMException');\n var message = ex.message ? name + ': ' + ex.message : name;\n\n return this.captureMessage(\n message,\n objectMerge(options, {\n // neither DOMError or DOMException provide stack trace and we most likely wont get it this way as well\n // but it's barely any overhead so we may at least try\n stacktrace: true,\n trimHeadFrames: options.trimHeadFrames + 1\n })\n );\n } else if (isError(ex)) {\n // we have a real Error object\n ex = ex;\n } else if (isPlainObject(ex)) {\n // If it is plain Object, serialize it manually and extract options\n // This will allow us to group events based on top-level keys\n // which is much better than creating new group when any key/value change\n options = this._getCaptureExceptionOptionsFromPlainObject(options, ex);\n ex = new Error(options.message);\n } else {\n // If none of previous checks were valid, then it means that\n // it's not a DOMError/DOMException\n // it's not a plain Object\n // it's not a valid ErrorEvent (one with an error property)\n // it's not an Error\n // So bail out and capture it as a simple message:\n return this.captureMessage(\n ex,\n objectMerge(options, {\n stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace\n trimHeadFrames: options.trimHeadFrames + 1\n })\n );\n }\n\n // Store the raw exception object for potential debugging and introspection\n this._lastCapturedException = ex;\n\n // TraceKit.report will re-raise any exception passed to it,\n // which means you have to wrap it in try/catch. Instead, we\n // can wrap it here and only re-raise if TraceKit.report\n // raises an exception different from the one we asked to\n // report on.\n try {\n var stack = TraceKit.computeStackTrace(ex);\n this._handleStackInfo(stack, options);\n } catch (ex1) {\n if (ex !== ex1) {\n throw ex1;\n }\n }\n\n return this;\n },\n\n _getCaptureExceptionOptionsFromPlainObject: function(currentOptions, ex) {\n var exKeys = Object.keys(ex).sort();\n var options = objectMerge(currentOptions, {\n message:\n 'Non-Error exception captured with keys: ' + serializeKeysForMessage(exKeys),\n fingerprint: [md5(exKeys)],\n extra: currentOptions.extra || {}\n });\n options.extra.__serialized__ = serializeException(ex);\n\n return options;\n },\n\n /*\n * Manually send a message to Sentry\n *\n * @param {string} msg A plain message to be captured in Sentry\n * @param {object} options A specific set of options for this message [optional]\n * @return {Raven}\n */\n captureMessage: function(msg, options) {\n // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an\n // early call; we'll error on the side of logging anything called before configuration since it's\n // probably something you should see:\n if (\n !!this._globalOptions.ignoreErrors.test &&\n this._globalOptions.ignoreErrors.test(msg)\n ) {\n return;\n }\n\n options = options || {};\n msg = msg + ''; // Make sure it's actually a string\n\n var data = objectMerge(\n {\n message: msg\n },\n options\n );\n\n var ex;\n // Generate a \"synthetic\" stack trace from this point.\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative\n // of a bug with Raven.js. Sentry generates synthetic traces either by configuration,\n // or if it catches a thrown object without a \"stack\" property.\n try {\n throw new Error(msg);\n } catch (ex1) {\n ex = ex1;\n }\n\n // null exception name so `Error` isn't prefixed to msg\n ex.name = null;\n var stack = TraceKit.computeStackTrace(ex);\n\n // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]\n var initialCall = isArray(stack.stack) && stack.stack[1];\n\n // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call\n // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd\n // initialCall => captureException(string) => captureMessage(string)\n if (initialCall && initialCall.func === 'Raven.captureException') {\n initialCall = stack.stack[2];\n }\n\n var fileurl = (initialCall && initialCall.url) || '';\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n // Always attempt to get stacktrace if message is empty.\n // It's the only way to provide any helpful information to the user.\n if (this._globalOptions.stacktrace || options.stacktrace || data.message === '') {\n // fingerprint on msg, not stack trace (legacy behavior, could be revisited)\n data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;\n\n options = objectMerge(\n {\n trimHeadFrames: 0\n },\n options\n );\n // Since we know this is a synthetic trace, the top frame (this function call)\n // MUST be from Raven.js, so mark it for trimming\n // We add to the trim counter so that callers can choose to trim extra frames, such\n // as utility functions.\n options.trimHeadFrames += 1;\n\n var frames = this._prepareFrames(stack, options);\n data.stacktrace = {\n // Sentry expects frames oldest to newest\n frames: frames.reverse()\n };\n }\n\n // Make sure that fingerprint is always wrapped in an array\n if (data.fingerprint) {\n data.fingerprint = isArray(data.fingerprint)\n ? data.fingerprint\n : [data.fingerprint];\n }\n\n // Fire away!\n this._send(data);\n\n return this;\n },\n\n captureBreadcrumb: function(obj) {\n var crumb = objectMerge(\n {\n timestamp: now() / 1000\n },\n obj\n );\n\n if (isFunction(this._globalOptions.breadcrumbCallback)) {\n var result = this._globalOptions.breadcrumbCallback(crumb);\n\n if (isObject(result) && !isEmptyObject(result)) {\n crumb = result;\n } else if (result === false) {\n return this;\n }\n }\n\n this._breadcrumbs.push(crumb);\n if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {\n this._breadcrumbs.shift();\n }\n return this;\n },\n\n addPlugin: function(plugin /*arg1, arg2, ... argN*/) {\n var pluginArgs = [].slice.call(arguments, 1);\n\n this._plugins.push([plugin, pluginArgs]);\n if (this._isRavenInstalled) {\n this._drainPlugins();\n }\n\n return this;\n },\n\n /*\n * Set/clear a user to be sent along with the payload.\n *\n * @param {object} user An object representing user data [optional]\n * @return {Raven}\n */\n setUserContext: function(user) {\n // Intentionally do not merge here since that's an unexpected behavior.\n this._globalContext.user = user;\n\n return this;\n },\n\n /*\n * Merge extra attributes to be sent along with the payload.\n *\n * @param {object} extra An object representing extra data [optional]\n * @return {Raven}\n */\n setExtraContext: function(extra) {\n this._mergeContext('extra', extra);\n\n return this;\n },\n\n /*\n * Merge tags to be sent along with the payload.\n *\n * @param {object} tags An object representing tags [optional]\n * @return {Raven}\n */\n setTagsContext: function(tags) {\n this._mergeContext('tags', tags);\n\n return this;\n },\n\n /*\n * Clear all of the context.\n *\n * @return {Raven}\n */\n clearContext: function() {\n this._globalContext = {};\n\n return this;\n },\n\n /*\n * Get a copy of the current context. This cannot be mutated.\n *\n * @return {object} copy of context\n */\n getContext: function() {\n // lol javascript\n return JSON.parse(stringify(this._globalContext));\n },\n\n /*\n * Set environment of application\n *\n * @param {string} environment Typically something like 'production'.\n * @return {Raven}\n */\n setEnvironment: function(environment) {\n this._globalOptions.environment = environment;\n\n return this;\n },\n\n /*\n * Set release version of application\n *\n * @param {string} release Typically something like a git SHA to identify version\n * @return {Raven}\n */\n setRelease: function(release) {\n this._globalOptions.release = release;\n\n return this;\n },\n\n /*\n * Set the dataCallback option\n *\n * @param {function} callback The callback to run which allows the\n * data blob to be mutated before sending\n * @return {Raven}\n */\n setDataCallback: function(callback) {\n var original = this._globalOptions.dataCallback;\n this._globalOptions.dataCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the breadcrumbCallback option\n *\n * @param {function} callback The callback to run which allows filtering\n * or mutating breadcrumbs\n * @return {Raven}\n */\n setBreadcrumbCallback: function(callback) {\n var original = this._globalOptions.breadcrumbCallback;\n this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /*\n * Set the shouldSendCallback option\n *\n * @param {function} callback The callback to run which allows\n * introspecting the blob before sending\n * @return {Raven}\n */\n setShouldSendCallback: function(callback) {\n var original = this._globalOptions.shouldSendCallback;\n this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback);\n return this;\n },\n\n /**\n * Override the default HTTP transport mechanism that transmits data\n * to the Sentry server.\n *\n * @param {function} transport Function invoked instead of the default\n * `makeRequest` handler.\n *\n * @return {Raven}\n */\n setTransport: function(transport) {\n this._globalOptions.transport = transport;\n\n return this;\n },\n\n /*\n * Get the latest raw exception that was captured by Raven.\n *\n * @return {error}\n */\n lastException: function() {\n return this._lastCapturedException;\n },\n\n /*\n * Get the last event id\n *\n * @return {string}\n */\n lastEventId: function() {\n return this._lastEventId;\n },\n\n /*\n * Determine if Raven is setup and ready to go.\n *\n * @return {boolean}\n */\n isSetup: function() {\n if (!this._hasJSON) return false; // needs JSON support\n if (!this._globalServer) {\n if (!this.ravenNotConfiguredError) {\n this.ravenNotConfiguredError = true;\n this._logDebug('error', 'Error: Raven has not been configured.');\n }\n return false;\n }\n return true;\n },\n\n afterLoad: function() {\n // TODO: remove window dependence?\n\n // Attempt to initialize Raven on load\n var RavenConfig = _window.RavenConfig;\n if (RavenConfig) {\n this.config(RavenConfig.dsn, RavenConfig.config).install();\n }\n },\n\n showReportDialog: function(options) {\n if (\n !_document // doesn't work without a document (React native)\n )\n return;\n\n options = objectMerge(\n {\n eventId: this.lastEventId(),\n dsn: this._dsn,\n user: this._globalContext.user || {}\n },\n options\n );\n\n if (!options.eventId) {\n throw new RavenConfigError('Missing eventId');\n }\n\n if (!options.dsn) {\n throw new RavenConfigError('Missing DSN');\n }\n\n var encode = encodeURIComponent;\n var encodedOptions = [];\n\n for (var key in options) {\n if (key === 'user') {\n var user = options.user;\n if (user.name) encodedOptions.push('name=' + encode(user.name));\n if (user.email) encodedOptions.push('email=' + encode(user.email));\n } else {\n encodedOptions.push(encode(key) + '=' + encode(options[key]));\n }\n }\n var globalServer = this._getGlobalServer(this._parseDSN(options.dsn));\n\n var script = _document.createElement('script');\n script.async = true;\n script.src = globalServer + '/api/embed/error-page/?' + encodedOptions.join('&');\n (_document.head || _document.body).appendChild(script);\n },\n\n /**** Private functions ****/\n _ignoreNextOnError: function() {\n var self = this;\n this._ignoreOnError += 1;\n setTimeout(function() {\n // onerror should trigger before setTimeout\n self._ignoreOnError -= 1;\n });\n },\n\n _triggerEvent: function(eventType, options) {\n // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it\n var evt, key;\n\n if (!this._hasDocument) return;\n\n options = options || {};\n\n eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1);\n\n if (_document.createEvent) {\n evt = _document.createEvent('HTMLEvents');\n evt.initEvent(eventType, true, true);\n } else {\n evt = _document.createEventObject();\n evt.eventType = eventType;\n }\n\n for (key in options)\n if (hasKey(options, key)) {\n evt[key] = options[key];\n }\n\n if (_document.createEvent) {\n // IE9 if standards\n _document.dispatchEvent(evt);\n } else {\n // IE8 regardless of Quirks or Standards\n // IE9 if quirks\n try {\n _document.fireEvent('on' + evt.eventType.toLowerCase(), evt);\n } catch (e) {\n // Do nothing\n }\n }\n },\n\n /**\n * Wraps addEventListener to capture UI breadcrumbs\n * @param evtName the event name (e.g. \"click\")\n * @returns {Function}\n * @private\n */\n _breadcrumbEventHandler: function(evtName) {\n var self = this;\n return function(evt) {\n // reset keypress timeout; e.g. triggering a 'click' after\n // a 'keypress' will reset the keypress debounce so that a new\n // set of keypresses can be recorded\n self._keypressTimeout = null;\n\n // It's possible this handler might trigger multiple times for the same\n // event (e.g. event propagation through node ancestors). Ignore if we've\n // already captured the event.\n if (self._lastCapturedEvent === evt) return;\n\n self._lastCapturedEvent = evt;\n\n // try/catch both:\n // - accessing evt.target (see getsentry/raven-js#838, #768)\n // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly\n // can throw an exception in some circumstances.\n var target;\n try {\n target = htmlTreeAsString(evt.target);\n } catch (e) {\n target = '<unknown>';\n }\n\n self.captureBreadcrumb({\n category: 'ui.' + evtName, // e.g. ui.click, ui.input\n message: target\n });\n };\n },\n\n /**\n * Wraps addEventListener to capture keypress UI events\n * @returns {Function}\n * @private\n */\n _keypressEventHandler: function() {\n var self = this,\n debounceDuration = 1000; // milliseconds\n\n // TODO: if somehow user switches keypress target before\n // debounce timeout is triggered, we will only capture\n // a single breadcrumb from the FIRST target (acceptable?)\n return function(evt) {\n var target;\n try {\n target = evt.target;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n var tagName = target && target.tagName;\n\n // only consider keypress events on actual input elements\n // this will disregard keypresses targeting body (e.g. tabbing\n // through elements, hotkeys, etc)\n if (\n !tagName ||\n (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)\n )\n return;\n\n // record first keypress in a series, but ignore subsequent\n // keypresses until debounce clears\n var timeout = self._keypressTimeout;\n if (!timeout) {\n self._breadcrumbEventHandler('input')(evt);\n }\n clearTimeout(timeout);\n self._keypressTimeout = setTimeout(function() {\n self._keypressTimeout = null;\n }, debounceDuration);\n };\n },\n\n /**\n * Captures a breadcrumb of type \"navigation\", normalizing input URLs\n * @param to the originating URL\n * @param from the target URL\n * @private\n */\n _captureUrlChange: function(from, to) {\n var parsedLoc = parseUrl(this._location.href);\n var parsedTo = parseUrl(to);\n var parsedFrom = parseUrl(from);\n\n // because onpopstate only tells you the \"new\" (to) value of location.href, and\n // not the previous (from) value, we need to track the value of the current URL\n // state ourselves\n this._lastHref = to;\n\n // Use only the path component of the URL if the URL matches the current\n // document (almost all the time when using pushState)\n if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host)\n to = parsedTo.relative;\n if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host)\n from = parsedFrom.relative;\n\n this.captureBreadcrumb({\n category: 'navigation',\n data: {\n to: to,\n from: from\n }\n });\n },\n\n _patchFunctionToString: function() {\n var self = this;\n self._originalFunctionToString = Function.prototype.toString;\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = function() {\n if (typeof this === 'function' && this.__raven__) {\n return self._originalFunctionToString.apply(this.__orig__, arguments);\n }\n return self._originalFunctionToString.apply(this, arguments);\n };\n },\n\n _unpatchFunctionToString: function() {\n if (this._originalFunctionToString) {\n // eslint-disable-next-line no-extend-native\n Function.prototype.toString = this._originalFunctionToString;\n }\n },\n\n /**\n * Wrap timer functions and event targets to catch errors and provide\n * better metadata.\n */\n _instrumentTryCatch: function() {\n var self = this;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapTimeFn(orig) {\n return function(fn, t) {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n var originalCallback = args[0];\n if (isFunction(originalCallback)) {\n args[0] = self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {function: orig.name || '<anonymous>'}\n }\n },\n originalCallback\n );\n }\n\n // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it\n // also supports only two arguments and doesn't care what this is, so we\n // can just call the original function directly.\n if (orig.apply) {\n return orig.apply(this, args);\n } else {\n return orig(args[0], args[1]);\n }\n };\n }\n\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n function wrapEventTarget(global) {\n var proto = _window[global] && _window[global].prototype;\n if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {\n fill(\n proto,\n 'addEventListener',\n function(orig) {\n return function(evtName, fn, capture, secure) {\n // preserve arity\n try {\n if (fn && fn.handleEvent) {\n fn.handleEvent = self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {\n target: global,\n function: 'handleEvent',\n handler: (fn && fn.name) || '<anonymous>'\n }\n }\n },\n fn.handleEvent\n );\n }\n } catch (err) {\n // can sometimes get 'Permission denied to access property \"handle Event'\n }\n\n // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`\n // so that we don't have more than one wrapper function\n var before, clickHandler, keypressHandler;\n\n if (\n autoBreadcrumbs &&\n autoBreadcrumbs.dom &&\n (global === 'EventTarget' || global === 'Node')\n ) {\n // NOTE: generating multiple handlers per addEventListener invocation, should\n // revisit and verify we can just use one (almost certainly)\n clickHandler = self._breadcrumbEventHandler('click');\n keypressHandler = self._keypressEventHandler();\n before = function(evt) {\n // need to intercept every DOM event in `before` argument, in case that\n // same wrapped method is re-used for different events (e.g. mousemove THEN click)\n // see #724\n if (!evt) return;\n\n var eventType;\n try {\n eventType = evt.type;\n } catch (e) {\n // just accessing event properties can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/raven-js/issues/838\n return;\n }\n if (eventType === 'click') return clickHandler(evt);\n else if (eventType === 'keypress') return keypressHandler(evt);\n };\n }\n return orig.call(\n this,\n evtName,\n self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {\n target: global,\n function: 'addEventListener',\n handler: (fn && fn.name) || '<anonymous>'\n }\n }\n },\n fn,\n before\n ),\n capture,\n secure\n );\n };\n },\n wrappedBuiltIns\n );\n fill(\n proto,\n 'removeEventListener',\n function(orig) {\n return function(evt, fn, capture, secure) {\n try {\n fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn);\n } catch (e) {\n // ignore, accessing __raven_wrapper__ will throw in some Selenium environments\n }\n return orig.call(this, evt, fn, capture, secure);\n };\n },\n wrappedBuiltIns\n );\n }\n }\n\n fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);\n fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns);\n if (_window.requestAnimationFrame) {\n fill(\n _window,\n 'requestAnimationFrame',\n function(orig) {\n return function(cb) {\n return orig(\n self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {\n function: 'requestAnimationFrame',\n handler: (orig && orig.name) || '<anonymous>'\n }\n }\n },\n cb\n )\n );\n };\n },\n wrappedBuiltIns\n );\n }\n\n // event targets borrowed from bugsnag-js:\n // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666\n var eventTargets = [\n 'EventTarget',\n 'Window',\n 'Node',\n 'ApplicationCache',\n 'AudioTrackList',\n 'ChannelMergerNode',\n 'CryptoOperation',\n 'EventSource',\n 'FileReader',\n 'HTMLUnknownElement',\n 'IDBDatabase',\n 'IDBRequest',\n 'IDBTransaction',\n 'KeyOperation',\n 'MediaController',\n 'MessagePort',\n 'ModalWindow',\n 'Notification',\n 'SVGElementInstance',\n 'Screen',\n 'TextTrack',\n 'TextTrackCue',\n 'TextTrackList',\n 'WebSocket',\n 'WebSocketWorker',\n 'Worker',\n 'XMLHttpRequest',\n 'XMLHttpRequestEventTarget',\n 'XMLHttpRequestUpload'\n ];\n for (var i = 0; i < eventTargets.length; i++) {\n wrapEventTarget(eventTargets[i]);\n }\n },\n\n /**\n * Instrument browser built-ins w/ breadcrumb capturing\n * - XMLHttpRequests\n * - DOM interactions (click/typing)\n * - window.location changes\n * - console\n *\n * Can be disabled or individually configured via the `autoBreadcrumbs` config option\n */\n _instrumentBreadcrumbs: function() {\n var self = this;\n var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;\n\n var wrappedBuiltIns = self._wrappedBuiltIns;\n\n function wrapProp(prop, xhr) {\n if (prop in xhr && isFunction(xhr[prop])) {\n fill(xhr, prop, function(orig) {\n return self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {function: prop, handler: (orig && orig.name) || '<anonymous>'}\n }\n },\n orig\n );\n }); // intentionally don't track filled methods on XHR instances\n }\n }\n\n if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) {\n var xhrproto = _window.XMLHttpRequest && _window.XMLHttpRequest.prototype;\n fill(\n xhrproto,\n 'open',\n function(origOpen) {\n return function(method, url) {\n // preserve arity\n\n // if Sentry key appears in URL, don't capture\n if (isString(url) && url.indexOf(self._globalKey) === -1) {\n this.__raven_xhr = {\n method: method,\n url: url,\n status_code: null\n };\n }\n\n return origOpen.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n\n fill(\n xhrproto,\n 'send',\n function(origSend) {\n return function() {\n // preserve arity\n var xhr = this;\n\n function onreadystatechangeHandler() {\n if (xhr.__raven_xhr && xhr.readyState === 4) {\n try {\n // touching statusCode in some platforms throws\n // an exception\n xhr.__raven_xhr.status_code = xhr.status;\n } catch (e) {\n /* do nothing */\n }\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'xhr',\n data: xhr.__raven_xhr\n });\n }\n }\n\n var props = ['onload', 'onerror', 'onprogress'];\n for (var j = 0; j < props.length; j++) {\n wrapProp(props[j], xhr);\n }\n\n if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {\n fill(\n xhr,\n 'onreadystatechange',\n function(orig) {\n return self.wrap(\n {\n mechanism: {\n type: 'instrument',\n data: {\n function: 'onreadystatechange',\n handler: (orig && orig.name) || '<anonymous>'\n }\n }\n },\n orig,\n onreadystatechangeHandler\n );\n } /* intentionally don't track this instrumentation */\n );\n } else {\n // if onreadystatechange wasn't actually set by the page on this xhr, we\n // are free to set our own and capture the breadcrumb\n xhr.onreadystatechange = onreadystatechangeHandler;\n }\n\n return origSend.apply(this, arguments);\n };\n },\n wrappedBuiltIns\n );\n }\n\n if (autoBreadcrumbs.xhr && supportsFetch()) {\n fill(\n _window,\n 'fetch',\n function(origFetch) {\n return function() {\n // preserve arity\n // Make a copy of the arguments to prevent deoptimization\n // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; ++i) {\n args[i] = arguments[i];\n }\n\n var fetchInput = args[0];\n var method = 'GET';\n var url;\n\n if (typeof fetchInput === 'string') {\n url = fetchInput;\n } else if ('Request' in _window && fetchInput instanceof _window.Request) {\n url = fetchInput.url;\n if (fetchInput.method) {\n method = fetchInput.method;\n }\n } else {\n url = '' + fetchInput;\n }\n\n // if Sentry key appears in URL, don't capture, as it's our own request\n if (url.indexOf(self._globalKey) !== -1) {\n return origFetch.apply(this, args);\n }\n\n if (args[1] && args[1].method) {\n method = args[1].method;\n }\n\n var fetchData = {\n method: method,\n url: url,\n status_code: null\n };\n\n return origFetch\n .apply(this, args)\n .then(function(response) {\n fetchData.status_code = response.status;\n\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData\n });\n\n return response;\n })\n ['catch'](function(err) {\n // if there is an error performing the request\n self.captureBreadcrumb({\n type: 'http',\n category: 'fetch',\n data: fetchData,\n level: 'error'\n });\n\n throw err;\n });\n };\n },\n wrappedBuiltIns\n );\n }\n\n // Capture breadcrumbs from any click that is unhandled / bubbled up all the way\n // to the document. Do this before we instrument addEventListener.\n if (autoBreadcrumbs.dom && this._hasDocument) {\n if (_document.addEventListener) {\n _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);\n _document.addEventListener('keypress', self._keypressEventHandler(), false);\n } else if (_document.attachEvent) {\n // IE8 Compatibility\n _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));\n _document.attachEvent('onkeypress', self._keypressEventHandler());\n }\n }\n\n // record navigation (URL) changes\n // NOTE: in Chrome App environment, touching history.pushState, *even inside\n // a try/catch block*, will cause Chrome to output an error to console.error\n // borrowed from: https://github.com/angular/angular.js/pull/13945/files\n var chrome = _window.chrome;\n var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;\n var hasPushAndReplaceState =\n !isChromePackagedApp &&\n _window.history &&\n _window.history.pushState &&\n _window.history.replaceState;\n if (autoBreadcrumbs.location && hasPushAndReplaceState) {\n // TODO: remove onpopstate handler on uninstall()\n var oldOnPopState = _window.onpopstate;\n _window.onpopstate = function() {\n var currentHref = self._location.href;\n self._captureUrlChange(self._lastHref, currentHref);\n\n if (oldOnPopState) {\n return oldOnPopState.apply(this, arguments);\n }\n };\n\n var historyReplacementFunction = function(origHistFunction) {\n // note history.pushState.length is 0; intentionally not declaring\n // params to preserve 0 arity\n return function(/* state, title, url */) {\n var url = arguments.length > 2 ? arguments[2] : undefined;\n\n // url argument is optional\n if (url) {\n // coerce to string (this is what pushState does)\n self._captureUrlChange(self._lastHref, url + '');\n }\n\n return origHistFunction.apply(this, arguments);\n };\n };\n\n fill(_window.history, 'pushState', historyReplacementFunction, wrappedBuiltIns);\n fill(_window.history, 'replaceState', historyReplacementFunction, wrappedBuiltIns);\n }\n\n if (autoBreadcrumbs.console && 'console' in _window && console.log) {\n // console\n var consoleMethodCallback = function(msg, data) {\n self.captureBreadcrumb({\n message: msg,\n level: data.level,\n category: 'console'\n });\n };\n\n each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) {\n wrapConsoleMethod(console, level, consoleMethodCallback);\n });\n }\n },\n\n _restoreBuiltIns: function() {\n // restore any wrapped builtins\n var builtin;\n while (this._wrappedBuiltIns.length) {\n builtin = this._wrappedBuiltIns.shift();\n\n var obj = builtin[0],\n name = builtin[1],\n orig = builtin[2];\n\n obj[name] = orig;\n }\n },\n\n _restoreConsole: function() {\n // eslint-disable-next-line guard-for-in\n for (var method in this._originalConsoleMethods) {\n this._originalConsole[method] = this._originalConsoleMethods[method];\n }\n },\n\n _drainPlugins: function() {\n var self = this;\n\n // FIX ME TODO\n each(this._plugins, function(_, plugin) {\n var installer = plugin[0];\n var args = plugin[1];\n installer.apply(self, [self].concat(args));\n });\n },\n\n _parseDSN: function(str) {\n var m = dsnPattern.exec(str),\n dsn = {},\n i = 7;\n\n try {\n while (i--) dsn[dsnKeys[i]] = m[i] || '';\n } catch (e) {\n throw new RavenConfigError('Invalid DSN: ' + str);\n }\n\n if (dsn.pass && !this._globalOptions.allowSecretKey) {\n throw new RavenConfigError(\n 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key'\n );\n }\n\n return dsn;\n },\n\n _getGlobalServer: function(uri) {\n // assemble the endpoint from the uri pieces\n var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : '');\n\n if (uri.protocol) {\n globalServer = uri.protocol + ':' + globalServer;\n }\n return globalServer;\n },\n\n _handleOnErrorStackInfo: function(stackInfo, options) {\n options = options || {};\n options.mechanism = options.mechanism || {\n type: 'onerror',\n handled: false\n };\n\n // if we are intentionally ignoring errors via onerror, bail out\n if (!this._ignoreOnError) {\n this._handleStackInfo(stackInfo, options);\n }\n },\n\n _handleStackInfo: function(stackInfo, options) {\n var frames = this._prepareFrames(stackInfo, options);\n\n this._triggerEvent('handle', {\n stackInfo: stackInfo,\n options: options\n });\n\n this._processException(\n stackInfo.name,\n stackInfo.message,\n stackInfo.url,\n stackInfo.lineno,\n frames,\n options\n );\n },\n\n _prepareFrames: function(stackInfo, options) {\n var self = this;\n var frames = [];\n if (stackInfo.stack && stackInfo.stack.length) {\n each(stackInfo.stack, function(i, stack) {\n var frame = self._normalizeFrame(stack, stackInfo.url);\n if (frame) {\n frames.push(frame);\n }\n });\n\n // e.g. frames captured via captureMessage throw\n if (options && options.trimHeadFrames) {\n for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) {\n frames[j].in_app = false;\n }\n }\n }\n frames = frames.slice(0, this._globalOptions.stackTraceLimit);\n return frames;\n },\n\n _normalizeFrame: function(frame, stackInfoUrl) {\n // normalize the frames data\n var normalized = {\n filename: frame.url,\n lineno: frame.line,\n colno: frame.column,\n function: frame.func || '?'\n };\n\n // Case when we don't have any information about the error\n // E.g. throwing a string or raw object, instead of an `Error` in Firefox\n // Generating synthetic error doesn't add any value here\n //\n // We should probably somehow let a user know that they should fix their code\n if (!frame.url) {\n normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler\n }\n\n normalized.in_app = !// determine if an exception came from outside of our app\n // first we check the global includePaths list.\n (\n (!!this._globalOptions.includePaths.test &&\n !this._globalOptions.includePaths.test(normalized.filename)) ||\n // Now we check for fun, if the function name is Raven or TraceKit\n /(Raven|TraceKit)\\./.test(normalized['function']) ||\n // finally, we do a last ditch effort and check for raven.min.js\n /raven\\.(min\\.)?js$/.test(normalized.filename)\n );\n\n return normalized;\n },\n\n _processException: function(type, message, fileurl, lineno, frames, options) {\n var prefixedMessage = (type ? type + ': ' : '') + (message || '');\n if (\n !!this._globalOptions.ignoreErrors.test &&\n (this._globalOptions.ignoreErrors.test(message) ||\n this._globalOptions.ignoreErrors.test(prefixedMessage))\n ) {\n return;\n }\n\n var stacktrace;\n\n if (frames && frames.length) {\n fileurl = frames[0].filename || fileurl;\n // Sentry expects frames oldest to newest\n // and JS sends them as newest to oldest\n frames.reverse();\n stacktrace = {frames: frames};\n } else if (fileurl) {\n stacktrace = {\n frames: [\n {\n filename: fileurl,\n lineno: lineno,\n in_app: true\n }\n ]\n };\n }\n\n if (\n !!this._globalOptions.ignoreUrls.test &&\n this._globalOptions.ignoreUrls.test(fileurl)\n ) {\n return;\n }\n\n if (\n !!this._globalOptions.whitelistUrls.test &&\n !this._globalOptions.whitelistUrls.test(fileurl)\n ) {\n return;\n }\n\n var data = objectMerge(\n {\n // sentry.interfaces.Exception\n exception: {\n values: [\n {\n type: type,\n value: message,\n stacktrace: stacktrace\n }\n ]\n },\n transaction: fileurl\n },\n options\n );\n\n var ex = data.exception.values[0];\n if (ex.type == null && ex.value === '') {\n ex.value = 'Unrecoverable error caught';\n }\n\n // Move mechanism from options to exception interface\n // We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be\n // too much\n if (!data.exception.mechanism && data.mechanism) {\n data.exception.mechanism = data.mechanism;\n delete data.mechanism;\n }\n\n data.exception.mechanism = objectMerge(\n {\n type: 'generic',\n handled: true\n },\n data.exception.mechanism || {}\n );\n\n // Fire away!\n this._send(data);\n },\n\n _trimPacket: function(data) {\n // For now, we only want to truncate the two different messages\n // but this could/should be expanded to just trim everything\n var max = this._globalOptions.maxMessageLength;\n if (data.message) {\n data.message = truncate(data.message, max);\n }\n if (data.exception) {\n var exception = data.exception.values[0];\n exception.value = truncate(exception.value, max);\n }\n\n var request = data.request;\n if (request) {\n if (request.url) {\n request.url = truncate(request.url, this._globalOptions.maxUrlLength);\n }\n if (request.Referer) {\n request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);\n }\n }\n\n if (data.breadcrumbs && data.breadcrumbs.values)\n this._trimBreadcrumbs(data.breadcrumbs);\n\n return data;\n },\n\n /**\n * Truncate breadcrumb values (right now just URLs)\n */\n _trimBreadcrumbs: function(breadcrumbs) {\n // known breadcrumb properties with urls\n // TODO: also consider arbitrary prop values that start with (https?)?://\n var urlProps = ['to', 'from', 'url'],\n urlProp,\n crumb,\n data;\n\n for (var i = 0; i < breadcrumbs.values.length; ++i) {\n crumb = breadcrumbs.values[i];\n if (\n !crumb.hasOwnProperty('data') ||\n !isObject(crumb.data) ||\n objectFrozen(crumb.data)\n )\n continue;\n\n data = objectMerge({}, crumb.data);\n for (var j = 0; j < urlProps.length; ++j) {\n urlProp = urlProps[j];\n if (data.hasOwnProperty(urlProp) && data[urlProp]) {\n data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength);\n }\n }\n breadcrumbs.values[i].data = data;\n }\n },\n\n _getHttpData: function() {\n if (!this._hasNavigator && !this._hasDocument) return;\n var httpData = {};\n\n if (this._hasNavigator && _navigator.userAgent) {\n httpData.headers = {\n 'User-Agent': _navigator.userAgent\n };\n }\n\n // Check in `window` instead of `document`, as we may be in ServiceWorker environment\n if (_window.location && _window.location.href) {\n httpData.url = _window.location.href;\n }\n\n if (this._hasDocument && _document.referrer) {\n if (!httpData.headers) httpData.headers = {};\n httpData.headers.Referer = _document.referrer;\n }\n\n return httpData;\n },\n\n _resetBackoff: function() {\n this._backoffDuration = 0;\n this._backoffStart = null;\n },\n\n _shouldBackoff: function() {\n return this._backoffDuration && now() - this._backoffStart < this._backoffDuration;\n },\n\n /**\n * Returns true if the in-process data payload matches the signature\n * of the previously-sent data\n *\n * NOTE: This has to be done at this level because TraceKit can generate\n * data from window.onerror WITHOUT an exception object (IE8, IE9,\n * other old browsers). This can take the form of an \"exception\"\n * data object with a single frame (derived from the onerror args).\n */\n _isRepeatData: function(current) {\n var last = this._lastData;\n\n if (\n !last ||\n current.message !== last.message || // defined for captureMessage\n current.transaction !== last.transaction // defined for captureException/onerror\n )\n return false;\n\n // Stacktrace interface (i.e. from captureMessage)\n if (current.stacktrace || last.stacktrace) {\n return isSameStacktrace(current.stacktrace, last.stacktrace);\n } else if (current.exception || last.exception) {\n // Exception interface (i.e. from captureException/onerror)\n return isSameException(current.exception, last.exception);\n }\n\n return true;\n },\n\n _setBackoffState: function(request) {\n // If we are already in a backoff state, don't change anything\n if (this._shouldBackoff()) {\n return;\n }\n\n var status = request.status;\n\n // 400 - project_id doesn't exist or some other fatal\n // 401 - invalid/revoked dsn\n // 429 - too many requests\n if (!(status === 400 || status === 401 || status === 429)) return;\n\n var retry;\n try {\n // If Retry-After is not in Access-Control-Expose-Headers, most\n // browsers will throw an exception trying to access it\n if (supportsFetch()) {\n retry = request.headers.get('Retry-After');\n } else {\n retry = request.getResponseHeader('Retry-After');\n }\n\n // Retry-After is returned in seconds\n retry = parseInt(retry, 10) * 1000;\n } catch (e) {\n /* eslint no-empty:0 */\n }\n\n this._backoffDuration = retry\n ? // If Sentry server returned a Retry-After value, use it\n retry\n : // Otherwise, double the last backoff duration (starts at 1 sec)\n this._backoffDuration * 2 || 1000;\n\n this._backoffStart = now();\n },\n\n _send: function(data) {\n var globalOptions = this._globalOptions;\n\n var baseData = {\n project: this._globalProject,\n logger: globalOptions.logger,\n platform: 'javascript'\n },\n httpData = this._getHttpData();\n\n if (httpData) {\n baseData.request = httpData;\n }\n\n // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload\n if (data.trimHeadFrames) delete data.trimHeadFrames;\n\n data = objectMerge(baseData, data);\n\n // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge\n data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags);\n data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra);\n\n // Send along our own collected metadata with extra\n data.extra['session:duration'] = now() - this._startTime;\n\n if (this._breadcrumbs && this._breadcrumbs.length > 0) {\n // intentionally make shallow copy so that additions\n // to breadcrumbs aren't accidentally sent in this request\n data.breadcrumbs = {\n values: [].slice.call(this._breadcrumbs, 0)\n };\n }\n\n if (this._globalContext.user) {\n // sentry.interfaces.User\n data.user = this._globalContext.user;\n }\n\n // Include the environment if it's defined in globalOptions\n if (globalOptions.environment) data.environment = globalOptions.environment;\n\n // Include the release if it's defined in globalOptions\n if (globalOptions.release) data.release = globalOptions.release;\n\n // Include server_name if it's defined in globalOptions\n if (globalOptions.serverName) data.server_name = globalOptions.serverName;\n\n data = this._sanitizeData(data);\n\n // Cleanup empty properties before sending them to the server\n Object.keys(data).forEach(function(key) {\n if (data[key] == null || data[key] === '' || isEmptyObject(data[key])) {\n delete data[key];\n }\n });\n\n if (isFunction(globalOptions.dataCallback)) {\n data = globalOptions.dataCallback(data) || data;\n }\n\n // Why??????????\n if (!data || isEmptyObject(data)) {\n return;\n }\n\n // Check if the request should be filtered or not\n if (\n isFunction(globalOptions.shouldSendCallback) &&\n !globalOptions.shouldSendCallback(data)\n ) {\n return;\n }\n\n // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests),\n // so drop requests until \"cool-off\" period has elapsed.\n if (this._shouldBackoff()) {\n this._logDebug('warn', 'Raven dropped error due to backoff: ', data);\n return;\n }\n\n if (typeof globalOptions.sampleRate === 'number') {\n if (Math.random() < globalOptions.sampleRate) {\n this._sendProcessedPayload(data);\n }\n } else {\n this._sendProcessedPayload(data);\n }\n },\n\n _sanitizeData: function(data) {\n return sanitize(data, this._globalOptions.sanitizeKeys);\n },\n\n _getUuid: function() {\n return uuid4();\n },\n\n _sendProcessedPayload: function(data, callback) {\n var self = this;\n var globalOptions = this._globalOptions;\n\n if (!this.isSetup()) return;\n\n // Try and clean up the packet before sending by truncating long values\n data = this._trimPacket(data);\n\n // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,\n // but this would require copying an un-truncated copy of the data packet, which can be\n // arbitrarily deep (extra_data) -- could be worthwhile? will revisit\n if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) {\n this._logDebug('warn', 'Raven dropped repeat event: ', data);\n return;\n }\n\n // Send along an event_id if not explicitly passed.\n // This event_id can be used to reference the error within Sentry itself.\n // Set lastEventId after we know the error should actually be sent\n this._lastEventId = data.event_id || (data.event_id = this._getUuid());\n\n // Store outbound payload after trim\n this._lastData = data;\n\n this._logDebug('debug', 'Raven about to send:', data);\n\n var auth = {\n sentry_version: '7',\n sentry_client: 'raven-js/' + this.VERSION,\n sentry_key: this._globalKey\n };\n\n if (this._globalSecret) {\n auth.sentry_secret = this._globalSecret;\n }\n\n var exception = data.exception && data.exception.values[0];\n\n // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy\n if (\n this._globalOptions.autoBreadcrumbs &&\n this._globalOptions.autoBreadcrumbs.sentry\n ) {\n this.captureBreadcrumb({\n category: 'sentry',\n message: exception\n ? (exception.type ? exception.type + ': ' : '') + exception.value\n : data.message,\n event_id: data.event_id,\n level: data.level || 'error' // presume error unless specified\n });\n }\n\n var url = this._globalEndpoint;\n (globalOptions.transport || this._makeRequest).call(this, {\n url: url,\n auth: auth,\n data: data,\n options: globalOptions,\n onSuccess: function success() {\n self._resetBackoff();\n\n self._triggerEvent('success', {\n data: data,\n src: url\n });\n callback && callback();\n },\n onError: function failure(error) {\n self._logDebug('error', 'Raven transport failed to send: ', error);\n\n if (error.request) {\n self._setBackoffState(error.request);\n }\n\n self._triggerEvent('failure', {\n data: data,\n src: url\n });\n error = error || new Error('Raven send failed (no additional details provided)');\n callback && callback(error);\n }\n });\n },\n\n _makeRequest: function(opts) {\n // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests\n var url = opts.url + '?' + urlencode(opts.auth);\n\n var evaluatedHeaders = null;\n var evaluatedFetchParameters = {};\n\n if (opts.options.headers) {\n evaluatedHeaders = this._evaluateHash(opts.options.headers);\n }\n\n if (opts.options.fetchParameters) {\n evaluatedFetchParameters = this._evaluateHash(opts.options.fetchParameters);\n }\n\n if (supportsFetch()) {\n evaluatedFetchParameters.body = stringify(opts.data);\n\n var defaultFetchOptions = objectMerge({}, this._fetchDefaults);\n var fetchOptions = objectMerge(defaultFetchOptions, evaluatedFetchParameters);\n\n if (evaluatedHeaders) {\n fetchOptions.headers = evaluatedHeaders;\n }\n\n return _window\n .fetch(url, fetchOptions)\n .then(function(response) {\n if (response.ok) {\n opts.onSuccess && opts.onSuccess();\n } else {\n var error = new Error('Sentry error code: ' + response.status);\n // It's called request only to keep compatibility with XHR interface\n // and not add more redundant checks in setBackoffState method\n error.request = response;\n opts.onError && opts.onError(error);\n }\n })\n ['catch'](function() {\n opts.onError &&\n opts.onError(new Error('Sentry error code: network unavailable'));\n });\n }\n\n var request = _window.XMLHttpRequest && new _window.XMLHttpRequest();\n if (!request) return;\n\n // if browser doesn't support CORS (e.g. IE7), we are out of luck\n var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined';\n\n if (!hasCORS) return;\n\n if ('withCredentials' in request) {\n request.onreadystatechange = function() {\n if (request.readyState !== 4) {\n return;\n } else if (request.status === 200) {\n opts.onSuccess && opts.onSuccess();\n } else if (opts.onError) {\n var err = new Error('Sentry error code: ' + request.status);\n err.request = request;\n opts.onError(err);\n }\n };\n } else {\n request = new XDomainRequest();\n // xdomainrequest cannot go http -> https (or vice versa),\n // so always use protocol relative\n url = url.replace(/^https?:/, '');\n\n // onreadystatechange not supported by XDomainRequest\n if (opts.onSuccess) {\n request.onload = opts.onSuccess;\n }\n if (opts.onError) {\n request.onerror = function() {\n var err = new Error('Sentry error code: XDomainRequest');\n err.request = request;\n opts.onError(err);\n };\n }\n }\n\n request.open('POST', url);\n\n if (evaluatedHeaders) {\n each(evaluatedHeaders, function(key, value) {\n request.setRequestHeader(key, value);\n });\n }\n\n request.send(stringify(opts.data));\n },\n\n _evaluateHash: function(hash) {\n var evaluated = {};\n\n for (var key in hash) {\n if (hash.hasOwnProperty(key)) {\n var value = hash[key];\n evaluated[key] = typeof value === 'function' ? value() : value;\n }\n }\n\n return evaluated;\n },\n\n _logDebug: function(level) {\n // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change\n if (\n this._originalConsoleMethods[level] &&\n (this.debug || this._globalOptions.debug)\n ) {\n // In IE<10 console methods do not have their own 'apply' method\n Function.prototype.apply.call(\n this._originalConsoleMethods[level],\n this._originalConsole,\n [].slice.call(arguments, 1)\n );\n }\n },\n\n _mergeContext: function(key, context) {\n if (isUndefined(context)) {\n delete this._globalContext[key];\n } else {\n this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context);\n }\n }\n};\n\n// Deprecations\nRaven.prototype.setUser = Raven.prototype.setUserContext;\nRaven.prototype.setReleaseContext = Raven.prototype.setRelease;\n\nmodule.exports = Raven;\n","/**\n * Enforces a single instance of the Raven client, and the\n * main entry point for Raven. If you are a consumer of the\n * Raven library, you SHOULD load this file (vs raven.js).\n **/\n\nvar RavenConstructor = require('./raven');\n\n// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)\nvar _window =\n typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\nvar _Raven = _window.Raven;\n\nvar Raven = new RavenConstructor();\n\n/*\n * Allow multiple versions of Raven to be installed.\n * Strip Raven from the global context and returns the instance.\n *\n * @return {Raven}\n */\nRaven.noConflict = function() {\n _window.Raven = _Raven;\n return Raven;\n};\n\nRaven.afterLoad();\n\nmodule.exports = Raven;\n\n/**\n * DISCLAIMER:\n *\n * Expose `Client` constructor for cases where user want to track multiple \"sub-applications\" in one larger app.\n * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it.\n * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug.\n *\n * It's called `Client' to be in-line with Raven Node implementation.\n *\n * HOWTO:\n *\n * import Raven from 'raven-js';\n *\n * const someAppReporter = new Raven.Client();\n * const someOtherAppReporter = new Raven.Client();\n *\n * someAppReporter.config('__DSN__', {\n * ...config goes here\n * });\n *\n * someOtherAppReporter.config('__OTHER_DSN__', {\n * ...config goes here\n * });\n *\n * someAppReporter.captureMessage(...);\n * someAppReporter.captureException(...);\n * someAppReporter.captureBreadcrumb(...);\n *\n * someOtherAppReporter.captureMessage(...);\n * someOtherAppReporter.captureException(...);\n * someOtherAppReporter.captureBreadcrumb(...);\n *\n * It should \"just work\".\n */\nmodule.exports.Client = RavenConstructor;\n","// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isWeakMap = input => instanceOf(input, WeakMap);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isTextNode = input => getConstructor(input) === Text;\nconst isEvent = input => instanceOf(input, Event);\nconst isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\nconst isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\n\nconst isEmpty = input =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (e) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: this,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise(resolve =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport { toggleListener } from './events';\nimport is from './is';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) {\n return;\n }\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) {\n return;\n }\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) {\n return;\n }\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) {\n return;\n }\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.object(existing) && is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Trap focus inside container\nexport function trapFocus(element = null, toggle = false) {\n if (!is.element(element)) {\n return;\n }\n\n const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = document.activeElement;\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n if (!is.element(element)) {\n return;\n }\n\n // Set regular focus\n element.focus({ preventScroll: true });\n\n // If we want to mimic keyboard focus via tab\n if (tabFocus) {\n toggleClass(element, this.config.classNames.tabFocus);\n }\n}\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport { toggleHidden } from './elements';\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element) {\n setTimeout(() => {\n try {\n toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n toggleHidden(element, false);\n } catch (e) {\n // Do nothing\n }\n }, 0);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isEdge: window.navigator.userAgent.includes('Edge'),\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (e) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map(source => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(source => source.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n // Get first match for requested size\n const source = sources.find(source => Number(source.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n player.play();\n }\n });\n\n // Load new source\n player.media.load();\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport function replaceAll(input = '', find = '', replace = '') {\n return input.replace(\n new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'),\n replace.toString(),\n );\n}\n\n// Convert to title case\nexport function toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n}\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([key, value]) => {\n string = replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(result => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = value => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = value => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`,\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n\n const attributes = Object.assign({}, attr, {\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),\n });\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = Object.assign({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-label': i18n.get(type, this.config),\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on(\n menuItem,\n 'keydown keyup',\n event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![32, 38, 39, 40].includes(event.which)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [32, 39].includes(event.which)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.which !== 32) {\n if (event.which === 40 || (isRadioButton && event.which === 39)) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on(menuItem, 'keyup', event => {\n if (event.which !== 13) {\n return;\n }\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behaviour\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(checked) {\n // Ensure exclusivity\n if (checked) {\n Array.from(menuItem.parentNode.children)\n .filter(node => matches(node, '[role=\"menuitemradio\"]'))\n .forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n event => {\n if (is.keyboardEvent(event) && event.which !== 32) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const value = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Set the speed options\n if (is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, tabFocus = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, tabFocus);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.which === 27) {\n show = false;\n } else if (is.event(input)) {\n const isMenuItem = popup.contains(input.target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', tabFocus = false) {\n const target = document.getElementById(`plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, tabFocus);\n },\n\n // Set the download link\n setDownloadLink() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set download link\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Volume controls\n if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {\n const volume = createElement('div', {\n class: 'plyr__volume',\n });\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n volume.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n controls.createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n\n this.elements.volume = volume;\n }\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n const control = createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n control.appendChild(\n controls.createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on(menuItem, 'click', () => {\n controls.showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on(\n pane,\n 'keydown',\n event => {\n // We only care about <-\n if (event.which !== 37) {\n return;\n }\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n controls.showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on(backButton, 'click', () => {\n controls.showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n control.appendChild(popup);\n container.appendChild(control);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = control;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Download button\n if (this.config.controls.includes('download')) {\n const attributes = {\n element: 'a',\n href: this.download,\n target: '_blank',\n };\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(controls.createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n // Set available quality levels\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n } else if (is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n Object.defineProperty(button, 'pressed', {\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button)\n .filter(Boolean)\n .forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {string} input - the URL to be parsed\n * @param {boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (e) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n track.mode = 'hidden';\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n\n // Update available languages in list\n if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter(track => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(track => track.language === language);\n return !track; // Break iteration if there is a match\n });\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || [])\n .map(cue => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api:\n 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n },\n\n // YouTube plugin\n youtube: {\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { hasClass, toggleClass, trapFocus } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Trigger an event\n triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n\n if (!hasProperty) {\n viewport.content += `,${property}`;\n }\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter(part => part.trim() !== property)\n .join(',');\n }\n\n // Force a repaint as sometimes Safari doesn't want to fill the screen\n setTimeout(() => repaint(this.target), 100);\n }\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n onChange.call(this);\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get usingNative() {\n return Fullscreen.native && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n let mode;\n\n if (this.forceFallback) {\n mode = 'Fallback (forced)';\n } else if (Fullscreen.native) {\n mode = 'Native';\n } else {\n mode = 'Fallback';\n }\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitEnterFullscreen();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/loadImage';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('poster', poster);\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch(err => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw err;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n ui.togglePoster.call(this, true);\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n target.pressed = this.playing;\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls } = this.elements;\n\n if (controls && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now());\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport is from './is';\n\n/* function reduceAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n} */\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n let ratio = input;\n\n if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) {\n ({ ratio } = this.embed);\n }\n\n if (!is.string(ratio)) {\n ({ ratio } = this.config);\n }\n\n const [x, y] = ratio.split(':').map(Number);\n const padding = (100 / x) * y;\n\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n\n return { padding, ratio };\n}\n\nexport default { setAspectRatio };\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { setAspectRatio } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.setTabFocus = this.setTabFocus.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keycodes should we prevent default\n const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n player.forward();\n break;\n\n case 37:\n // Arrow back\n player.rewind();\n break;\n\n case 70:\n // F key\n player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n player.loop = !player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n }\n\n setTabFocus(event) {\n const { player } = this;\n const { elements } = player;\n\n clearTimeout(this.focusTimer);\n\n // Ignore any key other than tab\n if (event.type === 'keydown' && event.which !== 9) {\n return;\n }\n\n // Store reference to event timeStamp\n if (event.type === 'keydown') {\n this.lastKeyDown = event.timeStamp;\n }\n\n // Remove current classes\n const removeCurrent = () => {\n const className = player.config.classNames.tabFocus;\n const current = getElements.call(player, `.${className}`);\n toggleClass(current, className, false);\n };\n\n // Determine if a key was pressed to trigger this event\n const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n // Ignore focus events if a key was pressed prior\n if (event.type === 'focus' && !wasKeyDown) {\n return;\n }\n\n // Remove all current\n removeCurrent();\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n this.focusTimer = setTimeout(() => {\n const focused = document.activeElement;\n\n // Ignore if current focus element isn't inside the player\n if (!elements.container.contains(focused)) {\n return;\n }\n\n toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n }, 10);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n\n // Tab focus detection\n toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);\n }\n\n // Container listeners\n container() {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n event => {\n const { controls } = elements;\n\n // Remove button states for fullscreen\n if (controls && event.type === 'enterfullscreen') {\n controls.pressed = false;\n controls.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Force edge to repaint on exit fullscreen\n // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen\n /* if (browser.isEdge) {\n on.call(player, elements.container, 'exitfullscreen', () => {\n setTimeout(() => repaint(elements.container), 100);\n });\n } */\n\n // Set a gutter for Vimeo\n const setGutter = (ratio, padding, toggle) => {\n if (!player.isVimeo) {\n return;\n }\n\n const target = player.elements.wrapper.firstChild;\n const [, height] = ratio.split(':').map(Number);\n const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number);\n\n target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null;\n target.style.margin = toggle ? '0 auto' : null;\n };\n\n // Resize on fullscreen change\n const setPlayerSize = measure => {\n // If we don't need to measure the viewport\n if (!measure) {\n return setAspectRatio.call(player);\n }\n\n const rect = elements.container.getBoundingClientRect();\n const { width, height } = rect;\n\n return setAspectRatio.call(player, `${width}:${height}`);\n };\n\n const resized = () => {\n window.clearTimeout(timers.resized);\n timers.resized = window.setTimeout(setPlayerSize, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const { target, usingNative } = player.fullscreen;\n\n // Ignore for iOS native\n if (!player.isEmbed || target !== elements.container) {\n return;\n }\n\n const isEnter = event.type === 'enterfullscreen';\n\n // Set the player size when entering fullscreen to viewport size\n const { padding, ratio } = setPlayerSize(isEnter);\n\n // Set Vimeo gutter\n setGutter(ratio, padding, isEnter);\n\n // If not using native fullscreen, we need to check for resizes of viewport\n if (!usingNative) {\n if (isEnter) {\n on.call(player, window, 'resize', resized);\n } else {\n off.call(player, window, 'resize', resized);\n }\n }\n });\n }\n\n // Listen for media events\n media() {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event =>\n controls.durationUpdate.call(player, event),\n );\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n on.call(player, player.media, 'canplay loadeddata', () => {\n toggleHidden(elements.volume, !player.hasAudio);\n toggleHidden(elements.buttons.mute, !player.hasAudio);\n });\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n on.call(player, player.media, 'playing', () => {\n if (!player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (player.ads.enabled && !player.ads.initialized) {\n // Wait for manager response\n player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play());\n }\n });\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, player.play, 'play');\n } else {\n this.proxy(event, player.togglePlay, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadLink.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, event => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n }\n\n // Run default and custom handlers\n proxy(event, defaultHandler, customHandlerKey) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n }\n\n // Trigger custom and default handlers\n bind(element, type, defaultHandler, customHandlerKey, passive = true) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n event => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n }\n\n // Listen for control events\n controls() {\n const { player } = this;\n const { elements } = player;\n\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', player.togglePlay, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward');\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n\n controls.toggleMenu.call(player, event);\n });\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n event => {\n const code = event.which;\n\n // We only care about space and return\n if (![13, 32].includes(code)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (code === 13) {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.which === 27) {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const code = event.keyCode ? event.keyCode : event.which;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n player.play();\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n event => {\n const seek = event.currentTarget;\n\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n event => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, elements, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));\n\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n}\n\nexport default Listeners;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, stripHTML } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n setAspectRatio.call(this);\n\n // Load the API if not already\n if (!is.object(window.Vimeo)) {\n loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams(\n extend(\n {},\n {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n },\n config,\n ),\n );\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = parseId(source);\n\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Get poster, if already set\n const { poster } = player;\n\n // Inject the package\n const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n\n // Get poster image\n fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set and show poster\n ui.setPoster.call(player, url.href).catch(() => {});\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n controls.setDownloadLink.call(player);\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = `${width}:${height}`;\n setAspectRatio.call(this, player.embed.ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/loadImage';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n setAspectRatio.call(this);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (is.string(key) && !is.empty(key)) {\n const url = format(this.config.urls.youtube.api, videoId, key);\n\n fetch(url)\n .then(result => {\n if (is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n\n // Get poster, if already set\n const { poster } = player;\n\n // Replace media element\n const container = createElement('div', { id, poster });\n player.media = replaceElement(container, player.media);\n\n // Id to poster wrapper\n const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src))\n .then(posterSrc => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!posterSrc.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n\n const config = player.config.youtube;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined,\n playerVars: extend(\n {},\n {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n hl: player.config.hl, // iframe interface language\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occured';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr.io demo\n// This code is purely for the https://plyr.io website\n// Please see readme.md in the root or github.com/sampotts/plyr\n// ==========================================================================\n\nimport Raven from 'raven-js';\nimport Plyr from '../../../src/js/plyr';\n\n(() => {\n const { host } = window.location;\n const env = {\n prod: host === 'plyr.io',\n dev: host === 'dev.plyr.io',\n };\n\n document.addEventListener('DOMContentLoaded', () => {\n Raven.context(() => {\n const selector = '#player';\n const container = document.getElementById('container');\n\n if (window.shr) {\n window.shr.setup({\n count: {\n classname: 'button__count',\n },\n });\n }\n\n // Setup tab focus\n const tabClassName = 'tab-focus';\n\n // Remove class on blur\n document.addEventListener('focusout', event => {\n if (!event.target.classList || container.contains(event.target)) {\n return;\n }\n\n event.target.classList.remove(tabClassName);\n });\n\n // Add classname to tabbed elements\n document.addEventListener('keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n const focused = document.activeElement;\n\n if (!focused || !focused.classList || container.contains(focused)) {\n return;\n }\n\n focused.classList.add(tabClassName);\n }, 10);\n });\n\n // Setup the player\n const player = new Plyr(selector, {\n debug: true,\n title: 'View From A Blue Moon',\n iconUrl: 'dist/plyr.svg',\n keyboard: {\n global: true,\n },\n tooltips: {\n controls: true,\n },\n captions: {\n active: true,\n },\n keys: {\n google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c',\n },\n ads: {\n enabled: env.prod || env.dev,\n publisherId: '918848828995742',\n },\n previewThumbnails: {\n enabled: true,\n src: [\n 'https://cdn.plyr.io/static/demo/thumbs/100p.vtt',\n 'https://cdn.plyr.io/static/demo/thumbs/240p.vtt',\n ],\n },\n });\n\n // Expose for tinkering in the console\n window.player = player;\n\n // Setup type toggle\n const buttons = document.querySelectorAll('[data-source]');\n const types = {\n video: 'video',\n audio: 'audio',\n youtube: 'youtube',\n vimeo: 'vimeo',\n };\n let currentType = window.location.hash.replace('#', '');\n const historySupport = window.history && window.history.pushState;\n\n // Toggle class on an element\n function toggleClass(element, className, state) {\n if (element) {\n element.classList[state ? 'add' : 'remove'](className);\n }\n }\n\n // Set a new source\n function newSource(type, init) {\n // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video\n if (\n !(type in types) ||\n (!init && type === currentType) ||\n (!currentType.length && type === types.video)\n ) {\n return;\n }\n\n switch (type) {\n case types.video:\n player.source = {\n type: 'video',\n title: 'View From A Blue Moon',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',\n type: 'video/mp4',\n size: 576,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4',\n type: 'video/mp4',\n size: 720,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4',\n type: 'video/mp4',\n size: 1080,\n },\n {\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4',\n type: 'video/mp4',\n size: 1440,\n },\n ],\n poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg',\n tracks: [\n {\n kind: 'captions',\n label: 'English',\n srclang: 'en',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n default: true,\n },\n {\n kind: 'captions',\n label: 'French',\n srclang: 'fr',\n src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',\n },\n ],\n };\n\n break;\n\n case types.audio:\n player.source = {\n type: 'audio',\n title: 'Kishi Bashi – “It All Began With A Burst”',\n sources: [\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',\n type: 'audio/mp3',\n },\n {\n src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',\n type: 'audio/ogg',\n },\n ],\n };\n\n break;\n\n case types.youtube:\n player.source = {\n type: 'video',\n sources: [\n {\n src: 'https://youtube.com/watch?v=bTqVqk7FSmY',\n provider: 'youtube',\n },\n ],\n };\n\n break;\n\n case types.vimeo:\n player.source = {\n type: 'video',\n sources: [\n {\n src: 'https://vimeo.com/76979871',\n provider: 'vimeo',\n },\n ],\n };\n\n break;\n\n default:\n break;\n }\n\n // Set the current type for next time\n currentType = type;\n\n // Remove active classes\n Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));\n\n // Set active on parent\n toggleClass(document.querySelector(`[data-source=\"${type}\"]`), 'active', true);\n\n // Show cite\n Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {\n cite.setAttribute('hidden', '');\n });\n document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden');\n }\n\n // Bind to each button\n Array.from(buttons).forEach(button => {\n button.addEventListener('click', () => {\n const type = button.getAttribute('data-source');\n\n newSource(type);\n\n if (historySupport) {\n window.history.pushState({ type }, '', `#${type}`);\n }\n });\n });\n\n // List for backwards/forwards\n window.addEventListener('popstate', event => {\n if (event.state && 'type' in event.state) {\n newSource(event.state.type);\n }\n });\n\n // On load\n if (historySupport) {\n const video = !currentType.length;\n\n // If there's no current type set, assume video\n if (video) {\n currentType = types.video;\n }\n\n // Replace current history state\n if (currentType in types) {\n window.history.replaceState(\n {\n type: currentType,\n },\n '',\n video ? '' : `#${currentType}`,\n );\n }\n\n // If it's not video, load the source\n if (currentType !== types.video) {\n newSource(currentType, true);\n }\n }\n });\n });\n\n // Raven / Sentry\n // For demo site (https://plyr.io) only\n if (env.prod) {\n Raven.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install();\n }\n})();\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.extend.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n event => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n triggerEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1]) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6]) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load() {\n // Togglethe regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) {\n return;\n }\n\n this.getThumbnails().then(() => {\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n this.loaded = true;\n });\n }\n\n // Download VTT files and parse them\n getThumbnails() {\n return new Promise(resolve => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n\n Promise.all(promises).then(() => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n });\n });\n }\n\n // Process individual VTT file\n getThumbnail(url) {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n if (!thumbnail.frames[0].text.startsWith('/')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n }\n\n startMove(event) {\n if (!this.loaded) {\n return;\n }\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n return;\n }\n\n // Wait until media has a duration\n if (!this.player.media.duration) {\n return;\n }\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n\n endMove() {\n this.toggleThumbContainer(false, true);\n }\n\n startScrubbing(event) {\n // Only act on left mouse button (0), or touch device (event.button is false)\n if (event.button === false || event.button === 0) {\n this.mouseDown = true;\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n }\n\n finishScrubbing() {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n }\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners() {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n }\n\n /**\n * Create HTML elements for image containers\n */\n render() {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.container.appendChild(timeContainer);\n\n // Inject the whole thumb\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n }\n\n showImageAtCurrentTime() {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.toggleThumbContainer(true);\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n this.toggleThumbContainer(hasThumb);\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumbnum or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n }\n\n // Show the image that's currently specified in this.showingThumb\n loadImage(qualityIndex = 0) {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () =>\n this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n }\n\n showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n }\n\n // Remove all preview images that aren't the designated current image\n removeOldImages(currentImage) {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n image.dataset.deleting = true;\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n }\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby(thumbNum, forward = true) {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename))\n this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n }\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n }\n\n get currentImageContainer() {\n if (this.mouseDown) {\n return this.elements.scrubbing.container;\n }\n\n return this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n if (this.mouseDown) {\n return this.currentScrubbingImageElement;\n }\n\n return this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer(toggle = false, clearShowing = false) {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n toggleScrubbingContainer(toggle = false) {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n determineContainerAutoSizing() {\n if (this.elements.thumb.imageContainer.clientHeight > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n }\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos() {\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n }\n\n this.setThumbContainerPos();\n }\n\n setThumbContainerPos() {\n const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n const plyrRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const minVal = plyrRect.left - seekbarRect.left + 10;\n const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n if (previewPos < minVal) {\n previewPos = minVal;\n }\n\n if (previewPos > maxVal) {\n previewPos = maxVal;\n }\n\n container.style.left = `${previewPos}px`;\n }\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize() {\n this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`;\n // Can't use media.clientHeight - html5 video goes big and does black bars above and below\n this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`;\n }\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset(previewImage, frame) {\n if (!this.usingSprites) {\n return;\n }\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;\n previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;\n previewImage.style.left = `-${frame.x * multiplier}px`;\n previewImage.style.top = `-${frame.y * multiplier}px`;\n }\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Reload thumbnails\n if (this.previewThumbnails) {\n this.previewThumbnails.load();\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.4.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/previewThumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { cloneDeep, extend } from './utils/objects';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div', { tabindex: 0 });\n wrap(this.media, this.elements.container);\n }\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n this.increaseVolume(-step);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {number} - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} [toggle] - Whether to show the controls\n */\n toggleControls(toggle) {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n on.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Add event listeners once\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n once(event, callback) {\n once.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/demo/dist/error.css b/demo/dist/error.css index 818fce92..4898e3e7 100644 --- a/demo/dist/error.css +++ b/demo/dist/error.css @@ -1 +1 @@ -@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:300;src:url(https://cdn.plyr.io/static/fonts/gordita-light.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-light.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:400;src:url(https://cdn.plyr.io/static/fonts/gordita-regular.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:500;src:url(https://cdn.plyr.io/static/fonts/gordita-medium.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-medium.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:600;src:url(https://cdn.plyr.io/static/fonts/gordita-bold.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:900;src:url(https://cdn.plyr.io/static/fonts/gordita-black.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-black.woff) format("woff")}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a,button.faux-link{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}*,::after,::before{box-sizing:border-box}.error body,html.error{height:100%}html.error{background:linear-gradient(to left top,#4dc1ff,#0074b3);background-attachment:fixed}.error body{align-items:center;display:flex;width:100%}.error main{padding:20px;text-align:center;width:100%}.error main p{font-size:18px;font-size:1.125rem}html{font-size:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:15px;font-size:.9375rem;color:#fff;font-family:Gordita,Avenir,"Helvetica Neue",sans-serif;font-weight:500;line-height:1.75;text-shadow:0 1px 1px rgba(0,0,0,.15)}button,input,select,textarea{font:inherit}p,small{margin:0 0 20px}small{font-size:13px;font-size:.8125rem;display:block}h1{font-size:64px;font-size:4rem;font-weight:600;letter-spacing:-.025em;line-height:1.2;margin:0 0 20px}.button,.button__count{align-items:center;background:#fff;border:0;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.1);color:#55646b;display:inline-flex;padding:15px;position:relative;text-shadow:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}.button{font-weight:600;padding-left:20px;padding-right:20px;transition:all .2s ease}.button:focus,.button:hover{color:#343f4a}.button:focus::after,.button:hover::after{display:none}.button:hover{box-shadow:0 2px 2px rgba(0,0,0,.1);transform:translateY(-1px)}.button:focus{outline:0}.button.tab-focus{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}.button:active{transform:translateY(1px)}.button--with-count{display:inline-flex}.button--with-count .button .icon{flex-shrink:0}.button__count{animation:fadein .2s ease;margin-left:10px}.button__count::before{border:5px solid transparent;border-left-width:0;border-right-color:#fff;content:'';height:0;position:absolute;right:100%;top:50%;transform:translateY(-50%);width:0}button.faux-link{background:0 0;border:0;border-radius:0;cursor:pointer;font:inherit;line-height:1.75;margin:0;padding:0;position:relative;text-align:inherit;text-shadow:inherit;-moz-user-select:text;vertical-align:baseline;width:auto}a,button.faux-link{border-bottom:1px dotted currentColor;color:#fff;font-weight:600;position:relative;text-decoration:none;transition:all .2s ease}a::after,button.faux-link::after{background:currentColor;content:'';height:1px;left:50%;position:absolute;top:100%;transform:translateX(-50%);transition:width .2s ease;width:0}a:focus,a:hover,button.faux-link:focus,button.faux-link:hover{border-bottom-color:transparent;outline:0}a:focus::after,a:hover::after,button.faux-link:focus::after,button.faux-link:hover::after{width:100%}a.tab-focus,button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}a.no-border::after,button.no-border.faux-link::after{display:none}
\ No newline at end of file +@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:300;src:url(https://cdn.plyr.io/static/fonts/gordita-light.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-light.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:400;src:url(https://cdn.plyr.io/static/fonts/gordita-regular.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:500;src:url(https://cdn.plyr.io/static/fonts/gordita-medium.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-medium.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:600;src:url(https://cdn.plyr.io/static/fonts/gordita-bold.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Gordita;font-style:normal;font-weight:900;src:url(https://cdn.plyr.io/static/fonts/gordita-black.woff2) format("woff2"),url(https://cdn.plyr.io/static/fonts/gordita-black.woff) format("woff")}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a,button.faux-link{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}*,::after,::before{box-sizing:border-box}.error body,html.error{height:100%}html.error{background:linear-gradient(to left top,#4dc1ff,#0074b3);background-attachment:fixed}.error body{align-items:center;display:flex;width:100%}.error main{padding:20px;text-align:center;width:100%}.error main p{font-size:18px;font-size:1.125rem}html{font-size:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:15px;font-size:.9375rem;color:#fff;font-family:Gordita,Avenir,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-weight:500;line-height:1.75;text-shadow:0 1px 1px rgba(0,0,0,.15)}button,input,select,textarea{font:inherit}p,small{margin:0 0 20px}small{font-size:13px;font-size:.8125rem;display:block}h1{font-size:64px;font-size:4rem;font-weight:600;letter-spacing:-.025em;line-height:1.2;margin:0 0 20px}.button,.button__count{align-items:center;background:#fff;border:0;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.1);color:#55646b;display:inline-flex;padding:15px;position:relative;text-shadow:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}.button{font-weight:600;padding-left:20px;padding-right:20px;transition:all .2s ease}.button:focus,.button:hover{color:#343f4a}.button:focus::after,.button:hover::after{display:none}.button:hover{box-shadow:0 2px 2px rgba(0,0,0,.1);transform:translateY(-1px)}.button:focus{outline:0}.button.tab-focus{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}.button:active{transform:translateY(1px)}.button--with-count{display:inline-flex}.button--with-count .button .icon{flex-shrink:0}.button__count{animation:fadein .2s ease;margin-left:10px}.button__count::before{border:5px solid transparent;border-left-width:0;border-right-color:#fff;content:'';height:0;position:absolute;right:100%;top:50%;transform:translateY(-50%);width:0}button.faux-link{background:0 0;border:0;border-radius:0;cursor:pointer;font:inherit;line-height:1.75;margin:0;padding:0;position:relative;text-align:inherit;text-shadow:inherit;-moz-user-select:text;vertical-align:baseline;width:auto}a,button.faux-link{border-bottom:1px dotted currentColor;color:#fff;font-weight:600;position:relative;text-decoration:none;transition:all .2s ease}a::after,button.faux-link::after{background:currentColor;content:'';height:1px;left:50%;position:absolute;top:100%;transform:translateX(-50%);transition:width .2s ease;width:0}a:focus,a:hover,button.faux-link:focus,button.faux-link:hover{border-bottom-color:transparent;outline:0}a:focus::after,a:hover::after,button.faux-link:focus::after,button.faux-link:hover::after{width:100%}a.tab-focus,button.tab-focus.faux-link{box-shadow:0 0 0 3px rgba(255,255,255,.35);outline:0}a.no-border::after,button.no-border.faux-link::after{display:none}
\ No newline at end of file diff --git a/demo/dist/plyr.svg b/demo/dist/plyr.svg new file mode 100644 index 00000000..be7c210d --- /dev/null +++ b/demo/dist/plyr.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol id="plyr-airplay"><path d="M16 1H2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3v-2H3V3h12v8h-2v2h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/><path d="M4 17h10l-5-6z"/></symbol><symbol id="plyr-captions-off"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd" fill-opacity=".5"/></symbol><symbol id="plyr-captions-on"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd"/></symbol><symbol id="plyr-download"><path d="M9 13c.3 0 .5-.1.7-.3L15.4 7 14 5.6l-4 4V1H8v8.6l-4-4L2.6 7l5.7 5.7c.2.2.4.3.7.3zM2 15h14v2H2z"/></symbol><symbol id="plyr-enter-fullscreen"><path d="M10 3h3.6l-4 4L11 8.4l4-4V8h2V1h-7zM7 9.6l-4 4V10H1v7h7v-2H4.4l4-4z"/></symbol><symbol id="plyr-exit-fullscreen"><path d="M1 12h3.6l-4 4L2 17.4l4-4V17h2v-7H1zM16 .6l-4 4V1h-2v7h7V6h-3.6l4-4z"/></symbol><symbol id="plyr-fast-forward"><path d="M7.875 7.171L0 1v16l7.875-6.171V17L18 9 7.875 1z"/></symbol><symbol id="plyr-logo-vimeo"><path d="M17 5.3c-.1 1.6-1.2 3.7-3.3 6.4-2.2 2.8-4 4.2-5.5 4.2-.9 0-1.7-.9-2.4-2.6C5 10.9 4.4 6 3 6c-.1 0-.5.3-1.2.8l-.8-1c.8-.7 3.5-3.4 4.7-3.5 1.2-.1 2 .7 2.3 2.5.3 2 .8 6.1 1.8 6.1.9 0 2.5-3.4 2.6-4 .1-.9-.3-1.9-2.3-1.1.8-2.6 2.3-3.8 4.5-3.8 1.7.1 2.5 1.2 2.4 3.3z"/></symbol><symbol id="plyr-logo-youtube"><path d="M16.8 5.8c-.2-1.3-.8-2.2-2.2-2.4C12.4 3 9 3 9 3s-3.4 0-5.6.4C2 3.6 1.3 4.5 1.2 5.8 1 7.1 1 9 1 9s0 1.9.2 3.2c.2 1.3.8 2.2 2.2 2.4C5.6 15 9 15 9 15s3.4 0 5.6-.4c1.4-.3 2-1.1 2.2-2.4.2-1.3.2-3.2.2-3.2s0-1.9-.2-3.2zM7 12V6l5 3-5 3z"/></symbol><symbol id="plyr-muted"><path d="M12.4 12.5l2.1-2.1 2.1 2.1 1.4-1.4L15.9 9 18 6.9l-1.4-1.4-2.1 2.1-2.1-2.1L11 6.9 13.1 9 11 11.1zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol><symbol id="plyr-pause"><path d="M6 1H3c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1zM12 1c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1h-3z"/></symbol><symbol id="plyr-pip"><path d="M13.293 3.293L7.022 9.564l1.414 1.414 6.271-6.271L17 7V1h-6z"/><path d="M13 15H3V5h5V3H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-6h-2v5z"/></symbol><symbol id="plyr-play"><path d="M15.562 8.1L3.87.225C3.052-.337 2 .225 2 1.125v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"/></symbol><symbol id="plyr-restart"><path d="M9.7 1.2l.7 6.4 2.1-2.1c1.9 1.9 1.9 5.1 0 7-.9 1-2.2 1.5-3.5 1.5-1.3 0-2.6-.5-3.5-1.5-1.9-1.9-1.9-5.1 0-7 .6-.6 1.4-1.1 2.3-1.3l-.6-1.9C6 2.6 4.9 3.2 4 4.1 1.3 6.8 1.3 11.2 4 14c1.3 1.3 3.1 2 4.9 2 1.9 0 3.6-.7 4.9-2 2.7-2.7 2.7-7.1 0-9.9L16 1.9l-6.3-.7z"/></symbol><symbol id="plyr-rewind"><path d="M10.125 1L0 9l10.125 8v-6.171L18 17V1l-7.875 6.171z"/></symbol><symbol id="plyr-settings"><path d="M16.135 7.784a2 2 0 0 1-1.23-2.969c.322-.536.225-.998-.094-1.316l-.31-.31c-.318-.318-.78-.415-1.316-.094a2 2 0 0 1-2.969-1.23C10.065 1.258 9.669 1 9.219 1h-.438c-.45 0-.845.258-.997.865a2 2 0 0 1-2.969 1.23c-.536-.322-.999-.225-1.317.093l-.31.31c-.318.318-.415.781-.093 1.317a2 2 0 0 1-1.23 2.969C1.26 7.935 1 8.33 1 8.781v.438c0 .45.258.845.865.997a2 2 0 0 1 1.23 2.969c-.322.536-.225.998.094 1.316l.31.31c.319.319.782.415 1.316.094a2 2 0 0 1 2.969 1.23c.151.607.547.865.997.865h.438c.45 0 .845-.258.997-.865a2 2 0 0 1 2.969-1.23c.535.321.997.225 1.316-.094l.31-.31c.318-.318.415-.781.094-1.316a2 2 0 0 1 1.23-2.969c.607-.151.865-.547.865-.997v-.438c0-.451-.26-.846-.865-.997zM9 12a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol id="plyr-volume"><path d="M15.6 3.3c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4C15.4 5.9 16 7.4 16 9c0 1.6-.6 3.1-1.8 4.3-.4.4-.4 1 0 1.4.2.2.5.3.7.3.3 0 .5-.1.7-.3C17.1 13.2 18 11.2 18 9s-.9-4.2-2.4-5.7z"/><path d="M11.282 5.282a.909.909 0 0 0 0 1.316c.735.735.995 1.458.995 2.402 0 .936-.425 1.917-.995 2.487a.909.909 0 0 0 0 1.316c.145.145.636.262 1.018.156a.725.725 0 0 0 .298-.156C13.773 11.733 14.13 10.16 14.13 9c0-.17-.002-.34-.011-.51-.053-.992-.319-2.005-1.522-3.208a.909.909 0 0 0-1.316 0zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol></svg>
\ No newline at end of file diff --git a/demo/index.html b/demo/index.html index df0076f7..c668b00c 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,190 +1,286 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> + <head> + <meta charset="utf-8" /> + <title>Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player</title> + <meta + name="description" + property="og:description" + content="A simple HTML5 media player with custom controls and WebVTT captions." + /> + <meta name="author" content="Sam Potts" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> -<head> - <meta charset="utf-8" /> - <title>Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player</title> - <meta name="description" property="og:description" content="A simple HTML5 media player with custom controls and WebVTT captions."> - <meta name="author" content="Sam Potts"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - - <!-- Icons --> - <link rel="icon" href="https://cdn.plyr.io/static/icons/favicon.ico"> - <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/32x32.png" sizes="32x32"> - <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/16x16.png" sizes="16x16"> - <link rel="apple-touch-icon" sizes="180x180" href="https://cdn.plyr.io/static/icons/180x180.png"> - - <!-- Opengraph --> - <meta property="og:title" content="Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player"> - <meta property="og:site_name" content="Plyr"> - <meta property="og:url" content="https://plyr.io"> - <meta property="og:image" content="https://cdn.plyr.io/static/icons/1200x630.png"> - - <!-- Twitter --> - <meta name="twitter:card" content="summary"> - <meta name="twitter:site" content="@sam_potts"> - <meta name="twitter:creator" content="@sam_potts"> - <meta name="twitter:card" content="summary_large_image"> - - <!-- Docs styles --> - <link rel="stylesheet" href="dist/demo.css?v=2"> - - <!-- Preload --> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2"> - <link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2"> -</head> - -<body> - <div class="grid"> - <header> - <h1>Plyr</h1> - <p>A simple, accessible and customisable media player for - <button type="button" class="faux-link" data-source="video"> - <svg class="icon"> - <title>HTML5</title> - <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> - </svg>Video</button>, - <button type="button" class="faux-link" data-source="audio"> - <svg class="icon"> - <title>HTML5</title> - <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> - </svg>Audio</button>, - <button type="button" class="faux-link" data-source="youtube"> - <svg class="icon" role="presentation"> - <title>YouTube</title> - <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 + <!-- Icons --> + <link rel="icon" href="https://cdn.plyr.io/static/icons/favicon.ico" /> + <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/32x32.png" sizes="32x32" /> + <link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/16x16.png" sizes="16x16" /> + <link rel="apple-touch-icon" sizes="180x180" href="https://cdn.plyr.io/static/icons/180x180.png" /> + + <!-- Opengraph --> + <meta + property="og:title" + content="Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player" + /> + <meta property="og:site_name" content="Plyr" /> + <meta property="og:url" content="https://plyr.io" /> + <meta property="og:image" content="https://cdn.plyr.io/static/icons/1200x630.png" /> + + <!-- Twitter --> + <meta name="twitter:card" content="summary" /> + <meta name="twitter:site" content="@sam_potts" /> + <meta name="twitter:creator" content="@sam_potts" /> + <meta name="twitter:card" content="summary_large_image" /> + + <!-- Docs styles --> + <link rel="stylesheet" href="dist/demo.css" /> + + <!-- Preload --> + <link + rel="preload" + as="font" + crossorigin + type="font/woff2" + href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2" + /> + <link + rel="preload" + as="font" + crossorigin + type="font/woff2" + href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2" + /> + </head> + + <body> + <div class="grid"> + <header> + <h1>Plyr</h1> + <p> + A simple, accessible and customisable media player for + <button type="button" class="faux-link" data-source="video"> + <svg class="icon"> + <title>HTML5</title> + <path + d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z" + ></path></svg + >Video</button + >, + <button type="button" class="faux-link" data-source="audio"> + <svg class="icon"> + <title>HTML5</title> + <path + d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z" + ></path></svg + >Audio</button + >, + <button type="button" class="faux-link" data-source="youtube"> + <svg class="icon" role="presentation"> + <title>YouTube</title> + <path + d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z - M6,11V5l5,3L6,11z"></path> - </svg>YouTube</button> and - <button type="button" class="faux-link" data-source="vimeo"> - <svg class="icon" role="presentation"> - <title>Vimeo</title> - <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 + M6,11V5l5,3L6,11z" + ></path></svg + >YouTube + </button> + and + <button type="button" class="faux-link" data-source="vimeo"> + <svg class="icon" role="presentation"> + <title>Vimeo</title> + <path + d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 - c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> - </svg>Vimeo</button> - </p> + c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z" + ></path></svg + >Vimeo + </button> + </p> - <p>Premium video monitization from - <a href="https://vi.ai/publisher-video-monetization/?aid=plyrio" target="_blank" class="no-border"> - <img src="https://cdn.plyr.io/static/vi-logo-24x24.svg" alt="ai.vi"> - <span class="sr-only">ai.vi</span> - </a> - </p> + <p> + Premium video monitization from + <a href="https://vi.ai/publisher-video-monetization/?aid=plyrio" target="_blank" class="no-border"> + <img src="https://cdn.plyr.io/static/vi-logo-24x24.svg" alt="ai.vi" /> + <span class="sr-only">ai.vi</span> + </a> + </p> - <div class="call-to-action"> - <span class="button--with-count"> - <a href="https://github.com/sampotts/plyr" target="_blank" class="button" data-shr-network="github"> - <svg class="icon" role="presentation"> - <title>GitHub</title> - <path d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6 + <div class="call-to-action"> + <span class="button--with-count"> + <a + href="https://github.com/sampotts/plyr" + target="_blank" + class="button" + data-shr-network="github" + > + <svg class="icon" role="presentation"> + <title>GitHub</title> + <path + d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6 C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5 c0.8,0.1,1.2,0.8,1.2,0.8C4.4,13.4,5.6,13,6,12.8c0.1-0.5,0.3-0.9,0.5-1.1c-1.8-0.2-3.6-0.9-3.6-4c0-0.9,0.3-1.6,0.8-2.1 c-0.1-0.2-0.4-1,0.1-2.1c0,0,0.7-0.2,2.2,0.8c0.6-0.2,1.3-0.3,2-0.3c0.7,0,1.4,0.1,2,0.3c1.5-1,2.2-0.8,2.2-0.8 c0.4,1.1,0.2,1.9,0.1,2.1c0.5,0.6,0.8,1.3,0.8,2.1c0,3.1-1.9,3.7-3.7,3.9C9.7,12,10,12.5,10,13.2c0,1.1,0,1.9,0,2.2 - c0,0.2,0.1,0.5,0.6,0.4c3.2-1.1,5.5-4.1,5.5-7.6C16,3.8,12.4,0.2,8,0.2z"></path> - </svg> - Download on GitHub - </a> - </span> - </div> - </header> - - <main> - <video controls crossorigin playsinline poster="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg" id="player"> - <!-- Video files --> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4" size="576"> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4" type="video/mp4" size="720"> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4" type="video/mp4" size="1080"> - <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4" type="video/mp4" size="1440"> - - <!-- Caption files --> - <track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt" - default> - <track kind="captions" label="Français" srclang="fr" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt"> - - <!-- Fallback for browsers that don't support the <video> element --> - <a href="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" download>Download</a> - </video> - - <ul> - <li class="plyr__cite plyr__cite--video" hidden> - <small> - <svg class="icon"> - <title>HTML5</title> - <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> - </svg> - <a href="https://itunes.apple.com/au/movie/view-from-a-blue-moon/id1041586323" target="_blank">View From A Blue Moon</a> © Brainfarm - </small> - </li> - <li class="plyr__cite plyr__cite--audio" hidden> - <small> - <svg class="icon" title="HTML5"> - <title>HTML5</title> - <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> - </svg> - <a href="http://www.kishibashi.com/" target="_blank">Kishi Bashi – “It All Began With A Burst”</a> © Kishi Bashi - </small> - </li> - <li class="plyr__cite plyr__cite--youtube" hidden> - <small> - <a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank">View From A Blue Moon</a> on - <span class="color--youtube"> - <svg class="icon" role="presentation"> - <title>YouTube</title> - <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 + c0,0.2,0.1,0.5,0.6,0.4c3.2-1.1,5.5-4.1,5.5-7.6C16,3.8,12.4,0.2,8,0.2z" + ></path> + </svg> + Download on GitHub + </a> + </span> + </div> + </header> + + <main> + <div id="container"> + <video + controls + crossorigin + playsinline + poster="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg" + id="player" + > + <!-- Video files --> + <source + src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" + type="video/mp4" + size="576" + /> + <source + src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4" + type="video/mp4" + size="720" + /> + <source + src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4" + type="video/mp4" + size="1080" + /> + + <!-- Caption files --> + <track + kind="captions" + label="English" + srclang="en" + src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt" + default + /> + <track + kind="captions" + label="Français" + srclang="fr" + src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt" + /> + + <!-- Fallback for browsers that don't support the <video> element --> + <a href="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" download + >Download</a + > + </video> + </div> + + <ul> + <li class="plyr__cite plyr__cite--video" hidden> + <small> + <svg class="icon"> + <title>HTML5</title> + <path + d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z" + ></path> + </svg> + <a + href="https://itunes.apple.com/au/movie/view-from-a-blue-moon/id1041586323" + target="_blank" + >View From A Blue Moon</a + > + © Brainfarm + </small> + </li> + <li class="plyr__cite plyr__cite--audio" hidden> + <small> + <svg class="icon" title="HTML5"> + <title>HTML5</title> + <path + d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z" + ></path> + </svg> + <a href="http://www.kishibashi.com/" target="_blank" + >Kishi Bashi – “It All Began With A Burst”</a + > + © Kishi Bashi + </small> + </li> + <li class="plyr__cite plyr__cite--youtube" hidden> + <small> + <a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank" + >View From A Blue Moon</a + > + on + <span class="color--youtube"> + <svg class="icon" role="presentation"> + <title>YouTube</title> + <path + d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z - M6,11V5l5,3L6,11z"></path> - </svg>YouTube - </span> - </small> - </li> - <li class="plyr__cite plyr__cite--vimeo" hidden> - <small> - <a href="https://vimeo.com/76979871" target="_blank">The New Vimeo Player</a> on - <span class="color--vimeo"> - <svg class="icon" role="presentation"> - <title>Vimeo</title> - <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 + M6,11V5l5,3L6,11z" + ></path></svg + >YouTube + </span> + </small> + </li> + <li class="plyr__cite plyr__cite--vimeo" hidden> + <small> + <a href="https://vimeo.com/76979871" target="_blank">The New Vimeo Player</a> on + <span class="color--vimeo"> + <svg class="icon" role="presentation"> + <title>Vimeo</title> + <path + d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 - c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> - </svg>Vimeo - </span> - </small> - </li> - </ul> - </main> - </div> - - <aside> - <svg class="icon"> - <title>Twitter</title> - <path d="M16,3c-0.6,0.3-1.2,0.4-1.9,0.5c0.7-0.4,1.2-1,1.4-1.8c-0.6,0.4-1.3,0.6-2.1,0.8c-0.6-0.6-1.5-1-2.4-1 + c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z" + ></path></svg + >Vimeo + </span> + </small> + </li> + </ul> + </main> + </div> + + <aside> + <svg class="icon"> + <title>Twitter</title> + <path + d="M16,3c-0.6,0.3-1.2,0.4-1.9,0.5c0.7-0.4,1.2-1,1.4-1.8c-0.6,0.4-1.3,0.6-2.1,0.8c-0.6-0.6-1.5-1-2.4-1 C9.3,1.5,7.8,3,7.8,4.8c0,0.3,0,0.5,0.1,0.7C5.2,5.4,2.7,4.1,1.1,2.1c-0.3,0.5-0.4,1-0.4,1.7c0,1.1,0.6,2.1,1.5,2.7 c-0.5,0-1-0.2-1.5-0.4c0,0,0,0,0,0c0,1.6,1.1,2.9,2.6,3.2C3,9.4,2.7,9.4,2.4,9.4c-0.2,0-0.4,0-0.6-0.1c0.4,1.3,1.6,2.3,3.1,2.3 - c-1.1,0.9-2.5,1.4-4.1,1.4c-0.3,0-0.5,0-0.8,0c1.5,0.9,3.2,1.5,5,1.5c6,0,9.3-5,9.3-9.3c0-0.1,0-0.3,0-0.4C15,4.3,15.6,3.7,16,3z"></path> - </svg> - <p>If you think Plyr's good, - <a href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts" - target="_blank" data-shr-network="twitter">tweet it</a> - </p> - </aside> - - <!-- Polyfills --> - <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6,Array.prototype.includes,CustomEvent,Object.entries,Object.values,URL" - crossorigin="anonymous"></script> - - <!-- Plyr core script --> - <script src="../dist/plyr.js" crossorigin="anonymous"></script> + c-1.1,0.9-2.5,1.4-4.1,1.4c-0.3,0-0.5,0-0.8,0c1.5,0.9,3.2,1.5,5,1.5c6,0,9.3-5,9.3-9.3c0-0.1,0-0.3,0-0.4C15,4.3,15.6,3.7,16,3z" + ></path> + </svg> + <p> + If you think Plyr's good, + <a + href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts" + target="_blank" + data-shr-network="twitter" + >tweet it</a + > + 👍 + </p> + </aside> - <!-- Sharing libary (https://shr.one) --> - <script src="https://cdn.shr.one/1.0.1/shr.js" crossorigin="anonymous"></script> + <!-- Polyfills --> + <script + src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6,Array.prototype.includes,CustomEvent,Object.entries,Object.values,URL,Math.trunc" + crossorigin="anonymous" + ></script> - <!-- Rangetouch to fix <input type="range"> on touch devices (see https://rangetouch.com) --> - <script src="https://cdn.rangetouch.com/1.0.1/rangetouch.js" async crossorigin="anonymous"></script> + <!-- Sharing libary (https://shr.one) --> + <script src="https://cdn.shr.one/1.0.1/shr.js" crossorigin="anonymous"></script> - <!-- Docs script --> - <script src="dist/demo.js" crossorigin="anonymous"></script> -</body> + <!-- Rangetouch to fix <input type="range"> on touch devices (see https://rangetouch.com) --> + <script src="https://cdn.rangetouch.com/1.0.1/rangetouch.js" async crossorigin="anonymous"></script> -</html>
\ No newline at end of file + <!-- Docs script --> + <script src="dist/demo.js" crossorigin="anonymous"></script> + </body> +</html> diff --git a/demo/src/js/demo.js b/demo/src/js/demo.js index 003e85d5..add123e5 100644 --- a/demo/src/js/demo.js +++ b/demo/src/js/demo.js @@ -5,18 +5,20 @@ // ========================================================================== import Raven from 'raven-js'; +import Plyr from '../../../src/js/plyr'; (() => { - const isLive = window.location.host === 'plyr.io'; - - // Raven / Sentry - // For demo site (https://plyr.io) only - if (isLive) { - Raven.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install(); - } + const { host } = window.location; + const env = { + prod: host === 'plyr.io', + dev: host === 'dev.plyr.io', + }; document.addEventListener('DOMContentLoaded', () => { Raven.context(() => { + const selector = '#player'; + const container = document.getElementById('container'); + if (window.shr) { window.shr.setup({ count: { @@ -30,6 +32,10 @@ import Raven from 'raven-js'; // Remove class on blur document.addEventListener('focusout', event => { + if (!event.target.classList || container.contains(event.target)) { + return; + } + event.target.classList.remove(tabClassName); }); @@ -42,71 +48,27 @@ import Raven from 'raven-js'; // Delay the adding of classname until the focus has changed // This event fires before the focusin event setTimeout(() => { - document.activeElement.classList.add(tabClassName); - }, 0); + const focused = document.activeElement; + + if (!focused || !focused.classList || container.contains(focused)) { + return; + } + + focused.classList.add(tabClassName); + }, 10); }); // Setup the player - const player = new Plyr('#player', { + const player = new Plyr(selector, { debug: true, title: 'View From A Blue Moon', - iconUrl: '../dist/plyr.svg', + iconUrl: 'dist/plyr.svg', keyboard: { global: true, }, tooltips: { controls: true, }, - /* controls: [ - 'play-large', - 'restart', - 'rewind', - 'play', - 'fast-forward', - 'progress', - 'current-time', - 'duration', - 'mute', - 'volume', - 'captions', - 'settings', - 'pip', - 'airplay', - 'fullscreen', - ], */ - /* i18n: { - restart: '重新開始', - rewind: '快退{seektime}秒', - play: '播放', - pause: '暫停', - fastForward: '快進{seektime}秒', - seek: '尋求', - played: '發揮', - buffered: '緩衝的', - currentTime: '當前時間戳', - duration: '長短', - volume: '音量', - mute: '靜音', - unmute: '取消靜音', - enableCaptions: '開啟字幕', - disableCaptions: '關閉字幕', - enterFullscreen: '進入全螢幕', - exitFullscreen: '退出全螢幕', - frameTitle: '球員為{title}', - captions: '字幕', - settings: '設定', - speed: '速度', - normal: '正常', - quality: '質量', - loop: '循環', - start: 'Start', - end: 'End', - all: 'All', - reset: '重啟', - disabled: '殘', - enabled: '啟用', - advertisement: '廣告', - }, */ captions: { active: true, }, @@ -114,9 +76,16 @@ import Raven from 'raven-js'; google: 'AIzaSyDrNwtN3nLH_8rjCmu5Wq3ZCm4MNAVdc0c', }, ads: { - enabled: true, + enabled: env.prod || env.dev, publisherId: '918848828995742', }, + previewThumbnails: { + enabled: true, + src: [ + 'https://cdn.plyr.io/static/demo/thumbs/100p.vtt', + 'https://cdn.plyr.io/static/demo/thumbs/240p.vtt', + ], + }, }); // Expose for tinkering in the console @@ -143,7 +112,11 @@ import Raven from 'raven-js'; // Set a new source function newSource(type, init) { // Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video - if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) { + if ( + !(type in types) || + (!init && type === currentType) || + (!currentType.length && type === types.video) + ) { return; } @@ -215,10 +188,12 @@ import Raven from 'raven-js'; case types.youtube: player.source = { type: 'video', - sources: [{ - src: 'https://youtube.com/watch?v=bTqVqk7FSmY', - provider: 'youtube', - }], + sources: [ + { + src: 'https://youtube.com/watch?v=bTqVqk7FSmY', + provider: 'youtube', + }, + ], }; break; @@ -226,10 +201,12 @@ import Raven from 'raven-js'; case types.vimeo: player.source = { type: 'video', - sources: [{ - src: 'https://vimeo.com/76979871', - provider: 'vimeo', - }], + sources: [ + { + src: 'https://vimeo.com/76979871', + provider: 'vimeo', + }, + ], }; break; @@ -302,26 +279,9 @@ import Raven from 'raven-js'; }); }); - // Google analytics + // Raven / Sentry // For demo site (https://plyr.io) only - /* eslint-disable */ - if (isLive) { - (function(i, s, o, g, r, a, m) { - i.GoogleAnalyticsObject = r; - i[r] = - i[r] || - function() { - (i[r].q = i[r].q || []).push(arguments); - }; - i[r].l = 1 * new Date(); - a = s.createElement(o); - m = s.getElementsByTagName(o)[0]; - a.async = 1; - a.src = g; - m.parentNode.insertBefore(a, m); - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - window.ga('create', 'UA-40881672-11', 'auto'); - window.ga('send', 'pageview'); + if (env.prod) { + Raven.config('https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555').install(); } - /* eslint-enable */ })(); diff --git a/demo/src/sass/lib/fontface.scss b/demo/src/sass/lib/fontface.scss index e7e4edf8..d104c501 100644 --- a/demo/src/sass/lib/fontface.scss +++ b/demo/src/sass/lib/fontface.scss @@ -7,7 +7,8 @@ font-family: 'Gordita'; font-style: normal; font-weight: $font-weight-light; - src: url('https://cdn.plyr.io/static/fonts/gordita-light.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-light.woff') format('woff'); + src: url('https://cdn.plyr.io/static/fonts/gordita-light.woff2') format('woff2'), + url('https://cdn.plyr.io/static/fonts/gordita-light.woff') format('woff'); } @font-face { @@ -33,7 +34,8 @@ font-family: 'Gordita'; font-style: normal; font-weight: $font-weight-bold; - src: url('https://cdn.plyr.io/static/fonts/gordita-bold.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-bold.woff') format('woff'); + src: url('https://cdn.plyr.io/static/fonts/gordita-bold.woff2') format('woff2'), + url('https://cdn.plyr.io/static/fonts/gordita-bold.woff') format('woff'); } @font-face { @@ -41,5 +43,6 @@ font-family: 'Gordita'; font-style: normal; font-weight: $font-weight-black; - src: url('https://cdn.plyr.io/static/fonts/gordita-black.woff2') format('woff2'), url('https://cdn.plyr.io/static/fonts/gordita-black.woff') format('woff'); + src: url('https://cdn.plyr.io/static/fonts/gordita-black.woff2') format('woff2'), + url('https://cdn.plyr.io/static/fonts/gordita-black.woff') format('woff'); } diff --git a/demo/src/sass/settings/layout.scss b/demo/src/sass/settings/layout.scss index 8d1fbd28..77185344 100644 --- a/demo/src/sass/settings/layout.scss +++ b/demo/src/sass/settings/layout.scss @@ -2,4 +2,4 @@ // Layout // ========================================================================== -$container-max-width: 1280px; +$container-max-width: 1260px; diff --git a/demo/src/sass/settings/plyr.scss b/demo/src/sass/settings/plyr.scss index 44f89bb2..ae6be636 100644 --- a/demo/src/sass/settings/plyr.scss +++ b/demo/src/sass/settings/plyr.scss @@ -11,6 +11,9 @@ $plyr-font-size-small: 12px; $plyr-font-size-time: 11px; $plyr-font-size-badges: 9px; +// Other +$plyr-font-smoothing: true; + // Captions $plyr-font-size-captions-base: $plyr-font-size-base; $plyr-font-size-captions-small: $plyr-font-size-small; diff --git a/demo/src/sass/settings/type.scss b/demo/src/sass/settings/type.scss index e8f0b2c8..8c614361 100644 --- a/demo/src/sass/settings/type.scss +++ b/demo/src/sass/settings/type.scss @@ -2,7 +2,8 @@ // Typography // ========================================================================== -$font-sans-serif: 'Gordita', 'Avenir', 'Helvetica Neue', sans-serif; +$font-sans-serif: 'Gordita', 'Avenir', 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol'; $font-size-base: 15; $font-size-small: 13; diff --git a/dist/plyr.css b/dist/plyr.css index 04331e8e..190571d5 100644 --- a/dist/plyr.css +++ b/dist/plyr.css @@ -1 +1 @@ -@keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-family:Avenir,"Avenir Next","Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-variant-numeric:tabular-nums;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:#fff;font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:14px;left:0;padding:10px;position:absolute;text-align:center;transform:translateY(-40px);transition:transform .4s ease-in-out;width:100%}.plyr__captions span{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions span div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:16px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr--hide-controls .plyr__captions{transform:translateY(-15px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__control[aria-pressed=false] .icon--pressed,.plyr__control[aria-pressed=false] .label--pressed,.plyr__control[aria-pressed=true] .icon--not-pressed,.plyr__control[aria-pressed=true] .label--not-pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{height:20px;left:2px;position:relative;width:20px}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu:first-child,.plyr__controls .plyr__menu:first-child+[data-plyr=pause],.plyr__controls .plyr__progress:first-child,.plyr__controls .plyr__progress:first-child+[data-plyr=pause],.plyr__controls .plyr__time:first-child,.plyr__controls .plyr__time:first-child+[data-plyr=pause],.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0}.plyr__controls .plyr__volume{margin-left:5px}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls>.plyr__control{margin-left:10px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:5px}}.plyr--video .plyr__controls{background:linear-gradient(transparent,rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:35px 10px 10px;position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:2}.plyr--video .plyr__controls .plyr__control svg{-webkit-filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15));filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__controls .plyr__control.plyr__tab-focus,.plyr--video .plyr__controls .plyr__control:hover,.plyr--video .plyr__controls .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%;position:relative}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr--full-ui .plyr__video-embed iframe{pointer-events:none}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:16px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container ul{list-style:none;margin:0;overflow:hidden;padding:7px}.plyr__menu__container ul li{margin-top:2px}.plyr__menu__container ul li:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4f5b5f;display:flex;font-size:14px;padding:4px 14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container label.plyr__control{padding-left:7px}.plyr__menu__container label.plyr__control input[type=radio]+span{background:rgba(0,0,0,.1);border-radius:100%;display:block;flex-shrink:0;height:16px;margin-right:10px;position:relative;transition:all .3s ease;width:16px}.plyr__menu__container label.plyr__control input[type=radio]+span::after{background:#fff;border-radius:100%;content:'';height:6px;left:5px;opacity:0;position:absolute;top:5px;transform:scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container label.plyr__control input[type=radio]:checked+span{background:#1aafff}.plyr__menu__container label.plyr__control input[type=radio]:checked+span::after{opacity:1;transform:scale(1)}.plyr__menu__container label.plyr__control input[type=radio]:focus+span{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr__menu__container label.plyr__control.plyr__tab-focus input[type=radio]+span,.plyr__menu__container label.plyr__control:hover input[type=radio]+span{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:-7px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr__progress{display:flex;flex:1;position:relative}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:14px;left:0}.plyr__progress--buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:6px;left:0;margin:-3px 0 0;padding:0;position:absolute;top:50%;width:100%}.plyr__progress--buffer::-webkit-progress-bar{background:0 0;transition:width .2s ease}.plyr__progress--buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:6px}.plyr__progress--buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:6px;transition:width .2s ease}.plyr__progress--buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress--buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress--buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress--buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress--buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress--buffer{background-color:rgba(183,197,205,.66)}.plyr__poster{background-color:#000;background-position:50% 50%;background-repeat:no-repeat;background-size:100% 100%;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr--stopped .plyr__poster{opacity:1}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:28px;color:#1aafff;display:block;height:20px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-webkit-user-select:none;user-select:none;background-image:linear-gradient(to right,currentColor var(--value,0),transparent var(--value,0))}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:3px;height:6px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:3px;height:6px;transition:all .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);box-sizing:border-box;height:14px;position:relative;transition:all .2s ease;width:14px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 3px rgba(26,175,255,.35);outline:0}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr__time{font-size:14px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:14px;font-weight:500;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;white-space:nowrap;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translate(0,10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{right:0;transform:translate(0,10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0,0) scale(1)}.plyr--video{overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__volume{flex:1;position:relative}.plyr__volume input[type=range]{position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:50px}}@media (min-width:768px){.plyr__volume{max-width:80px}}.plyr--is-ios .plyr__volume{display:none!important}.plyr--is-ios.plyr--vimeo [data-plyr=mute]{display:none!important}.plyr--has-error{pointer-events:none}.plyr--has-error::after{align-items:center;background:#000;color:#fff;content:attr(data-plyr-error);display:flex;font-size:16px;height:100%;justify-content:center;left:0;position:absolute;text-align:center;text-shadow:0 1px 1px #000;top:0;width:100%;z-index:10}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:fullscreen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen .plyr__video-embed{overflow:visible}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-embed{overflow:visible}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-embed{overflow:visible}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback .plyr__video-embed{overflow:visible}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads::after{background:rgba(47,52,61,.8);border-radius:2px;bottom:10px;color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;z-index:3}.plyr__ads::after:empty{display:none}.plyr__cues{background:currentColor;display:block;height:6px;left:0;margin:-3px 0 0;opacity:.8;position:absolute;top:50%;width:3px;z-index:3}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}
\ No newline at end of file +@keyframes plyr-progress{to{background-position:25px 0}}@keyframes plyr-popup{0%{opacity:.5;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes plyr-fade-in{from{opacity:0}to{opacity:1}}.plyr{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:subpixel-antialiased;direction:ltr;font-family:Avenir,"Avenir Next","Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-variant-numeric:tabular-nums;font-weight:500;line-height:1.7;max-width:100%;min-width:200px;position:relative;text-shadow:none;transition:box-shadow .3s ease}.plyr audio,.plyr video{border-radius:inherit;height:auto;vertical-align:middle;width:100%}.plyr button{font:inherit;line-height:inherit;width:auto}.plyr:focus{outline:0}.plyr--full-ui{box-sizing:border-box}.plyr--full-ui *,.plyr--full-ui ::after,.plyr--full-ui ::before{box-sizing:inherit}.plyr--full-ui a,.plyr--full-ui button,.plyr--full-ui input,.plyr--full-ui label{touch-action:manipulation}.plyr__badge{background:#4f5b5f;border-radius:2px;color:#fff;font-size:9px;line-height:1;padding:3px 4px}.plyr--full-ui ::-webkit-media-text-track-container{display:none}.plyr__captions{animation:plyr-fade-in .3s ease;bottom:0;color:#fff;display:none;font-size:14px;left:0;padding:10px;position:absolute;text-align:center;transition:transform .4s ease-in-out;width:100%}.plyr__captions .plyr__caption{background:rgba(0,0,0,.8);border-radius:2px;-webkit-box-decoration-break:clone;box-decoration-break:clone;line-height:185%;padding:.2em .5em;white-space:pre-wrap}.plyr__captions .plyr__caption div{display:inline}.plyr__captions span:empty{display:none}@media (min-width:480px){.plyr__captions{font-size:16px;padding:20px}}@media (min-width:768px){.plyr__captions{font-size:18px}}.plyr--captions-active .plyr__captions{display:block}.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty)~.plyr__captions{transform:translateY(-40px)}.plyr__control{background:0 0;border:0;border-radius:3px;color:inherit;cursor:pointer;flex-shrink:0;overflow:visible;padding:7px;position:relative;transition:all .3s ease}.plyr__control svg{display:block;fill:currentColor;height:18px;pointer-events:none;width:18px}.plyr__control:focus{outline:0}.plyr__control.plyr__tab-focus{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}a.plyr__control{text-decoration:none}a.plyr__control::after,a.plyr__control::before{display:none}.plyr__control.plyr__control--pressed .icon--not-pressed,.plyr__control.plyr__control--pressed .label--not-pressed,.plyr__control:not(.plyr__control--pressed) .icon--pressed,.plyr__control:not(.plyr__control--pressed) .label--pressed{display:none}.plyr--audio .plyr__control.plyr__tab-focus,.plyr--audio .plyr__control:hover,.plyr--audio .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr--video .plyr__control svg{filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}.plyr--video .plyr__control.plyr__tab-focus,.plyr--video .plyr__control:hover,.plyr--video .plyr__control[aria-expanded=true]{background:#1aafff;color:#fff}.plyr__control--overlaid{background:rgba(26,175,255,.8);border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15);color:#fff;display:none;left:50%;padding:15px;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:2}.plyr__control--overlaid svg{left:2px;position:relative}.plyr__control--overlaid:focus,.plyr__control--overlaid:hover{background:#1aafff}.plyr--playing .plyr__control--overlaid{opacity:0;visibility:hidden}.plyr--full-ui.plyr--video .plyr__control--overlaid{display:block}.plyr--full-ui ::-webkit-media-controls{display:none}.plyr__controls{align-items:center;display:flex;justify-content:flex-end;text-align:center}.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls .plyr__volume,.plyr__controls>.plyr__control{margin-left:5px}.plyr__controls .plyr__menu+.plyr__control,.plyr__controls .plyr__progress+.plyr__control,.plyr__controls>.plyr__control+.plyr__control,.plyr__controls>.plyr__control+.plyr__menu{margin-left:2px}.plyr__controls>.plyr__control:first-child,.plyr__controls>.plyr__control:first-child+[data-plyr=pause]{margin-left:0;margin-right:auto}.plyr__controls:empty{display:none}@media (min-width:480px){.plyr__controls .plyr__menu,.plyr__controls .plyr__progress,.plyr__controls .plyr__time,.plyr__controls .plyr__volume,.plyr__controls>.plyr__control{margin-left:10px}}.plyr--audio .plyr__controls{background:#fff;border-radius:inherit;color:#4f5b5f;padding:10px}.plyr--video .plyr__controls{background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.7));border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;bottom:0;color:#fff;left:0;padding:20px 5px 5px;position:absolute;right:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out;z-index:3}@media (min-width:480px){.plyr--video .plyr__controls{padding:35px 10px 10px}}.plyr--video.plyr--hide-controls .plyr__controls{opacity:0;pointer-events:none;transform:translateY(100%)}.plyr [data-plyr=airplay],.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr [data-plyr=pip]{display:none}.plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--fullscreen-enabled [data-plyr=fullscreen],.plyr--pip-supported [data-plyr=pip]{display:inline-block}.plyr__video-embed{height:0;padding-bottom:56.25%;position:relative}.plyr__video-embed iframe{border:0;height:100%;left:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr--full-ui .plyr__video-embed>.plyr__video-embed__container{padding-bottom:240%;position:relative;transform:translateY(-38.28125%)}.plyr__menu{display:flex;position:relative}.plyr__menu .plyr__control svg{transition:transform .3s ease}.plyr__menu .plyr__control[aria-expanded=true] svg{transform:rotate(90deg)}.plyr__menu .plyr__control[aria-expanded=true] .plyr__tooltip{display:none}.plyr__menu__container{animation:plyr-popup .2s ease;background:rgba(255,255,255,.9);border-radius:4px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:16px;margin-bottom:10px;position:absolute;right:-3px;text-align:left;white-space:nowrap;z-index:3}.plyr__menu__container>div{overflow:hidden;transition:height .35s cubic-bezier(.4,0,.2,1),width .35s cubic-bezier(.4,0,.2,1)}.plyr__menu__container::after{border:4px solid transparent;border-top-color:rgba(255,255,255,.9);content:'';height:0;position:absolute;right:15px;top:100%;width:0}.plyr__menu__container [role=menu]{padding:7px}.plyr__menu__container [role=menuitem],.plyr__menu__container [role=menuitemradio]{margin-top:2px}.plyr__menu__container [role=menuitem]:first-child,.plyr__menu__container [role=menuitemradio]:first-child{margin-top:0}.plyr__menu__container .plyr__control{align-items:center;color:#4f5b5f;display:flex;font-size:14px;padding:4px 11px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.plyr__menu__container .plyr__control>span{align-items:inherit;display:flex;width:100%}.plyr__menu__container .plyr__control::after{border:4px solid transparent;content:'';position:absolute;top:50%;transform:translateY(-50%)}.plyr__menu__container .plyr__control--forward{padding-right:28px}.plyr__menu__container .plyr__control--forward::after{border-left-color:rgba(79,91,95,.8);right:5px}.plyr__menu__container .plyr__control--forward.plyr__tab-focus::after,.plyr__menu__container .plyr__control--forward:hover::after{border-left-color:currentColor}.plyr__menu__container .plyr__control--back{font-weight:500;margin:7px;margin-bottom:3px;padding-left:28px;position:relative;width:calc(100% - 14px)}.plyr__menu__container .plyr__control--back::after{border-right-color:rgba(79,91,95,.8);left:7px}.plyr__menu__container .plyr__control--back::before{background:#b7c5cd;box-shadow:0 1px 0 #fff;content:'';height:1px;left:0;margin-top:4px;overflow:hidden;position:absolute;right:0;top:100%}.plyr__menu__container .plyr__control--back.plyr__tab-focus::after,.plyr__menu__container .plyr__control--back:hover::after{border-right-color:currentColor}.plyr__menu__container .plyr__control[role=menuitemradio]{padding-left:7px}.plyr__menu__container .plyr__control[role=menuitemradio]::after,.plyr__menu__container .plyr__control[role=menuitemradio]::before{border-radius:100%}.plyr__menu__container .plyr__control[role=menuitemradio]::before{background:rgba(0,0,0,.1);content:'';display:block;flex-shrink:0;height:16px;margin-right:10px;transition:all .3s ease;width:16px}.plyr__menu__container .plyr__control[role=menuitemradio]::after{background:#fff;border:0;height:6px;left:12px;opacity:0;top:50%;transform:translateY(-50%) scale(0);transition:transform .3s ease,opacity .3s ease;width:6px}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before{background:#1aafff}.plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::after{opacity:1;transform:translateY(-50%) scale(1)}.plyr__menu__container .plyr__control[role=menuitemradio].plyr__tab-focus::before,.plyr__menu__container .plyr__control[role=menuitemradio]:hover::before{background:rgba(0,0,0,.1)}.plyr__menu__container .plyr__menu__value{align-items:center;display:flex;margin-left:auto;margin-right:-5px;overflow:hidden;padding-left:25px;pointer-events:none}.plyr--full-ui input[type=range]{-webkit-appearance:none;background:0 0;border:0;border-radius:26px;color:#1aafff;display:block;height:19px;margin:0;padding:0;transition:box-shadow .3s ease;width:100%}.plyr--full-ui input[type=range]::-webkit-slider-runnable-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-webkit-user-select:none;user-select:none;background-image:linear-gradient(to right,currentColor var(--value,0),transparent var(--value,0))}.plyr--full-ui input[type=range]::-webkit-slider-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px;-webkit-appearance:none;margin-top:-4px}.plyr--full-ui input[type=range]::-moz-range-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-moz-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-moz-range-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px}.plyr--full-ui input[type=range]::-moz-range-progress{background:currentColor;border-radius:2.5px;height:5px}.plyr--full-ui input[type=range]::-ms-track{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;color:transparent}.plyr--full-ui input[type=range]::-ms-fill-upper{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none}.plyr--full-ui input[type=range]::-ms-fill-lower{background:0 0;border:0;border-radius:2.5px;height:5px;transition:box-shadow .3s ease;-ms-user-select:none;user-select:none;background:currentColor}.plyr--full-ui input[type=range]::-ms-thumb{background:#fff;border:0;border-radius:100%;box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2);height:13px;position:relative;transition:all .2s ease;width:13px;margin-top:0}.plyr--full-ui input[type=range]::-ms-tooltip{display:none}.plyr--full-ui input[type=range]:focus{outline:0}.plyr--full-ui input[type=range]::-moz-focus-outer{border:0}.plyr--full-ui input[type=range].plyr__tab-focus::-webkit-slider-runnable-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-moz-range-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui input[type=range].plyr__tab-focus::-ms-track{box-shadow:0 0 0 5px rgba(26,175,255,.5);outline:0}.plyr--full-ui.plyr--video input[type=range]::-webkit-slider-runnable-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-moz-range-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]::-ms-track{background-color:rgba(255,255,255,.25)}.plyr--full-ui.plyr--video input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--video input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(255,255,255,.5)}.plyr--full-ui.plyr--audio input[type=range]::-webkit-slider-runnable-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-moz-range-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]::-ms-track{background-color:rgba(183,197,205,.66)}.plyr--full-ui.plyr--audio input[type=range]:active::-webkit-slider-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-moz-range-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr--full-ui.plyr--audio input[type=range]:active::-ms-thumb{box-shadow:0 1px 1px rgba(0,0,0,.15),0 0 0 1px rgba(47,52,61,.2),0 0 0 3px rgba(0,0,0,.1)}.plyr__poster{background-color:#000;background-position:50% 50%;background-repeat:no-repeat;background-size:contain;height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .2s ease;width:100%;z-index:1}.plyr--stopped.plyr__poster-enabled .plyr__poster{opacity:1}.plyr__time{font-size:14px}.plyr__time+.plyr__time::before{content:'\2044';margin-right:10px}@media (max-width:767px){.plyr__time+.plyr__time{display:none}}.plyr--video .plyr__time{text-shadow:0 1px 1px rgba(0,0,0,.15)}.plyr__tooltip{background:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);color:#4f5b5f;font-size:14px;font-weight:500;left:50%;line-height:1.3;margin-bottom:10px;opacity:0;padding:5px 7.5px;pointer-events:none;position:absolute;transform:translate(-50%,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;white-space:nowrap;z-index:2}.plyr__tooltip::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,.plyr .plyr__control:hover .plyr__tooltip,.plyr__tooltip--visible{opacity:1;transform:translate(-50%,0) scale(1)}.plyr .plyr__control:hover .plyr__tooltip{z-index:3}.plyr__controls>.plyr__control:first-child .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip{left:0;transform:translate(0,10px) scale(.8);transform-origin:0 100%}.plyr__controls>.plyr__control:first-child .plyr__tooltip::before,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip::before{left:16px}.plyr__controls>.plyr__control:last-child .plyr__tooltip{left:auto;right:0;transform:translate(0,10px) scale(.8);transform-origin:100% 100%}.plyr__controls>.plyr__control:last-child .plyr__tooltip::before{left:auto;right:16px;transform:translateX(50%)}.plyr__controls>.plyr__control:first-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control .plyr__tooltip--visible,.plyr__controls>.plyr__control:first-child+.plyr__control.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child+.plyr__control:hover .plyr__tooltip,.plyr__controls>.plyr__control:first-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:first-child:hover .plyr__tooltip,.plyr__controls>.plyr__control:last-child .plyr__tooltip--visible,.plyr__controls>.plyr__control:last-child.plyr__tab-focus .plyr__tooltip,.plyr__controls>.plyr__control:last-child:hover .plyr__tooltip{transform:translate(0,0) scale(1)}.plyr--video{background:#000;overflow:hidden}.plyr--video.plyr--menu-open{overflow:visible}.plyr__video-wrapper{background:#000;border-radius:inherit;overflow:hidden;position:relative;z-index:0}.plyr__progress{flex:1;left:6.5px;margin-right:13px;position:relative}.plyr__progress input[type=range],.plyr__progress__buffer{margin-left:-6.5px;margin-right:-6.5px;width:calc(100% + 13px)}.plyr__progress input[type=range]{position:relative;z-index:2}.plyr__progress .plyr__tooltip{font-size:14px;left:0}.plyr__progress__buffer{-webkit-appearance:none;background:0 0;border:0;border-radius:100px;height:5px;left:0;margin-top:-2.5px;padding:0;position:absolute;top:50%}.plyr__progress__buffer::-webkit-progress-bar{background:0 0}.plyr__progress__buffer::-webkit-progress-value{background:currentColor;border-radius:100px;min-width:5px;transition:width .2s ease}.plyr__progress__buffer::-moz-progress-bar{background:currentColor;border-radius:100px;min-width:5px;transition:width .2s ease}.plyr__progress__buffer::-ms-fill{border-radius:100px;transition:width .2s ease}.plyr--video .plyr__progress__buffer{box-shadow:0 1px 1px rgba(0,0,0,.15);color:rgba(255,255,255,.25)}.plyr--audio .plyr__progress__buffer{color:rgba(183,197,205,.66)}.plyr--loading .plyr__progress__buffer{animation:plyr-progress 1s linear infinite;background-image:linear-gradient(-45deg,rgba(47,52,61,.6) 25%,transparent 25%,transparent 50%,rgba(47,52,61,.6) 50%,rgba(47,52,61,.6) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:25px 25px;color:transparent}.plyr--video.plyr--loading .plyr__progress__buffer{background-color:rgba(255,255,255,.25)}.plyr--audio.plyr--loading .plyr__progress__buffer{background-color:rgba(183,197,205,.66)}.plyr__volume{align-items:center;display:flex;flex:1;position:relative}.plyr__volume input[type=range]{margin-left:5px;position:relative;z-index:2}@media (min-width:480px){.plyr__volume{max-width:90px}}@media (min-width:768px){.plyr__volume{max-width:110px}}.plyr--is-ios .plyr__volume{display:none!important}.plyr--is-ios.plyr--vimeo [data-plyr=mute]{display:none!important}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:fullscreen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}.plyr:fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}.plyr:-moz-full-screen .plyr__captions{font-size:21px}.plyr:-ms-fullscreen .plyr__captions{font-size:21px}.plyr:fullscreen .plyr__captions{font-size:21px}}.plyr:-webkit-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-webkit-full-screen video{height:100%}.plyr:-webkit-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-webkit-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-webkit-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-webkit-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-webkit-full-screen .plyr__captions{font-size:21px}}.plyr:-moz-full-screen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-moz-full-screen video{height:100%}.plyr:-moz-full-screen .plyr__video-wrapper{height:100%;width:100%}.plyr:-moz-full-screen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-moz-full-screen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-moz-full-screen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-moz-full-screen .plyr__captions{font-size:21px}}.plyr:-ms-fullscreen{background:#000;border-radius:0!important;height:100%;margin:0;width:100%}.plyr:-ms-fullscreen video{height:100%}.plyr:-ms-fullscreen .plyr__video-wrapper{height:100%;width:100%}.plyr:-ms-fullscreen.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen{display:block}.plyr:-ms-fullscreen .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr:-ms-fullscreen.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr:-ms-fullscreen .plyr__captions{font-size:21px}}.plyr--fullscreen-fallback{background:#000;border-radius:0!important;height:100%;margin:0;width:100%;bottom:0;left:0;position:fixed;right:0;top:0;z-index:10000000}.plyr--fullscreen-fallback video{height:100%}.plyr--fullscreen-fallback .plyr__video-wrapper{height:100%;width:100%}.plyr--fullscreen-fallback.plyr--vimeo .plyr__video-wrapper{height:0;top:50%;transform:translateY(-50%)}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen{display:block}.plyr--fullscreen-fallback .plyr__control .icon--exit-fullscreen+svg{display:none}.plyr--fullscreen-fallback.plyr--hide-controls{cursor:none}@media (min-width:1024px){.plyr--fullscreen-fallback .plyr__captions{font-size:21px}}.plyr__ads{border-radius:inherit;bottom:0;cursor:pointer;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:-1}.plyr__ads>div,.plyr__ads>div iframe{height:100%;position:absolute;width:100%}.plyr__ads::after{background:rgba(47,52,61,.8);border-radius:2px;bottom:10px;color:#fff;content:attr(data-badge-text);font-size:11px;padding:2px 6px;pointer-events:none;position:absolute;right:10px;z-index:3}.plyr__ads::after:empty{display:none}.plyr__cues{background:currentColor;display:block;height:5px;left:0;margin:-2.5px 0 0;opacity:.8;position:absolute;top:50%;width:3px;z-index:3}.plyr__preview-thumb{background-color:rgba(255,255,255,.9);border-radius:3px;bottom:100%;box-shadow:0 1px 2px rgba(0,0,0,.15);margin-bottom:10px;opacity:0;padding:3px;pointer-events:none;position:absolute;transform:translate(0,10px) scale(.8);transform-origin:50% 100%;transition:transform .2s .1s ease,opacity .2s .1s ease;z-index:2}.plyr__preview-thumb--is-shown{opacity:1;transform:translate(0,0) scale(1)}.plyr__preview-thumb::before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.9);bottom:-4px;content:'';height:0;left:50%;position:absolute;transform:translateX(-50%);width:0;z-index:2}.plyr__preview-thumb__image-container{background:#b7c5cd;border-radius:2px;overflow:hidden;position:relative;z-index:0}.plyr__preview-thumb__image-container img{height:100%;left:0;max-height:none;max-width:none;position:absolute;top:0;width:100%}.plyr__preview-thumb__time-container{bottom:6px;left:0;position:absolute;right:0;white-space:nowrap;z-index:3}.plyr__preview-thumb__time-container span{background-color:rgba(0,0,0,.55);border-radius:2px;color:#fff;font-size:14px;padding:3px 6px}.plyr__preview-scrubbing{bottom:0;filter:blur(1px);height:100%;left:0;margin:auto;opacity:0;overflow:hidden;position:absolute;right:0;top:0;transition:opacity .3s ease;width:100%;z-index:1}.plyr__preview-scrubbing--is-shown{opacity:1}.plyr__preview-scrubbing img{height:100%;left:0;max-height:none;max-width:none;-o-object-fit:contain;object-fit:contain;position:absolute;top:0;width:100%}.plyr--no-transition{transition:none!important}.plyr__sr-only{clip:rect(1px,1px,1px,1px);overflow:hidden;border:0!important;height:1px!important;padding:0!important;position:absolute!important;width:1px!important}.plyr [hidden]{display:none!important}
\ No newline at end of file diff --git a/dist/plyr.js b/dist/plyr.js index 3e20b389..031ccb1e 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -1,365 +1,71 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('Plyr', factory) : - (global.Plyr = factory()); +typeof navigator === "object" && (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('Plyr', factory) : + (global.Plyr = factory()); }(this, (function () { 'use strict'; -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var loadjs_umd = createCommonjsModule(function (module, exports) { -(function(root, factory) { - if (typeof undefined === 'function' && undefined.amd) { - undefined([], factory); - } else { - module.exports = factory(); + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } } -}(commonjsGlobal, function() { -/** - * Global dependencies. - * @global {Object} document - DOM - */ - -var devnull = function() {}, - bundleIdCache = {}, - bundleResultCache = {}, - bundleCallbackQueue = {}; - -/** - * Subscribe to bundle load event. - * @param {string[]} bundleIds - Bundle ids - * @param {Function} callbackFn - The callback function - */ -function subscribe(bundleIds, callbackFn) { - // listify - bundleIds = bundleIds.push ? bundleIds : [bundleIds]; - - var depsNotFound = [], - i = bundleIds.length, - numWaiting = i, - fn, - bundleId, - r, - q; - - // define callback function - fn = function (bundleId, pathsNotFound) { - if (pathsNotFound.length) depsNotFound.push(bundleId); - - numWaiting--; - if (!numWaiting) callbackFn(depsNotFound); - }; - - // register callback - while (i--) { - bundleId = bundleIds[i]; - - // execute callback if in result cache - r = bundleResultCache[bundleId]; - if (r) { - fn(bundleId, r); - continue; + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); } - - // add to callback queue - q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; - q.push(fn); } -} - - -/** - * Publish bundle load event. - * @param {string} bundleId - Bundle id - * @param {string[]} pathsNotFound - List of files not found - */ -function publish(bundleId, pathsNotFound) { - // exit if id isn't defined - if (!bundleId) return; - - var q = bundleCallbackQueue[bundleId]; - - // cache result - bundleResultCache[bundleId] = pathsNotFound; - - // exit if queue is empty - if (!q) return; - // empty callback queue - while (q.length) { - q[0](bundleId, pathsNotFound); - q.splice(0, 1); - } -} - - -/** - * Execute callbacks. - * @param {Object or Function} args - The callback args - * @param {string[]} depsNotFound - List of dependencies not found - */ -function executeCallbacks(args, depsNotFound) { - // accept function as argument - if (args.call) args = {success: args}; - - // success and error callbacks - if (depsNotFound.length) (args.error || devnull)(depsNotFound); - else (args.success || devnull)(args); -} - - -/** - * Load individual file. - * @param {string} path - The file path - * @param {Function} callbackFn - The callback function - */ -function loadFile(path, callbackFn, args, numTries) { - var doc = document, - async = args.async, - maxTries = (args.numRetries || 0) + 1, - beforeCallbackFn = args.before || devnull, - pathStripped = path.replace(/^(css|img)!/, ''), - isCss, - e; - - numTries = numTries || 0; - - if (/(^css!|\.css$)/.test(path)) { - isCss = true; - - // css - e = doc.createElement('link'); - e.rel = 'stylesheet'; - e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix - } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { - // image - e = doc.createElement('img'); - e.src = pathStripped; - } else { - // javascript - e = doc.createElement('script'); - e.src = path; - e.async = async === undefined ? true : async; + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; } - e.onload = e.onerror = e.onbeforeload = function (ev) { - var result = ev.type[0]; - - // Note: The following code isolates IE using `hideFocus` and treats empty - // stylesheets as failures to get around lack of onerror support - if (isCss && 'hideFocus' in e) { - try { - if (!e.sheet.cssText.length) result = 'e'; - } catch (x) { - // sheets objects created from load errors don't allow access to - // `cssText` - result = 'e'; - } - } - - // handle retries in case of load failure - if (result == 'e') { - // increment counter - numTries += 1; - - // exit function and try again - if (numTries < maxTries) { - return loadFile(path, callbackFn, args, numTries); - } - } - - // execute callback - callbackFn(path, result, ev.defaultPrevented); - }; - - // add to document (unless callback returns `false`) - if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); -} - - -/** - * Load multiple files. - * @param {string[]} paths - The file paths - * @param {Function} callbackFn - The callback function - */ -function loadFiles(paths, callbackFn, args) { - // listify paths - paths = paths.push ? paths : [paths]; - - var numWaiting = paths.length, - x = numWaiting, - pathsNotFound = [], - fn, - i; - - // define callback function - fn = function(path, result, defaultPrevented) { - // handle error - if (result == 'e') pathsNotFound.push(path); - - // handle beforeload event. If defaultPrevented then that means the load - // will be blocked (ex. Ghostery/ABP on Safari) - if (result == 'b') { - if (defaultPrevented) pathsNotFound.push(path); - else return; - } - - numWaiting--; - if (!numWaiting) callbackFn(pathsNotFound); - }; - - // load scripts - for (i=0; i < x; i++) loadFile(paths[i], fn, args); -} - - -/** - * Initiate script load and register bundle. - * @param {(string|string[])} paths - The file paths - * @param {(string|Function)} [arg1] - The bundleId or success callback - * @param {Function} [arg2] - The success or error callback - * @param {Function} [arg3] - The error callback - */ -function loadjs(paths, arg1, arg2) { - var bundleId, - args; - - // bundleId (if string) - if (arg1 && arg1.trim) bundleId = arg1; - - // args (default is {}) - args = (bundleId ? arg2 : arg1) || {}; - - // throw error if bundle is already defined - if (bundleId) { - if (bundleId in bundleIdCache) { - throw "LoadJS"; + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); } else { - bundleIdCache[bundleId] = true; + obj[key] = value; } - } - - // load scripts - loadFiles(paths, function (pathsNotFound) { - // execute callbacks - executeCallbacks(args, pathsNotFound); - - // publish bundle load event - publish(bundleId, pathsNotFound); - }, args); -} - - -/** - * Execute callbacks when dependencies have been satisfied. - * @param {(string|string[])} deps - List of bundle ids - * @param {Object} args - success/error arguments - */ -loadjs.ready = function ready(deps, args) { - // subscribe to bundle load event - subscribe(deps, function (depsNotFound) { - // execute callbacks - executeCallbacks(args, depsNotFound); - }); - - return loadjs; -}; - - -/** - * Manually satisfy bundle dependencies. - * @param {string} bundleId - The bundle id - */ -loadjs.done = function done(bundleId) { - publish(bundleId, []); -}; + return obj; + } -/** - * Reset loadjs dependencies statuses - */ -loadjs.reset = function reset() { - bundleIdCache = {}; - bundleResultCache = {}; - bundleCallbackQueue = {}; -}; - - -/** - * Determine if bundle has already been defined - * @param String} bundleId - The bundle id - */ -loadjs.isDefined = function isDefined(bundleId) { - return bundleId in bundleIdCache; -}; - - -// export -return loadjs; - -})); -}); - -// ========================================================================== -// Plyr supported types and providers -// ========================================================================== - -var providers = { - html5: 'html5', - youtube: 'youtube', - vimeo: 'vimeo' -}; - -var types = { - audio: 'audio', - video: 'video' -}; + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } -}; -var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; } } - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); - -var defineProperty = function (obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; } - return obj; -}; + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } -var slicedToArray = function () { - function sliceIterator(arr, i) { + function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; @@ -376,7 +82,7 @@ var slicedToArray = function () { _e = err; } finally { try { - if (!_n && _i["return"]) _i["return"](); + if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } @@ -385,2342 +91,2020 @@ var slicedToArray = function () { return _arr; } - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; -}(); - -var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } else { - return Array.from(arr); + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); } -}; - -// ========================================================================== - -var utils = { - // Check variable types - is: { - plyr: function plyr(input) { - return this.instanceof(input, window.Plyr); - }, - object: function object(input) { - return this.getConstructor(input) === Object; - }, - number: function number(input) { - return this.getConstructor(input) === Number && !Number.isNaN(input); - }, - string: function string(input) { - return this.getConstructor(input) === String; - }, - boolean: function boolean(input) { - return this.getConstructor(input) === Boolean; - }, - function: function _function(input) { - return this.getConstructor(input) === Function; - }, - array: function array(input) { - return !this.nullOrUndefined(input) && Array.isArray(input); - }, - weakMap: function weakMap(input) { - return this.instanceof(input, window.WeakMap); - }, - nodeList: function nodeList(input) { - return this.instanceof(input, window.NodeList); - }, - element: function element(input) { - return this.instanceof(input, window.Element); - }, - textNode: function textNode(input) { - return this.getConstructor(input) === Text; - }, - event: function event(input) { - return this.instanceof(input, window.Event); - }, - cue: function cue(input) { - return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); - }, - track: function track(input) { - return this.instanceof(input, TextTrack) || !this.nullOrUndefined(input) && this.string(input.kind); - }, - url: function url(input) { - return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input); - }, - nullOrUndefined: function nullOrUndefined(input) { - return input === null || typeof input === 'undefined'; - }, - empty: function empty(input) { - return this.nullOrUndefined(input) || (this.string(input) || this.array(input) || this.nodeList(input)) && !input.length || this.object(input) && !Object.keys(input).length; - }, - instanceof: function _instanceof$$1(input, constructor) { - return Boolean(input && constructor && input instanceof constructor); - }, - getConstructor: function getConstructor(input) { - return !this.nullOrUndefined(input) ? input.constructor : null; - } - }, - - // Unfortunately, due to mixed support, UA sniffing is required - getBrowser: function getBrowser() { - return { - isIE: /* @cc_on!@ */false || !!document.documentMode, - isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), - isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), - isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) - }; - }, - - - // Fetch wrapper - // Using XHR to avoid issues with older browsers - fetch: function fetch(url) { - var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; - - return new Promise(function (resolve, reject) { - try { - var request = new XMLHttpRequest(); - - // Check for CORS support - if (!('withCredentials' in request)) { - return; - } - - request.addEventListener('load', function () { - if (responseType === 'text') { - try { - resolve(JSON.parse(request.responseText)); - } catch (e) { - resolve(request.responseText); - } - } else { - resolve(request.response); - } - }); - - request.addEventListener('error', function () { - throw new Error(request.statusText); - }); - - request.open('GET', url, true); - - // Set the required response type - request.responseType = responseType; - - request.send(); - } catch (e) { - reject(e); - } - }); - }, - - - // Load an external script - loadScript: function loadScript(url) { - return new Promise(function (resolve, reject) { - loadjs_umd(url, { - success: resolve, - error: reject - }); - }); - }, - - - // Load an external SVG sprite - loadSprite: function loadSprite(url, id) { - if (!utils.is.string(url)) { - return; - } - - var prefix = 'cache-'; - var hasId = utils.is.string(id); - var isCached = false; - - var exists = function exists() { - return document.querySelectorAll('#' + id).length; - }; - - function injectSprite(data) { - // Check again incase of race condition - if (hasId && exists()) { - return; - } - - // Inject content - this.innerHTML = data; - - // Inject the SVG to the body - document.body.insertBefore(this, document.body.childNodes[0]); - } - - // Only load once if ID set - if (!hasId || !exists()) { - // Create container - var container = document.createElement('div'); - utils.toggleHidden(container, true); - - if (hasId) { - container.setAttribute('id', id); - } - - // Check in cache - if (support.storage) { - var cached = window.localStorage.getItem(prefix + id); - isCached = cached !== null; - - if (isCached) { - var data = JSON.parse(cached); - injectSprite.call(container, data.content); - return; - } - } - - // Get the sprite - utils.fetch(url).then(function (result) { - if (utils.is.empty(result)) { - return; - } - - if (support.storage) { - window.localStorage.setItem(prefix + id, JSON.stringify({ - content: result - })); - } - - injectSprite.call(container, result); - }).catch(function () {}); - } - }, + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } - // Generate a random ID - generateId: function generateId(prefix) { - return prefix + '-' + Math.floor(Math.random() * 10000); - }, - - - // Wrap an element - wrap: function wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - var targets = elements.length ? elements : [elements]; - - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - Array.from(targets).reverse().forEach(function (element, index) { - var child = index > 0 ? wrapper.cloneNode(true) : wrapper; - - // Cache the current parent and sibling. - var parent = element.parentNode; - var sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - }); - }, - - - // Create a DocumentFragment - createElement: function createElement(type, attributes, text) { - // Create a new <element> - var element = document.createElement(type); - - // Set all passed attributes - if (utils.is.object(attributes)) { - utils.setAttributes(element, attributes); - } - - // Add text node - if (utils.is.string(text)) { - element.textContent = text; - } - - // Return built element - return element; - }, - - - // Inaert an element after another - insertAfter: function insertAfter(element, target) { - target.parentNode.insertBefore(element, target.nextSibling); - }, - - - // Insert a DocumentFragment - insertElement: function insertElement(type, parent, attributes, text) { - // Inject the new <element> - parent.appendChild(utils.createElement(type, attributes, text)); - }, - - - // Remove element(s) - removeElement: function removeElement(element) { - if (utils.is.nodeList(element) || utils.is.array(element)) { - Array.from(element).forEach(utils.removeElement); - return; - } - - if (!utils.is.element(element) || !utils.is.element(element.parentNode)) { - return; - } - - element.parentNode.removeChild(element); - }, - - - // Remove all child elements - emptyElement: function emptyElement(element) { - var length = element.childNodes.length; - - - while (length > 0) { - element.removeChild(element.lastChild); - length -= 1; - } - }, - - - // Replace element - replaceElement: function replaceElement(newChild, oldChild) { - if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) { - return null; - } - - oldChild.parentNode.replaceChild(newChild, oldChild); - - return newChild; - }, - - - // Set attributes - setAttributes: function setAttributes(element, attributes) { - if (!utils.is.element(element) || utils.is.empty(attributes)) { - return; - } - - Object.entries(attributes).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; - - element.setAttribute(key, value); - }); - }, - - - // Get an attribute object from a string selector - getAttributesFromSelector: function getAttributesFromSelector(sel, existingAttributes) { - // For example: - // '.test' to { class: 'test' } - // '#test' to { id: 'test' } - // '[data-test="test"]' to { 'data-test': 'test' } - - if (!utils.is.string(sel) || utils.is.empty(sel)) { - return {}; - } - - var attributes = {}; - var existing = existingAttributes; - - sel.split(',').forEach(function (s) { - // Remove whitespace - var selector = s.trim(); - var className = selector.replace('.', ''); - var stripped = selector.replace(/[[\]]/g, ''); - - // Get the parts and value - var parts = stripped.split('='); - var key = parts[0]; - var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; - - // Get the first character - var start = selector.charAt(0); - - switch (start) { - case '.': - // Add to existing classname - if (utils.is.object(existing) && utils.is.string(existing.class)) { - existing.class += ' ' + className; - } - - attributes.class = className; - break; - - case '#': - // ID selector - attributes.id = selector.replace('#', ''); - break; - - case '[': - // Attribute selector - attributes[key] = value; - - break; - - default: - break; - } - }); - - return attributes; - }, - - - // Toggle hidden - toggleHidden: function toggleHidden(element, hidden) { - if (!utils.is.element(element)) { - return; - } - - var hide = hidden; - - if (!utils.is.boolean(hide)) { - hide = !element.hasAttribute('hidden'); - } - - if (hide) { - element.setAttribute('hidden', ''); - } else { - element.removeAttribute('hidden'); - } - }, - - - // Toggle class on an element - toggleClass: function toggleClass(element, className, toggle) { - if (utils.is.element(element)) { - var contains = element.classList.contains(className); - - element.classList[toggle ? 'add' : 'remove'](className); - - return toggle && !contains || !toggle && contains; - } - - return null; - }, - - - // Has class name - hasClass: function hasClass(element, className) { - return utils.is.element(element) && element.classList.contains(className); - }, - - - // Element matches selector - matches: function matches(element, selector) { - var prototype = { Element: Element }; - - function match() { - return Array.from(document.querySelectorAll(selector)).includes(this); - } - - var matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; - - return matches.call(element, selector); - }, - - - // Find all elements - getElements: function getElements(selector) { - return this.elements.container.querySelectorAll(selector); - }, - - - // Find a single element - getElement: function getElement(selector) { - return this.elements.container.querySelector(selector); - }, - + // ========================================================================== + // Type checking utils + // ========================================================================== + var getConstructor = function getConstructor(input) { + return input !== null && typeof input !== 'undefined' ? input.constructor : null; + }; - // Get the focused element - getFocusElement: function getFocusElement() { - var focused = document.activeElement; + var instanceOf = function instanceOf(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); + }; - if (!focused || focused === document.body) { - focused = null; - } else { - focused = document.querySelector(':focus'); - } + var isNullOrUndefined = function isNullOrUndefined(input) { + return input === null || typeof input === 'undefined'; + }; - return focused; - }, + var isObject = function isObject(input) { + return getConstructor(input) === Object; + }; + var isNumber = function isNumber(input) { + return getConstructor(input) === Number && !Number.isNaN(input); + }; - // Trap focus inside container - trapFocus: function trapFocus() { - var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var isString = function isString(input) { + return getConstructor(input) === String; + }; - if (!utils.is.element(element)) { - return; - } + var isBoolean = function isBoolean(input) { + return getConstructor(input) === Boolean; + }; - var focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); - var first = focusable[0]; - var last = focusable[focusable.length - 1]; + var isFunction = function isFunction(input) { + return getConstructor(input) === Function; + }; - var trap = function trap(event) { - // Bail if not tab key or not fullscreen - if (event.key !== 'Tab' || event.keyCode !== 9) { - return; - } + var isArray = function isArray(input) { + return Array.isArray(input); + }; - // Get the current focused element - var focused = utils.getFocusElement(); - - if (focused === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - first.focus(); - event.preventDefault(); - } else if (focused === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - last.focus(); - event.preventDefault(); - } - }; + var isWeakMap = function isWeakMap(input) { + return instanceOf(input, WeakMap); + }; - if (toggle) { - utils.on(this.elements.container, 'keydown', trap, false); - } else { - utils.off(this.elements.container, 'keydown', trap, false); - } - }, + var isNodeList = function isNodeList(input) { + return instanceOf(input, NodeList); + }; + var isElement = function isElement(input) { + return instanceOf(input, Element); + }; - // Toggle event listener - toggleListener: function toggleListener(elements, event, callback) { - var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; - var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + var isTextNode = function isTextNode(input) { + return getConstructor(input) === Text; + }; - // Bail if no elemetns, event, or callback - if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) { - return; - } + var isEvent = function isEvent(input) { + return instanceOf(input, Event); + }; - // If a nodelist is passed, call itself on each node - if (utils.is.nodeList(elements) || utils.is.array(elements)) { - // Create listener for each node - Array.from(elements).forEach(function (element) { - if (element instanceof Node) { - utils.toggleListener.call(null, element, event, callback, toggle, passive, capture); - } - }); + var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); + }; - return; - } + var isCue = function isCue(input) { + return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); + }; - // Allow multiple events - var events = event.split(' '); + var isTrack = function isTrack(input) { + return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind); + }; - // Build options - // Default to just the capture boolean for browsers with no passive listener support - var options = capture; + var isEmpty = function isEmpty(input) { + return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length; + }; - // If passive events listeners are supported - if (support.passiveListeners) { - options = { - // Whether the listener can be passive (i.e. default never prevented) - passive: passive, - // Whether the listener is a capturing listener or not - capture: capture - }; - } + var isUrl = function isUrl(input) { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } // Must be string from here - // If a single node is passed, bind the event listener - events.forEach(function (type) { - elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); - }); - }, + if (!isString(input)) { + return false; + } // Add the protocol if required - // Bind event handler - on: function on(element) { - var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var callback = arguments[2]; - var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; - var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; - utils.toggleListener(element, events, callback, true, passive, capture); - }, + var string = input; + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = "http://".concat(input); + } - // Unbind event handler - off: function off(element) { - var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var callback = arguments[2]; - var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; - var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } + }; - utils.toggleListener(element, events, callback, false, passive, capture); - }, + var is = { + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty + }; + // ========================================================================== + // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // https://www.youtube.com/watch?v=NPM6172J22g - // Trigger event - dispatchEvent: function dispatchEvent(element) { - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + var supportsPassiveListeners = function () { + // Test via a getter in the options object to see if the passive property is accessed + var supported = false; - // Bail if no element - if (!utils.is.element(element) || utils.is.empty(type)) { - return; - } + try { + var options = Object.defineProperty({}, 'passive', { + get: function get() { + supported = true; + return null; + } + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) {// Do nothing + } - // Create and dispatch the event - var event = new CustomEvent(type, { - bubbles: bubbles, - detail: Object.assign({}, detail, { - plyr: utils.is.plyr(this) ? this : null - }) - }); + return supported; + }(); // Toggle event listener - // Dispatch the event - element.dispatchEvent(event); - }, + function toggleListener(element, event, callback) { + var _this = this; - // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - toggleState: function toggleState(element, input) { - // If multiple elements passed - if (utils.is.array(element) || utils.is.nodeList(element)) { - Array.from(element).forEach(function (target) { - return utils.toggleState(target, input); - }); - return; - } + var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; - // Bail if no target - if (!utils.is.element(element)) { - return; - } + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { + return; + } // Allow multiple events - // Get state - var pressed = element.getAttribute('aria-pressed') === 'true'; - var state = utils.is.boolean(input) ? input : !pressed; - // Set the attribute on target - element.setAttribute('aria-pressed', state); - }, + var events = event.split(' '); // Build options + // Default to just the capture boolean for browsers with no passive listener support + var options = capture; // If passive events listeners are supported - // Format string - format: function format(input) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: passive, + // Whether the listener is a capturing listener or not + capture: capture + }; + } // If a single node is passed, bind the event listener - if (utils.is.empty(input)) { - return input; - } - return input.toString().replace(/{(\d+)}/g, function (match, i) { - return utils.is.string(args[i]) ? args[i] : ''; + events.forEach(function (type) { + if (_this && _this.eventListeners && toggle) { + // Cache event listener + _this.eventListeners.push({ + element: element, + type: type, + callback: callback, + options: options }); - }, - - - // Get percentage - getPercentage: function getPercentage(current, max) { - if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { - return 0; - } - - return (current / max * 100).toFixed(2); - }, - - - // Time helpers - getHours: function getHours(value) { - return parseInt(value / 60 / 60 % 60, 10); - }, - getMinutes: function getMinutes(value) { - return parseInt(value / 60 % 60, 10); - }, - getSeconds: function getSeconds(value) { - return parseInt(value % 60, 10); - }, - - - // Format time to UI friendly string - formatTime: function formatTime() { - var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + } - // Bail if the value isn't a number - if (!utils.is.number(time)) { - return this.formatTime(null, displayHours, inverted); - } + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); + } // Bind event handler + + function on(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, true, passive, capture); + } // Unbind event handler + + function off(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, false, passive, capture); + } // Bind once-only event handler + + function once(element) { + var _this2 = this; + + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + var onceCallback = function onceCallback() { + off(element, events, onceCallback, passive, capture); + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - // Format time component to add leading zero - var format = function format(value) { - return ('0' + value).slice(-2); - }; + callback.apply(_this2, args); + }; + + toggleListener.call(this, element, events, onceCallback, true, passive, capture); + } // Trigger event + + function triggerEvent(element) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + // Bail if no element + if (!is.element(element) || is.empty(type)) { + return; + } // Create and dispatch the event + + + var event = new CustomEvent(type, { + bubbles: bubbles, + detail: Object.assign({}, detail, { + plyr: this + }) + }); // Dispatch the event + + element.dispatchEvent(event); + } // Unbind all cached event listeners + + function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(function (item) { + var element = item.element, + type = item.type, + callback = item.callback, + options = item.options; + element.removeEventListener(type, callback, options); + }); + this.eventListeners = []; + } + } // Run method when / if player is ready - // Breakdown to hours, mins, secs - var hours = this.getHours(time); - var mins = this.getMinutes(time); - var secs = this.getSeconds(time); + function ready() { + var _this3 = this; - // Do we need to display hours? - if (displayHours || hours > 0) { - hours = hours + ':'; - } else { - hours = ''; - } + return new Promise(function (resolve) { + return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve); + }).then(function () {}); + } - // Render - return '' + (inverted ? '-' : '') + hours + format(mins) + ':' + format(secs); - }, + function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + Array.from(targets).reverse().forEach(function (element, index) { + var child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling. - // Replace all occurances of a string in a string - replaceAll: function replaceAll() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + var parent = element.parentNode; + var sibling = element.nextSibling; // Wrap the element (is automatically removed from its current + // parent). - return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); - }, + child.appendChild(element); // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); + } // Set attributes - // Convert to title case - toTitleCase: function toTitleCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + function setAttributes(element, attributes) { + if (!is.element(element) || is.empty(attributes)) { + return; + } // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" - return input.toString().replace(/\w\S*/g, function (text) { - return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); - }); - }, + Object.entries(attributes).filter(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + value = _ref2[1]; - // Convert string to pascalCase - toPascalCase: function toPascalCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return !is.nullOrUndefined(value); + }).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; - var string = input.toString(); + return element.setAttribute(key, value); + }); + } // Create a DocumentFragment - // Convert kebab case - string = utils.replaceAll(string, '-', ' '); + function createElement(type, attributes, text) { + // Create a new <element> + var element = document.createElement(type); // Set all passed attributes - // Convert snake case - string = utils.replaceAll(string, '_', ' '); + if (is.object(attributes)) { + setAttributes(element, attributes); + } // Add text node - // Convert to title case - string = utils.toTitleCase(string); - // Convert to pascal case - return utils.replaceAll(string, ' ', ''); - }, + if (is.string(text)) { + element.innerText = text; + } // Return built element - // Convert string to pascalCase - toCamelCase: function toCamelCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return element; + } // Inaert an element after another - var string = input.toString(); + function insertAfter(element, target) { + if (!is.element(element) || !is.element(target)) { + return; + } - // Convert to pascal case - string = utils.toPascalCase(string); + target.parentNode.insertBefore(element, target.nextSibling); + } // Insert a DocumentFragment - // Convert first character to lowercase - return string.charAt(0).toLowerCase() + string.slice(1); - }, + function insertElement(type, parent, attributes, text) { + if (!is.element(parent)) { + return; + } + parent.appendChild(createElement(type, attributes, text)); + } // Remove element(s) - // Deep extend destination object with N more objects - extend: function extend() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + function removeElement(element) { + if (is.nodeList(element) || is.array(element)) { + Array.from(element).forEach(removeElement); + return; + } - for (var _len2 = arguments.length, sources = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - sources[_key2 - 1] = arguments[_key2]; - } + if (!is.element(element) || !is.element(element.parentNode)) { + return; + } - if (!sources.length) { - return target; - } + element.parentNode.removeChild(element); + } // Remove all child elements - var source = sources.shift(); + function emptyElement(element) { + if (!is.element(element)) { + return; + } - if (!utils.is.object(source)) { - return target; - } + var length = element.childNodes.length; - Object.keys(source).forEach(function (key) { - if (utils.is.object(source[key])) { - if (!Object.keys(target).includes(key)) { - Object.assign(target, defineProperty({}, key, {})); - } + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } + } // Replace element - utils.extend(target[key], source[key]); - } else { - Object.assign(target, defineProperty({}, key, source[key])); - } - }); + function replaceElement(newChild, oldChild) { + if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { + return null; + } - return utils.extend.apply(utils, [target].concat(toConsumableArray(sources))); - }, + oldChild.parentNode.replaceChild(newChild, oldChild); + return newChild; + } // Get an attribute object from a string selector + + function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + if (!is.string(sel) || is.empty(sel)) { + return {}; + } + var attributes = {}; + var existing = existingAttributes; + sel.split(',').forEach(function (s) { + // Remove whitespace + var selector = s.trim(); + var className = selector.replace('.', ''); + var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value - // Remove duplicates in an array - dedupe: function dedupe(array) { - if (!utils.is.array(array)) { - return array; - } + var parts = stripped.split('='); + var key = parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character - return array.filter(function (item, index) { - return array.indexOf(item) === index; - }); - }, + var start = selector.charAt(0); + switch (start) { + case '.': + // Add to existing classname + if (is.object(existing) && is.string(existing.class)) { + existing.class += " ".concat(className); + } - // Get the closest value in an array - closest: function closest(array, value) { - if (!utils.is.array(array) || !array.length) { - return null; - } + attributes.class = className; + break; - return array.reduce(function (prev, curr) { - return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; - }); - }, + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + case '[': + // Attribute selector + attributes[key] = value; + break; - // Get the provider for a given URL - getProviderByUrl: function getProviderByUrl(url) { - // YouTube - if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/.test(url)) { - return providers.youtube; - } + default: + break; + } + }); + return attributes; + } // Toggle hidden - // Vimeo - if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { - return providers.vimeo; - } + function toggleHidden(element, hidden) { + if (!is.element(element)) { + return; + } - return null; - }, + var hide = hidden; + if (!is.boolean(hide)) { + hide = !element.hidden; + } - // Parse YouTube ID from URL - parseYouTubeId: function parseYouTubeId(url) { - if (utils.is.empty(url)) { - return null; - } + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } + } // Mirror Element.classList.toggle, with IE compatibility for "force" argument - var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; - return url.match(regex) ? RegExp.$2 : url; - }, + function toggleClass(element, className, force) { + if (is.nodeList(element)) { + return Array.from(element).map(function (e) { + return toggleClass(e, className, force); + }); + } + if (is.element(element)) { + var method = 'toggle'; - // Parse Vimeo ID from URL - parseVimeoId: function parseVimeoId(url) { - if (utils.is.empty(url)) { - return null; - } + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } - if (utils.is.number(Number(url))) { - return url; - } + element.classList[method](className); + return element.classList.contains(className); + } - var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; - return url.match(regex) ? RegExp.$2 : url; - }, + return false; + } // Has class name + function hasClass(element, className) { + return is.element(element) && element.classList.contains(className); + } // Element matches selector - // Convert a URL to a location object - parseUrl: function parseUrl(url) { - var parser = document.createElement('a'); - parser.href = url; - return parser; - }, + function matches(element, selector) { + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } - // Get URL query parameters - getUrlParams: function getUrlParams(input) { - var search = input; + var matches = match; + return matches.call(element, selector); + } // Find all elements - // Parse URL if needed - if (input.startsWith('http://') || input.startsWith('https://')) { - var _parseUrl = this.parseUrl(input); + function getElements(selector) { + return this.elements.container.querySelectorAll(selector); + } // Find a single element - search = _parseUrl.search; - } + function getElement(selector) { + return this.elements.container.querySelector(selector); + } // Trap focus inside container - if (this.is.empty(search)) { - return null; - } + function trapFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - var hashes = search.slice(search.indexOf('?') + 1).split('&'); + if (!is.element(element)) { + return; + } - return hashes.reduce(function (params, hash) { - var _hash$split = hash.split('='), - _hash$split2 = slicedToArray(_hash$split, 2), - key = _hash$split2[0], - val = _hash$split2[1]; + var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + var first = focusable[0]; + var last = focusable[focusable.length - 1]; - return Object.assign(params, defineProperty({}, key, decodeURIComponent(val))); - }, {}); - }, + var trap = function trap(event) { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } // Get the current focused element - // Convert object to URL parameters - buildUrlParams: function buildUrlParams(input) { - if (!utils.is.object(input)) { - return ''; - } + var focused = document.activeElement; - return Object.keys(input).map(function (key) { - return encodeURIComponent(key) + '=' + encodeURIComponent(input[key]); - }).join('&'); - }, + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); + } // Set focus and tab focus class - // Remove HTML from a string - stripHTML: function stripHTML(source) { - var fragment = document.createDocumentFragment(); - var element = document.createElement('div'); - fragment.appendChild(element); - element.innerHTML = source; - return fragment.firstChild.innerText; - }, + function setFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (!is.element(element)) { + return; + } // Set regular focus - // Get aspect ratio for dimensions - getAspectRatio: function getAspectRatio(width, height) { - var getRatio = function getRatio(w, h) { - return h === 0 ? w : getRatio(h, w % h); - }; - var ratio = getRatio(width, height); - return width / ratio + ':' + height / ratio; - }, + element.focus({ + preventScroll: true + }); // If we want to mimic keyboard focus via tab - // Get the transition end event - get transitionEndEvent() { - var element = document.createElement('span'); + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } + } - var events = { - WebkitTransition: 'webkitTransitionEnd', - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd otransitionend', - transition: 'transitionend' - }; + // ========================================================================== + var transitionEndEvent = function () { + var element = document.createElement('span'); + var events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + var type = Object.keys(events).find(function (event) { + return element.style[event] !== undefined; + }); + return is.string(type) ? events[type] : false; + }(); // Force repaint of element - var type = Object.keys(events).find(function (event) { - return element.style[event] !== undefined; - }); + function repaint(element) { + setTimeout(function () { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line - return utils.is.string(type) ? events[type] : false; - }, + toggleHidden(element, false); + } catch (e) {// Do nothing + } + }, 0); + } - // Force repaint of element - repaint: function repaint(element) { - setTimeout(function () { - utils.toggleHidden(element, true); - element.offsetHeight; // eslint-disable-line - utils.toggleHidden(element, false); - }, 0); - } -}; + // ========================================================================== + // Browser sniffing + // Unfortunately, due to mixed support, UA sniffing is required + // ========================================================================== + var browser = { + isIE: + /* @cc_on!@ */ + !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) + }; -// ========================================================================== + var defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora' + }; // Check for feature support -// Check for feature support -var support = { + var support = { // Basic support audio: 'canPlayType' in document.createElement('audio'), video: 'canPlayType' in document.createElement('video'), - // Check for support // Basic functionality vs full UI check: function check(type, provider, playsinline) { - var api = false; - var ui = false; - var browser = utils.getBrowser(); - var canPlayInline = browser.isIPhone && playsinline && support.playsinline; - - switch (provider + ':' + type) { - case 'html5:video': - api = support.video; - ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline); - break; - - case 'html5:audio': - api = support.audio; - ui = api && support.rangeInput; - break; + var canPlayInline = browser.isIPhone && playsinline && support.playsinline; + var api = support[type] || provider !== 'html5'; + var ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); + return { + api: api, + ui: ui + }; + }, + // Picture-in-picture support + // Safari & Chrome only currently + pip: function () { + if (browser.isIPhone) { + return false; + } // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls - case 'youtube:video': - case 'vimeo:video': - api = true; - ui = support.rangeInput && (!browser.isIPhone || canPlayInline); - break; - default: - api = support.audio && support.video; - ui = api && support.rangeInput; - } + if (is.function(createElement('video').webkitSetPresentationMode)) { + return true; + } // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture - return { - api: api, - ui: ui - }; - }, + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } - // Picture-in-picture support - // Safari only currently - pip: function () { - var browser = utils.getBrowser(); - return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode); + return false; }(), - // Airplay support // Safari only currently - airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent), - + airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent), // Inline playback support // https://webkit.org/blog/6784/new-video-policies-for-ios/ playsinline: 'playsInline' in document.createElement('video'), - // Check for mime type support against a player instance // Credits: http://diveintohtml5.info/everything.html // Related: http://www.leanbackplayer.com/test/h5mt.html - mime: function mime(type) { - var media = this.media; - - - try { - // Bail if no checking function - if (!this.isHTML5 || !utils.is.function(media.canPlayType)) { - return false; - } - - // Check directly if codecs specified - if (type.includes('codecs=')) { - return media.canPlayType(type).replace(/no/, ''); - } - - // Type specific checks - if (this.isVideo) { - switch (type) { - case 'video/webm': - return media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''); - - case 'video/mp4': - return media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''); + mime: function mime(input) { + if (is.empty(input)) { + return false; + } - case 'video/ogg': - return media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''); + var _input$split = input.split('/'), + _input$split2 = _slicedToArray(_input$split, 1), + mediaType = _input$split2[0]; - default: - return false; - } - } else if (this.isAudio) { - switch (type) { - case 'audio/mpeg': - return media.canPlayType('audio/mpeg;').replace(/no/, ''); + var type = input; // Verify we're using HTML5 and there's no media type mismatch - case 'audio/ogg': - return media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''); + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } // Add codec if required - case 'audio/wav': - return media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''); - default: - return false; - } - } - } catch (e) { - return false; - } + if (Object.keys(defaultCodecs).includes(type)) { + type += "; codecs=\"".concat(defaultCodecs[input], "\""); + } - // If we got this far, we're stuffed + try { + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); + } catch (e) { return false; + } }, - - // Check for textTracks support textTracks: 'textTracks' in document.createElement('video'), - - // Check for passive event listener support - // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - // https://www.youtube.com/watch?v=NPM6172J22g - passiveListeners: function () { - // Test via a getter in the options object to see if the passive property is accessed - var supported = false; - try { - var options = Object.defineProperty({}, 'passive', { - get: function get() { - supported = true; - return null; - } - }); - window.addEventListener('test', null, options); - } catch (e) { - // Do nothing - } - - return supported; - }(), - // <input type="range"> Sliders rangeInput: function () { - var range = document.createElement('input'); - range.type = 'range'; - return range.type === 'range'; + var range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; }(), - // Touch // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event touch: 'ontouchstart' in document.documentElement, - // Detect transitions support - transitions: utils.transitionEndEvent !== false, - + transitions: transitionEndEvent !== false, // Reduced motion iOS & MacOS setting // https://webkit.org/blog/7551/responsive-design-for-motion/ reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches -}; - -// ========================================================================== + }; -var html5 = { + // ========================================================================== + var html5 = { getSources: function getSources() { - if (!this.isHTML5) { - return null; - } - - return this.media.querySelectorAll('source'); - }, + var _this = this; + if (!this.isHTML5) { + return []; + } - // Get quality levels - getQualityOptions: function getQualityOptions() { - if (!this.isHTML5) { - return null; - } - - // Get sources - var sources = html5.getSources.call(this); - - if (utils.is.empty(sources)) { - return null; - } + var sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified) - // Get <source> with size attribute - var sizes = Array.from(sources).filter(function (source) { - return !utils.is.empty(source.getAttribute('size')); - }); + return sources.filter(function (source) { + var type = source.getAttribute('type'); - // If none, bail - if (utils.is.empty(sizes)) { - return null; + if (is.empty(type)) { + return true; } - // Reduce to unique list - return utils.dedupe(sizes.map(function (source) { - return Number(source.getAttribute('size')); - })); + return support.mime.call(_this, type); + }); + }, + // Get quality levels + getQualityOptions: function getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources.call(this).map(function (source) { + return Number(source.getAttribute('size')); + }).filter(Boolean); }, extend: function extend() { - if (!this.isHTML5) { - return; - } - - var player = this; - - // Quality - Object.defineProperty(player.media, 'quality', { - get: function get() { - // Get sources - var sources = html5.getSources.call(player); - - if (utils.is.empty(sources)) { - return null; - } - - var matches = Array.from(sources).filter(function (source) { - return source.getAttribute('src') === player.source; - }); - - if (utils.is.empty(matches)) { - return null; - } - - return Number(matches[0].getAttribute('size')); - }, - set: function set(input) { - // Get sources - var sources = html5.getSources.call(player); + if (!this.isHTML5) { + return; + } - if (utils.is.empty(sources)) { - return; - } + var player = this; // Quality - // Get matches for requested size - var matches = Array.from(sources).filter(function (source) { - return Number(source.getAttribute('size')) === input; - }); + Object.defineProperty(player.media, 'quality', { + get: function get() { + // Get sources + var sources = html5.getSources.call(player); + var source = sources.find(function (source) { + return source.getAttribute('src') === player.source; + }); // Return size, if match is found - // No matches for requested size - if (utils.is.empty(matches)) { - return; - } + return source && Number(source.getAttribute('size')); + }, + set: function set(input) { + // Get sources + var sources = html5.getSources.call(player); // Get first match for requested size - // Get supported sources - var supported = matches.filter(function (source) { - return support.mime.call(player, source.getAttribute('type')); - }); + var source = sources.find(function (source) { + return Number(source.getAttribute('size')) === input; + }); // No matching source found - // No supported sources - if (utils.is.empty(supported)) { - return; - } + if (!source) { + return; + } // Get current state - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality: input - }); - // Get current state - var currentTime = player.currentTime, - playing = player.playing; + var _player$media = player.media, + currentTime = _player$media.currentTime, + paused = _player$media.paused, + preload = _player$media.preload, + readyState = _player$media.readyState; // Set new source - // Set new source + player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044) - player.media.src = supported[0].getAttribute('src'); + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', function () { + player.currentTime = currentTime; // Resume playing - // Load new source - player.media.load(); + if (!paused) { + player.play(); + } + }); // Load new source - // Resume playing - if (playing) { - player.play(); - } + player.media.load(); + } // Trigger change event - // Restore time - player.currentTime = currentTime; - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { - quality: input - }); - } - }); + triggerEvent.call(player, player.media, 'qualitychange', false, { + quality: input + }); + } + }); }, - - // Cancel current network requests // See https://github.com/sampotts/plyr/issues/174 cancelRequests: function cancelRequests() { - if (!this.isHTML5) { - return; - } - - // Remove child sources - utils.removeElement(html5.getSources()); - - // Set blank video src attribute - // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error - // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection - this.media.setAttribute('src', this.config.blankVideo); - - // Load the new empty source - // This will cancel existing requests - // See https://github.com/sampotts/plyr/issues/174 - this.media.load(); - - // Debugging - this.debug.log('Cancelled network requests'); - } -}; + if (!this.isHTML5) { + return; + } // Remove child sources -// ========================================================================== -var i18n = { - get: function get$$1() { - var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + removeElement(html5.getSources.call(this)); // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection - if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) { - return ''; - } + this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 - var string = config.i18n[key]; - - var replace = { - '{seektime}': config.seekTime, - '{title}': config.title - }; + this.media.load(); // Debugging - Object.entries(replace).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + this.debug.log('Cancelled network requests'); + } + }; - string = utils.replaceAll(string, key, value); - }); + // ========================================================================== - return string; + function dedupe(array) { + if (!is.array(array)) { + return array; } -}; - -// ========================================================================== -// Sniff out the browser -var browser = utils.getBrowser(); + return array.filter(function (item, index) { + return array.indexOf(item) === index; + }); + } // Get the closest value in an array -var ui = { - addStyleHook: function addStyleHook() { - utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); - utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); - }, + function closest(array, value) { + if (!is.array(array) || !array.length) { + return null; + } + return array.reduce(function (prev, curr) { + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); + } - // Toggle native HTML5 media controls - toggleNativeControls: function toggleNativeControls() { - var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); + } // Get a nested value in an object - if (toggle && this.isHTML5) { - this.media.setAttribute('controls', ''); - } else { - this.media.removeAttribute('controls'); - } - }, + function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); + } // Deep extend destination object with N more objects + function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - // Setup the UI - build: function build() { - var _this = this; + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } - // Re-attach media element listeners - // TODO: Use event bubbling? - this.listeners.media(); + if (!sources.length) { + return target; + } - // Don't setup interface if no support - if (!this.supported.ui) { - this.debug.warn('Basic support only for ' + this.provider + ' ' + this.type); + var source = sources.shift(); - // Restore native controls - ui.toggleNativeControls.call(this, true); + if (!is.object(source)) { + return target; + } - // Bail - return; + Object.keys(source).forEach(function (key) { + if (is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); } - // Inject custom controls if not present - if (!utils.is.element(this.elements.controls)) { - // Inject custom controls - controls.inject.call(this); + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); + } + }); + return extend.apply(void 0, [target].concat(sources)); + } - // Re-attach control listeners - this.listeners.controls(); - } + // ========================================================================== - // Remove native controls - ui.toggleNativeControls.call(this); + function generateId(prefix) { + return "".concat(prefix, "-").concat(Math.floor(Math.random() * 10000)); + } // Format string - // Captions - captions.setup.call(this); + function format(input) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } - // Reset volume - this.volume = null; + if (is.empty(input)) { + return input; + } - // Reset mute state - this.muted = null; + return input.toString().replace(/{(\d+)}/g, function (match, i) { + return args[i].toString(); + }); + } // Get percentage - // Reset speed - this.speed = null; + function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } - // Reset loop state - this.loop = null; + return (current / max * 100).toFixed(2); + } // Replace all occurances of a string in a string - // Reset quality setting - this.quality = null; + function replaceAll() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); + } // Convert to title case - // Reset volume display - ui.updateVolume.call(this); + function toTitleCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return input.toString().replace(/\w\S*/g, function (text) { + return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); + }); + } // Convert string to pascalCase - // Reset time display - ui.timeUpdate.call(this); + function toPascalCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert kebab case - // Update the UI - ui.checkPlaying.call(this); + string = replaceAll(string, '-', ' '); // Convert snake case - // Check for picture-in-picture support - utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); + string = replaceAll(string, '_', ' '); // Convert to title case - // Check for airplay support - utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); + string = toTitleCase(string); // Convert to pascal case - // Add iOS class - utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); + return replaceAll(string, ' ', ''); + } // Convert string to pascalCase - // Add touch class - utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); + function toCamelCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert to pascal case - // Ready for API calls - this.ready = true; + string = toPascalCase(string); // Convert first character to lowercase - // Ready event at end of execution stack - setTimeout(function () { - utils.dispatchEvent.call(_this, _this.media, 'ready'); - }, 0); + return string.charAt(0).toLowerCase() + string.slice(1); + } // Remove HTML from a string - // Set the title - ui.setTitle.call(this); + function stripHTML(source) { + var fragment = document.createDocumentFragment(); + var element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; + } // Like outerHTML, but also works for DocumentFragment - // Set the poster image - ui.setPoster.call(this); - }, + function getHTML(element) { + var wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; + } + var resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube' + }; + var i18n = { + get: function get() { + var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - // Setup aria attribute for play and iframe title - setTitle: function setTitle() { - // Find the current text - var label = i18n.get('play', this.config); + if (is.empty(key) || is.empty(config)) { + return ''; + } - // If there's a media title set, use that for the label - if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) { - label += ', ' + this.config.title; + var string = getDeep(config.i18n, key); - // Set container label - this.elements.container.setAttribute('aria-label', this.config.title); + if (is.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; } - // If there's a play button, set label - if (utils.is.nodeList(this.elements.buttons.play)) { - Array.from(this.elements.buttons.play).forEach(function (button) { - button.setAttribute('aria-label', label); - }); - } + return ''; + } - // Set iframe title - // https://github.com/sampotts/plyr/issues/124 - if (this.isEmbed) { - var iframe = utils.getElement.call(this, 'iframe'); + var replace = { + '{seektime}': config.seekTime, + '{title}': config.title + }; + Object.entries(replace).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + string = replaceAll(string, key, value); + }); + return string; + } + }; - if (!utils.is.element(iframe)) { - return; - } + var Storage = + /*#__PURE__*/ + function () { + function Storage(player) { + _classCallCheck(this, Storage); - // Default to media type - var title = !utils.is.empty(this.config.title) ? this.config.title : 'video'; - var format = i18n.get('frameTitle', this.config); + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } // Check for actual support (see if we can use it) - iframe.setAttribute('title', format.replace('{title}', title)); + + _createClass(Storage, [{ + key: "get", + value: function get(key) { + if (!Storage.supported || !this.enabled) { + return null; } - }, + var store = window.localStorage.getItem(this.key); - // Set the poster image - setPoster: function setPoster() { - if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) { - return; + if (is.empty(store)) { + return null; } - // Set the inline style - var posters = this.poster.split(','); - this.elements.poster.style.backgroundImage = posters.map(function (p) { - return 'url(\'' + p + '\')'; - }).join(','); - }, + var json = JSON.parse(store); + return is.string(key) && key.length ? json[key] : json; + } + }, { + key: "set", + value: function set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } // Can only store objectst - // Check playing state - checkPlaying: function checkPlaying(event) { - // Class hooks - utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing); - utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused); - utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); + if (!is.object(object)) { + return; + } // Get current storage - // Set ARIA state - utils.toggleState(this.elements.buttons.play, this.playing); - // Only update controls on non timeupdate events - if (utils.is.event(event) && event.type === 'timeupdate') { - return; - } + var storage = this.get(); // Default to empty object - // Toggle controls - this.toggleControls(!this.playing); - }, + if (is.empty(storage)) { + storage = {}; + } // Update the working copy of the values - // Check if media is loading - checkLoading: function checkLoading(event) { - var _this2 = this; + extend(storage, object); // Update storage - this.loading = ['stalled', 'waiting'].includes(event.type); + window.localStorage.setItem(this.key, JSON.stringify(storage)); + } + }], [{ + key: "supported", + get: function get() { + try { + if (!('localStorage' in window)) { + return false; + } - // Clear timer - clearTimeout(this.timers.loading); + var test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 - // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(function () { - // Toggle container class hook - utils.toggleClass(_this2.elements.container, _this2.config.classNames.loading, _this2.loading); + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + } + }]); - // Show controls if loading, hide if done - _this2.toggleControls(_this2.loading); - }, this.loading ? 250 : 0); - }, + return Storage; + }(); + + // ========================================================================== + // Fetch wrapper + // Using XHR to avoid issues with older browsers + // ========================================================================== + function fetch(url) { + var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + return new Promise(function (resolve, reject) { + try { + var request = new XMLHttpRequest(); // Check for CORS support + if (!('withCredentials' in request)) { + return; + } - // Check if media failed to load - checkFailed: function checkFailed() { - var _this3 = this; + request.addEventListener('load', function () { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); + request.addEventListener('error', function () { + throw new Error(request.status); + }); + request.open('GET', url, true); // Set the required response type - // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState - this.failed = this.media.networkState === 3; + request.responseType = responseType; + request.send(); + } catch (e) { + reject(e); + } + }); + } - if (this.failed) { - utils.toggleClass(this.elements.container, this.config.classNames.loading, false); - utils.toggleClass(this.elements.container, this.config.classNames.error, true); - } + // ========================================================================== - // Clear timer - clearTimeout(this.timers.failed); + function loadSprite(url, id) { + if (!is.string(url)) { + return; + } - // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(function () { - // Toggle container class hook - utils.toggleClass(_this3.elements.container, _this3.config.classNames.loading, _this3.loading); + var prefix = 'cache'; + var hasId = is.string(id); + var isCached = false; - // Show controls if loading, hide if done - _this3.toggleControls(_this3.loading); - }, this.loading ? 250 : 0); - }, + var exists = function exists() { + return document.getElementById(id) !== null; + }; + var update = function update(container, data) { + container.innerHTML = data; // Check again incase of race condition - // Update volume UI and storage - updateVolume: function updateVolume() { - if (!this.supported.ui) { - return; - } + if (hasId && exists()) { + return; + } // Inject the SVG to the body - // Update range - if (utils.is.element(this.elements.inputs.volume)) { - ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); - } - // Update mute state - if (utils.is.element(this.elements.buttons.mute)) { - utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); - } - }, + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set - // Update seek value and lower fill - setRange: function setRange(target) { - var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + if (!hasId || !exists()) { + var useStorage = Storage.supported; // Create container - if (!utils.is.element(target)) { - return; - } + var container = document.createElement('div'); + container.setAttribute('hidden', ''); - // eslint-disable-next-line - target.value = value; + if (hasId) { + container.setAttribute('id', id); + } // Check in cache - // Webkit range fill - controls.updateRangeFill.call(this, target); - }, + if (useStorage) { + var cached = window.localStorage.getItem("".concat(prefix, "-").concat(id)); + isCached = cached !== null; - // Set <progress> value - setProgress: function setProgress(target, input) { - var value = utils.is.number(input) ? input : 0; - var progress = utils.is.element(target) ? target : this.elements.display.buffer; + if (isCached) { + var data = JSON.parse(cached); + update(container, data.content); + } + } // Get the sprite - // Update value and label - if (utils.is.element(progress)) { - progress.value = value; - // Update text label inside - var label = progress.getElementsByTagName('span')[0]; - if (utils.is.element(label)) { - label.childNodes[0].nodeValue = value; - } + fetch(url).then(function (result) { + if (is.empty(result)) { + return; } - }, - - // Update <progress> elements - updateProgress: function updateProgress(event) { - if (!this.supported.ui || !utils.is.event(event)) { - return; + if (useStorage) { + window.localStorage.setItem("".concat(prefix, "-").concat(id), JSON.stringify({ + content: result + })); } - var value = 0; + update(container, result); + }).catch(function () {}); + } + } - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - value = utils.getPercentage(this.currentTime, this.duration); + // ========================================================================== - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate') { - ui.setRange.call(this, this.elements.inputs.seek, value); - } + var getHours = function getHours(value) { + return Math.trunc(value / 60 / 60 % 60, 10); + }; + var getMinutes = function getMinutes(value) { + return Math.trunc(value / 60 % 60, 10); + }; + var getSeconds = function getSeconds(value) { + return Math.trunc(value % 60, 10); + }; // Format time to UI friendly string - break; + function formatTime() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - // Check buffer status - case 'playing': - case 'progress': - ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100); + // Bail if the value isn't a number + if (!is.number(time)) { + return formatTime(null, displayHours, inverted); + } // Format time component to add leading zero - break; - default: - break; - } - } - }, + var format = function format(value) { + return "0".concat(value).slice(-2); + }; // Breakdown to hours, mins, secs - // Update the displayed time - updateTimeDisplay: function updateTimeDisplay() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var hours = getHours(time); + var mins = getMinutes(time); + var secs = getSeconds(time); // Do we need to display hours? - // Bail if there's no element to display or the value isn't a number - if (!utils.is.element(target) || !utils.is.number(time)) { - return; - } + if (displayHours || hours > 0) { + hours = "".concat(hours, ":"); + } else { + hours = ''; + } // Render - // Always display hours if duration is over an hour - var forceHours = utils.getHours(this.duration) > 0; - // eslint-disable-next-line no-param-reassign - target.textContent = utils.formatTime(time, forceHours, inverted); + return "".concat(inverted && time > 0 ? '-' : '').concat(hours).concat(format(mins), ":").concat(format(secs)); + } + + var controls = { + // Get icon URL + getIconUrl: function getIconUrl() { + var url = new URL(this.config.iconUrl, window.location); + var cors = url.host !== window.location.host || browser.isIE && !window.svg4everybody; + return { + url: this.config.iconUrl, + cors: cors + }; + }, + // Find the UI controls + findElements: function findElements() { + try { + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons + + this.elements.buttons = { + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen) + }; // Progress + + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs + + this.elements.inputs = { + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume) + }; // Display + + this.elements.display = { + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration) + }; // Seek tooltip + + if (is.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip)); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls + + this.toggleNativeControls(true); + return false; + } }, + // Create <svg> icon + createIcon: function createIcon(type, attributes) { + var namespace = 'http://www.w3.org/2000/svg'; + var iconUrl = controls.getIconUrl.call(this); + var iconPath = "".concat(!iconUrl.cors ? iconUrl.url : '', "#").concat(this.config.iconPrefix); // Create <svg> + var icon = document.createElementNS(namespace, 'svg'); + setAttributes(icon, extend(attributes, { + role: 'presentation', + focusable: 'false' + })); // Create the <use> to reference sprite - // Handle time change event - timeUpdate: function timeUpdate(event) { - // Only invert if only one time element is displayed and used for both duration and currentTime - var invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime; + var use = document.createElementNS(namespace, 'use'); + var path = "".concat(iconPath, "-").concat(type); // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href - // Duration - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } // Always set the older attribute even though it's "deprecated" (it'll be around for ages) - // Ignore updates while seeking - if (event && event.type === 'timeupdate' && this.media.seeking) { - return; - } - // Playing progress - ui.updateProgress.call(this, event); + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg> + + icon.appendChild(use); + return icon; + }, + // Create hidden text label + createLabel: function createLabel(key) { + var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var text = i18n.get(key, this.config); + var attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') + }); + return createElement('span', attributes, text); }, + // Create a badge + createBadge: function createBadge(text) { + if (is.empty(text)) { + return null; + } + var badge = createElement('span', { + class: this.config.classNames.menu.value + }); + badge.appendChild(createElement('span', { + class: this.config.classNames.menu.badge + }, text)); + return badge; + }, + // Create a <button> + createButton: function createButton(buttonType, attr) { + var attributes = Object.assign({}, attr); + var type = toCamelCase(buttonType); + var props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null + }; + ['element', 'icon', 'label'].forEach(function (key) { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); // Default to 'button' type to prevent form submission + + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { + attributes.type = 'button'; + } // Set class name + + + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { + attributes.class += " ".concat(this.config.classNames.control); + } + } else { + attributes.class = this.config.classNames.control; + } // Large play button + + + switch (buttonType) { + case 'play': + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; + break; + + case 'mute': + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; + break; + + case 'captions': + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; + break; + + case 'fullscreen': + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; + break; + + case 'play-large': + attributes.class += " ".concat(this.config.classNames.control, "--overlaid"); + type = 'play'; + props.label = 'play'; + props.icon = 'play'; + break; - // Show the duration on metadataloaded - durationUpdate: function durationUpdate() { - if (!this.supported.ui) { - return; - } + default: + if (is.empty(props.label)) { + props.label = type; + } - // If there's a spot to display duration - var hasDuration = utils.is.element(this.elements.display.duration); + if (is.empty(props.icon)) { + props.icon = buttonType; + } - // If there's only one time display, display duration there - if (!hasDuration && this.config.displayDuration && this.paused) { - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); - } + } - // If there's a duration element, update content - if (hasDuration) { - ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); - } + var button = createElement(props.element); // Setup toggle icon and labels - // Update the tooltip (if visible) - controls.updateSeekTooltip.call(this); - } -}; + if (props.toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed' + })); + button.appendChild(controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed' + })); // Label/Tooltip -// ========================================================================== + button.appendChild(controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed' + })); + button.appendChild(controls.createLabel.call(this, props.label, { + class: 'label--not-pressed' + })); + } else { + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); + } // Merge and set attributes -// Sniff out the browser -var browser$1 = utils.getBrowser(); -var controls = { - // Webkit polyfill for lower fill range - updateRangeFill: function updateRangeFill(target) { - // Get range from event if event passed - var range = utils.is.event(target) ? target.target : target; + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons - // Needs to be a valid <input type='range'> - if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { - return; + if (type === 'play') { + if (!is.array(this.elements.buttons[type])) { + this.elements.buttons[type] = []; } - // Set aria value for https://github.com/sampotts/plyr/issues/905 - range.setAttribute('aria-valuenow', range.value); + this.elements.buttons[type].push(button); + } else { + this.elements.buttons[type] = button; + } - // WebKit only - if (!browser$1.isWebkit) { - return; - } + return button; + }, + // Create an <input type='range'> + createRange: function createRange(type, attributes) { + // Seek input + var input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + // A11y fixes for https://github.com/sampotts/plyr/issues/905 + role: 'slider', + 'aria-label': i18n.get(type, this.config), + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'aria-valuenow': 0 + }, attributes)); + this.elements.inputs[type] = input; // Set the fill for webkit now + + controls.updateRangeFill.call(this, input); + return input; + }, + // Create a <progress> + createProgress: function createProgress(type, attributes) { + var progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), { + min: 0, + max: 100, + value: 0, + role: 'presentation', + 'aria-hidden': true + }, attributes)); // Create the label inside + + if (type !== 'volume') { + progress.appendChild(createElement('span', null, '0')); + var suffixKey = { + played: 'played', + buffer: 'buffered' + }[type]; + var suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; + progress.innerText = "% ".concat(suffix.toLowerCase()); + } - // Set CSS custom property - range.style.setProperty('--value', range.value / range.max * 100 + '%'); + this.elements.display[type] = progress; + return progress; + }, + // Create time display + createTime: function createTime(type) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + var container = createElement('div', extend(attributes, { + class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-label': i18n.get(type, this.config) + }), '00:00'); // Reference for updates + + this.elements.display[type] = container; + return container; }, + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { + var _this = this; + // Navigate through menus via arrow keys and space + on(menuItem, 'keydown keyup', function (event) { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } // Prevent play / seek - // Get icon URL - getIconUrl: function getIconUrl() { - var url = new URL(this.config.iconUrl, window.location); - var cors = url.host !== window.location.host || browser$1.isIE && !window.svg4everybody; - return { - url: this.config.iconUrl, - cors: cors - }; - }, + event.preventDefault(); + event.stopPropagation(); // We're just here to prevent the keydown bubbling + if (event.type === 'keydown') { + return; + } - // Find the UI controls and store references in custom controls - // TODO: Allow settings menus with custom controls - findElements: function findElements() { - try { - this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper); - - // Buttons - this.elements.buttons = { - play: utils.getElements.call(this, this.config.selectors.buttons.play), - pause: utils.getElement.call(this, this.config.selectors.buttons.pause), - restart: utils.getElement.call(this, this.config.selectors.buttons.restart), - rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind), - fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward), - mute: utils.getElement.call(this, this.config.selectors.buttons.mute), - pip: utils.getElement.call(this, this.config.selectors.buttons.pip), - airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay), - settings: utils.getElement.call(this, this.config.selectors.buttons.settings), - captions: utils.getElement.call(this, this.config.selectors.buttons.captions), - fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen) - }; + var isRadioButton = matches(menuItem, '[role="menuitemradio"]'); // Show the respective menu - // Progress - this.elements.progress = utils.getElement.call(this, this.config.selectors.progress); + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(_this, type, true); + } else { + var target; - // Inputs - this.elements.inputs = { - seek: utils.getElement.call(this, this.config.selectors.inputs.seek), - volume: utils.getElement.call(this, this.config.selectors.inputs.volume) - }; + if (event.which !== 32) { + if (event.which === 40 || isRadioButton && event.which === 39) { + target = menuItem.nextElementSibling; - // Display - this.elements.display = { - buffer: utils.getElement.call(this, this.config.selectors.display.buffer), - currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime), - duration: utils.getElement.call(this, this.config.selectors.display.duration) - }; + if (!is.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; - // Seek tooltip - if (utils.is.element(this.elements.progress)) { - this.elements.display.seekTooltip = this.elements.progress.querySelector('.' + this.config.classNames.tooltip); + if (!is.element(target)) { + target = menuItem.parentNode.lastElementChild; + } } - return true; - } catch (error) { - // Log it - this.debug.warn('It looks like there is a problem with your custom controls HTML', error); - - // Restore native video controls - this.toggleNativeControls(true); + setFocus.call(_this, target, true); + } + } + }, false); // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here - return false; + on(menuItem, 'keyup', function (event) { + if (event.which !== 13) { + return; } - }, + controls.focusFirstMenuItem.call(_this, null, true); + }); + }, + // Create a settings menu item + createMenuItem: function createMenuItem(_ref) { + var _this2 = this; + + var value = _ref.value, + list = _ref.list, + type = _ref.type, + title = _ref.title, + _ref$badge = _ref.badge, + badge = _ref$badge === void 0 ? null : _ref$badge, + _ref$checked = _ref.checked, + checked = _ref$checked === void 0 ? false : _ref$checked; + var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + var menuItem = createElement('button', extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: "".concat(this.config.classNames.control, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-checked': checked, + value: value + })); + var flex = createElement('span'); // We have to set as HTML incase of special characters + + flex.innerHTML = title; + + if (is.element(badge)) { + flex.appendChild(badge); + } - // Create <svg> icon - createIcon: function createIcon(type, attributes) { - var namespace = 'http://www.w3.org/2000/svg'; - var iconUrl = controls.getIconUrl.call(this); - var iconPath = (!iconUrl.cors ? iconUrl.url : '') + '#' + this.config.iconPrefix; - - // Create <svg> - var icon = document.createElementNS(namespace, 'svg'); - utils.setAttributes(icon, utils.extend(attributes, { - role: 'presentation', - focusable: 'false' - })); + menuItem.appendChild(flex); // Replicate radio button behaviour - // Create the <use> to reference sprite - var use = document.createElementNS(namespace, 'use'); - var path = iconPath + '-' + type; + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get: function get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set: function set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children).filter(function (node) { + return matches(node, '[role="menuitemradio"]'); + }).forEach(function (node) { + return node.setAttribute('aria-checked', 'false'); + }); + } - // Set `href` attributes - // https://github.com/sampotts/plyr/issues/460 - // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href - if ('href' in use) { - use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); - } else { - use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + } + }); + this.listeners.bind(menuItem, 'click keyup', function (event) { + if (is.keyboardEvent(event) && event.which !== 32) { + return; } - // Add <use> to <svg> - icon.appendChild(use); - - return icon; - }, - - - // Create hidden text label - createLabel: function createLabel(type, attr) { - var text = i18n.get(type, this.config); - var attributes = Object.assign({}, attr); + event.preventDefault(); + event.stopPropagation(); + menuItem.checked = true; switch (type) { - case 'pip': - text = 'PIP'; - break; + case 'language': + _this2.currentTrack = Number(value); + break; - case 'airplay': - text = 'AirPlay'; - break; + case 'quality': + _this2.quality = value; + break; - default: - break; - } + case 'speed': + _this2.speed = parseFloat(value); + break; - if ('class' in attributes) { - attributes.class += ' ' + this.config.classNames.hidden; - } else { - attributes.class = this.config.classNames.hidden; + default: + break; } - return utils.createElement('span', attributes, text); + controls.showMenuPanel.call(_this2, 'home', is.keyboardEvent(event)); + }, type, false); + controls.bindMenuItemShortcuts.call(this, menuItem, type); + list.appendChild(menuItem); }, + // Format a time for display + formatTime: function formatTime$$1() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + // Bail if the value isn't a number + if (!is.number(time)) { + return time; + } // Always display hours if duration is over an hour - // Create a badge - createBadge: function createBadge(text) { - if (utils.is.empty(text)) { - return null; - } - - var badge = utils.createElement('span', { - class: this.config.classNames.menu.value - }); - - badge.appendChild(utils.createElement('span', { - class: this.config.classNames.menu.badge - }, text)); - return badge; + var forceHours = getHours(this.duration) > 0; + return formatTime(time, forceHours, inverted); }, + // Update the displayed time + updateTimeDisplay: function updateTimeDisplay() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + // Bail if there's no element to display or the value isn't a number + if (!is.element(target) || !is.number(time)) { + return; + } // eslint-disable-next-line no-param-reassign - // Create a <button> - createButton: function createButton(buttonType, attr) { - var button = utils.createElement('button'); - var attributes = Object.assign({}, attr); - var type = utils.toCamelCase(buttonType); - - var toggle = false; - var label = void 0; - var icon = void 0; - var labelPressed = void 0; - var iconPressed = void 0; - - if (!('type' in attributes)) { - attributes.type = 'button'; - } - if ('class' in attributes) { - if (attributes.class.includes(this.config.classNames.control)) { - attributes.class += ' ' + this.config.classNames.control; - } - } else { - attributes.class = this.config.classNames.control; - } + target.innerText = controls.formatTime(time, inverted); + }, + // Update volume UI and storage + updateVolume: function updateVolume() { + if (!this.supported.ui) { + return; + } // Update range - // Large play button - switch (buttonType) { - case 'play': - toggle = true; - label = 'play'; - labelPressed = 'pause'; - icon = 'play'; - iconPressed = 'pause'; - break; - case 'mute': - toggle = true; - label = 'mute'; - labelPressed = 'unmute'; - icon = 'volume'; - iconPressed = 'muted'; - break; + if (is.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } // Update mute state - case 'captions': - toggle = true; - label = 'enableCaptions'; - labelPressed = 'disableCaptions'; - icon = 'captions-off'; - iconPressed = 'captions-on'; - break; - case 'fullscreen': - toggle = true; - label = 'enterFullscreen'; - labelPressed = 'exitFullscreen'; - icon = 'enter-fullscreen'; - iconPressed = 'exit-fullscreen'; - break; + if (is.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } + }, + // Update seek value and lower fill + setRange: function setRange(target) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - case 'play-large': - attributes.class += ' ' + this.config.classNames.control + '--overlaid'; - type = 'play'; - label = 'play'; - icon = 'play'; - break; + if (!is.element(target)) { + return; + } // eslint-disable-next-line - default: - label = type; - icon = buttonType; - } - // Setup toggle icon and labels - if (toggle) { - // Icon - button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' })); - button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' })); + target.value = value; // Webkit range fill - // Label/Tooltip - button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' })); - button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' })); + controls.updateRangeFill.call(this, target); + }, + // Update <progress> elements + updateProgress: function updateProgress(event) { + var _this3 = this; - // Add aria attributes - attributes['aria-pressed'] = false; - } else { - button.appendChild(controls.createIcon.call(this, icon)); - button.appendChild(controls.createLabel.call(this, label)); - } + if (!this.supported.ui || !is.event(event)) { + return; + } - // Merge attributes - utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + var value = 0; - utils.setAttributes(button, attributes); + var setProgress = function setProgress(target, input) { + var value = is.number(input) ? input : 0; + var progress = is.element(target) ? target : _this3.elements.display.buffer; // Update value and label - // We have multiple play buttons - if (type === 'play') { - if (!utils.is.array(this.elements.buttons[type])) { - this.elements.buttons[type] = []; - } + if (is.element(progress)) { + progress.value = value; // Update text label inside - this.elements.buttons[type].push(button); - } else { - this.elements.buttons[type] = button; + var label = progress.getElementsByTagName('span')[0]; + + if (is.element(label)) { + label.childNodes[0].nodeValue = value; + } } + }; - return button; - }, + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } - // Create an <input type='range'> - createRange: function createRange(type, attributes) { - // Seek label - var label = utils.createElement('label', { - for: attributes.id, - id: attributes.id + '-label', - class: this.config.classNames.hidden - }, i18n.get(type, this.config)); - - // Seek input - var input = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { - type: 'range', - min: 0, - max: 100, - step: 0.01, - value: 0, - autocomplete: 'off', - // A11y fixes for https://github.com/sampotts/plyr/issues/905 - role: 'slider', - 'aria-labelledby': attributes.id + '-label', - 'aria-valuemin': 0, - 'aria-valuemax': 100, - 'aria-valuenow': 0 - }, attributes)); - - this.elements.inputs[type] = input; - - // Set the fill for webkit now - controls.updateRangeFill.call(this, input); + break; + // Check buffer status - return { - label: label, - input: input - }; + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + break; + + default: + break; + } + } }, + // Webkit polyfill for lower fill range + updateRangeFill: function updateRangeFill(target) { + // Get range from event if event passed + var range = is.event(target) ? target.target : target; // Needs to be a valid <input type='range'> + if (!is.element(range) || range.getAttribute('type') !== 'range') { + return; + } // Set aria values for https://github.com/sampotts/plyr/issues/905 + + + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + var currentTime = controls.formatTime(this.currentTime); + var duration = controls.formatTime(this.duration); + var format$$1 = i18n.get('seekLabel', this.config); + range.setAttribute('aria-valuetext', format$$1.replace('{currentTime}', currentTime).replace('{duration}', duration)); + } else if (matches(range, this.config.selectors.inputs.volume)) { + var percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', "".concat(percent.toFixed(1), "%")); + } else { + range.setAttribute('aria-valuenow', range.value); + } // WebKit only - // Create a <progress> - createProgress: function createProgress(type, attributes) { - var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), { - min: 0, - max: 100, - value: 0, - role: 'presentation', - 'aria-hidden': true - }, attributes)); - // Create the label inside - if (type !== 'volume') { - progress.appendChild(utils.createElement('span', null, '0')); + if (!browser.isWebkit) { + return; + } // Set CSS custom property - var suffix = ''; - switch (type) { - case 'played': - suffix = i18n.get('played', this.config); - break; - case 'buffer': - suffix = i18n.get('buffered', this.config); - break; + range.style.setProperty('--value', "".concat(range.value / range.max * 100, "%")); + }, + // Update hover tooltip for seeking + updateSeekTooltip: function updateSeekTooltip(event) { + var _this4 = this; - default: - break; - } + // Bail if setting not true + if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) { + return; + } // Calculate percentage - progress.textContent = '% ' + suffix.toLowerCase(); - } - this.elements.display[type] = progress; + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + var visible = "".concat(this.config.classNames.tooltip, "--visible"); - return progress; - }, + var toggle = function toggle(_toggle) { + toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + }; // Hide on touch - // Create time display - createTime: function createTime(type) { - var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]); + if (this.touch) { + toggle(false); + return; + } // Determine percentage, if already visible - var container = utils.createElement('div', utils.extend(attributes, { - class: 'plyr__time ' + attributes.class, - 'aria-label': i18n.get(type, this.config) - }), '00:00'); - // Reference for updates - this.elements.display[type] = container; + if (is.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } // Set bounds - return container; - }, + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } // Display the time a click would seek to - // Create a settings menu item - createMenuItem: function createMenuItem(value, list, type, title) { - var badge = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - var checked = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; - var item = utils.createElement('li'); + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position - var label = utils.createElement('label', { - class: this.config.classNames.control - }); + this.elements.display.seekTooltip.style.left = "".concat(percent, "%"); // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds - var radio = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { - type: 'radio', - name: 'plyr-' + type, - value: value, - checked: checked, - class: 'plyr__sr-only' - })); + if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + toggle(event.type === 'mouseenter'); + } + }, + // Handle time change event + timeUpdate: function timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + var invert = !is.element(this.elements.display.duration) && this.config.invertTime; // Duration - var faux = utils.createElement('span', { hidden: '' }); + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking - label.appendChild(radio); - label.appendChild(faux); - label.insertAdjacentHTML('beforeend', title); + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } // Playing progress - if (utils.is.element(badge)) { - label.appendChild(badge); - } - item.appendChild(label); - list.appendChild(item); + controls.updateProgress.call(this, event); }, + // Show the duration on metadataloaded or durationchange events + durationUpdate: function durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || !this.config.invertTime && this.currentTime) { + return; + } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 - // Update hover tooltip for seeking - updateSeekTooltip: function updateSeekTooltip(event) { - var _this = this; + if (this.duration >= Math.pow(2, 32)) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } // Update ARIA values - // Bail if setting not true - if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) { - return; - } - // Calculate percentage - var percent = 0; - var clientRect = this.elements.inputs.seek.getBoundingClientRect(); - var visible = this.config.classNames.tooltip + '--visible'; + if (is.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); + } // If there's a spot to display duration - var toggle = function toggle(_toggle) { - utils.toggleClass(_this.elements.display.seekTooltip, visible, _toggle); - }; - // Hide on touch - if (this.touch) { - toggle(false); - return; - } + var hasDuration = is.element(this.elements.display.duration); // If there's only one time display, display duration there - // Determine percentage, if already visible - if (utils.is.event(event)) { - percent = 100 / clientRect.width * (event.pageX - clientRect.left); - } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { - percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); - } else { - return; - } + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } // If there's a duration element, update content - // Set bounds - if (percent < 0) { - percent = 0; - } else if (percent > 100) { - percent = 100; - } - // Display the time a click would seek to - ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } // Update the tooltip (if visible) - // Set position - this.elements.display.seekTooltip.style.left = percent + '%'; - // Show/hide the tooltip - // If the event is a moues in/out and percentage is inside bounds - if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { - toggle(event.type === 'mouseenter'); - } + controls.updateSeekTooltip.call(this); }, - - // Hide/show a tab - toggleTab: function toggleTab(setting, toggle) { - utils.toggleHidden(this.elements.settings.tabs[setting], !toggle); + toggleMenuButton: function toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); }, + // Update the selected setting + updateSetting: function updateSetting(setting, container, input) { + var pane = this.elements.settings.panels[setting]; + var value = null; + var list = container; + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is.empty(input) ? input : this[setting]; // Get default - // Set the quality menu - // TODO: Vimeo support - setQualityMenu: function setQualityMenu(options) { - var _this2 = this; + if (is.empty(value)) { + value = this.config[setting].default; + } // Unsupported value - // Menu required - if (!utils.is.element(this.elements.settings.panes.quality)) { - return; - } - - var type = 'quality'; - var list = this.elements.settings.panes.quality.querySelector('ul'); - - // Set options if passed and filter based on config - if (utils.is.array(options)) { - this.options.quality = options.filter(function (quality) { - return _this2.config.quality.options.includes(quality); - }); - } - // Toggle the pane and tab - var toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1; - controls.toggleTab.call(this, type, toggle); + if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn("Unsupported value of '".concat(value, "' for ").concat(setting)); + return; + } // Disabled value - // Check if we need to toggle the parent - controls.checkMenu.call(this); - // If we're hiding, nothing more to do - if (!toggle) { - return; + if (!this.config[setting].options.includes(value)) { + this.debug.warn("Disabled value of '".concat(value, "' for ").concat(setting)); + return; } + } // Get the list if we need to - // Empty the menu - utils.emptyElement(list); - - // Get the badge HTML for HD, 4K etc - var getBadge = function getBadge(quality) { - var label = ''; - switch (quality) { - case 2160: - label = '4K'; - break; + if (!is.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } // If there's no list it means it's not been rendered... - case 1440: - case 1080: - case 720: - label = 'HD'; - break; - case 576: - case 480: - label = 'SD'; - break; - - default: - break; - } + if (!is.element(list)) { + return; + } // Update the label - if (!label.length) { - return null; - } - return controls.createBadge.call(_this2, label); - }; + var label = this.elements.settings.buttons[setting].querySelector(".".concat(this.config.classNames.menu.value)); + label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it - // Sort options by the config and then render options - this.options.quality.sort(function (a, b) { - var sorting = _this2.config.quality.options; - return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; - }).forEach(function (quality) { - var label = controls.getLabel.call(_this2, 'quality', quality); - controls.createMenuItem.call(_this2, quality, list, type, label, getBadge(quality)); - }); + var target = list && list.querySelector("[value=\"".concat(value, "\"]")); - controls.updateSetting.call(this, type, list); + if (is.element(target)) { + target.checked = true; + } }, - - // Translate a value into a nice label - // TODO: Localisation getLabel: function getLabel(setting, value) { - switch (setting) { - case 'speed': - return value === 1 ? i18n.get('normal', this.config) : value + '×'; + switch (setting) { + case 'speed': + return value === 1 ? i18n.get('normal', this.config) : "".concat(value, "×"); - case 'quality': - if (utils.is.number(value)) { - return value + 'p'; - } + case 'quality': + if (is.number(value)) { + var label = i18n.get("qualityLabel.".concat(value), this.config); - return utils.toTitleCase(value); + if (!label.length) { + return "".concat(value, "p"); + } - case 'captions': - return captions.getLabel.call(this); + return label; + } - default: - return null; - } - }, + return toTitleCase(value); + case 'captions': + return captions.getLabel.call(this); - // Update the selected setting - updateSetting: function updateSetting(setting, container, input) { - var pane = this.elements.settings.panes[setting]; - var value = null; - var list = container; - - switch (setting) { - case 'captions': - if (this.captions.active) { - if (this.options.captions.length > 2 || !this.options.captions.some(function (lang) { - return lang === 'enabled'; - })) { - value = this.captions.language; - } else { - value = 'enabled'; - } - } else { - value = ''; - } + default: + return null; + } + }, + // Set the quality menu + setQualityMenu: function setQualityMenu(options) { + var _this5 = this; - break; + // Menu required + if (!is.element(this.elements.settings.panels.quality)) { + return; + } - default: - value = !utils.is.empty(input) ? input : this[setting]; + var type = 'quality'; + var list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); // Set options if passed and filter based on uniqueness and config - // Get default - if (utils.is.empty(value)) { - value = this.config[setting].default; - } + if (is.array(options)) { + this.options.quality = dedupe(options).filter(function (quality) { + return _this5.config.quality.options.includes(quality); + }); + } // Toggle the pane and tab - // Unsupported value - if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) { - this.debug.warn('Unsupported value of \'' + value + '\' for ' + setting); - return; - } - // Disabled value - if (!this.config[setting].options.includes(value)) { - this.debug.warn('Disabled value of \'' + value + '\' for ' + setting); - return; - } + var toggle = !is.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - break; - } + emptyElement(list); // Check if we need to toggle the parent - // Get the list if we need to - if (!utils.is.element(list)) { - list = pane && pane.querySelector('ul'); - } + controls.checkMenu.call(this); // If we're hiding, nothing more to do - // If there's no list it means it's not been rendered... - if (!utils.is.element(list)) { - return; - } + if (!toggle) { + return; + } // Get the badge HTML for HD, 4K etc - // Update the label - var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value); - label.innerHTML = controls.getLabel.call(this, setting, value); - // Find the radio option and check it - var target = list && list.querySelector('input[value="' + value + '"]'); + var getBadge = function getBadge(quality) { + var label = i18n.get("qualityBadge.".concat(quality), _this5.config); - if (utils.is.element(target)) { - target.checked = true; + if (!label.length) { + return null; } - }, + + return controls.createBadge.call(_this5, label); + }; // Sort options by the config and then render options + this.options.quality.sort(function (a, b) { + var sorting = _this5.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }).forEach(function (quality) { + controls.createMenuItem.call(_this5, { + value: quality, + list: list, + type: type, + title: controls.getLabel.call(_this5, 'quality', quality), + badge: getBadge(quality) + }); + }); + controls.updateSetting.call(this, type, list); + }, // Set the looping options + /* setLoopMenu() { // Menu required - if (!utils.is.element(this.elements.settings.panes.loop)) { + if (!is.element(this.elements.settings.panels.loop)) { return; } const options = ['start', 'end', 'all', 'reset']; - const list = this.elements.settings.panes.loop.querySelector('ul'); + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); // Show the pane and tab - utils.toggleHidden(this.elements.settings.tabs.loop, false); - utils.toggleHidden(this.elements.settings.panes.loop, false); + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); // Toggle the pane and tab - const toggle = !utils.is.empty(this.loop.options); - controls.toggleTab.call(this, 'loop', toggle); + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); // Empty the menu - utils.emptyElement(list); + emptyElement(list); options.forEach(option => { - const item = utils.createElement('li'); - const button = utils.createElement( + const item = createElement('li'); + const button = createElement( 'button', - utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), { + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { type: 'button', class: this.config.classNames.control, 'data-plyr-loop-action': option, @@ -2735,5355 +2119,6483 @@ var controls = { list.appendChild(item); }); }, */ - // Get current selected caption language // TODO: rework this to user the getter in the API? - // Set a list of available captions languages setCaptionsMenu: function setCaptionsMenu() { - var _this3 = this; - - // TODO: Captions or language? Currently it's mixed - var type = 'captions'; - var list = this.elements.settings.panes.captions.querySelector('ul'); + var _this6 = this; - // Toggle the pane and tab - var toggle = captions.getTracks.call(this).length; - controls.toggleTab.call(this, type, toggle); + // Menu required + if (!is.element(this.elements.settings.panels.captions)) { + return; + } // TODO: Captions or language? Currently it's mixed - // Empty the menu - utils.emptyElement(list); - // Check if we need to toggle the parent - controls.checkMenu.call(this); + var type = 'captions'; + var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + var tracks = captions.getTracks.call(this); + var toggle = Boolean(tracks.length); // Toggle the pane and tab - // If there's no captions, bail - if (!toggle) { - return; - } + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - // Re-map the tracks into just the data we need - var tracks = captions.getTracks.call(this).map(function (track) { - return { - language: !utils.is.empty(track.language) ? track.language : 'enabled', - label: captions.getLabel.call(_this3, track) - }; - }); + emptyElement(list); // Check if we need to toggle the parent - // Add the "Disabled" option to turn off captions - tracks.unshift({ - language: '', - label: i18n.get('disabled', this.config) - }); + controls.checkMenu.call(this); // If there's no captions, bail - // Generate options - tracks.forEach(function (track) { - controls.createMenuItem.call(_this3, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this3, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this3.captions.language.toLowerCase()); - }); + if (!toggle) { + return; + } // Generate options data - // Store reference - this.options.captions = tracks.map(function (track) { - return track.language; - }); - controls.updateSetting.call(this, type, list); + var options = tracks.map(function (track, value) { + return { + value: value, + checked: _this6.captions.toggled && _this6.currentTrack === value, + title: captions.getLabel.call(_this6, track), + badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + list: list, + type: 'language' + }; + }); // Add the "Disabled" option to turn off captions + + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list: list, + type: 'language' + }); // Generate options + + options.forEach(controls.createMenuItem.bind(this)); + controls.updateSetting.call(this, type, list); }, - - // Set a list of available captions languages setSpeedMenu: function setSpeedMenu(options) { - var _this4 = this; + var _this7 = this; - // Do nothing if not selected - if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) { - return; - } + // Menu required + if (!is.element(this.elements.settings.panels.speed)) { + return; + } - // Menu required - if (!utils.is.element(this.elements.settings.panes.speed)) { - return; - } + var type = 'speed'; + var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options - var type = 'speed'; + if (is.array(options)) { + this.options.speed = options; + } else if (this.isHTML5 || this.isVimeo) { + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + } // Set options if passed and filter based on config - // Set the speed options - if (utils.is.array(options)) { - this.options.speed = options; - } else if (this.isHTML5 || this.isVimeo) { - this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; - } - // Set options if passed and filter based on config - this.options.speed = this.options.speed.filter(function (speed) { - return _this4.config.speed.options.includes(speed); - }); + this.options.speed = this.options.speed.filter(function (speed) { + return _this7.config.speed.options.includes(speed); + }); // Toggle the pane and tab - // Toggle the pane and tab - var toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1; - controls.toggleTab.call(this, type, toggle); + var toggle = !is.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - // Check if we need to toggle the parent - controls.checkMenu.call(this); + emptyElement(list); // Check if we need to toggle the parent - // If we're hiding, nothing more to do - if (!toggle) { - return; - } + controls.checkMenu.call(this); // If we're hiding, nothing more to do - // Get the list to populate - var list = this.elements.settings.panes.speed.querySelector('ul'); + if (!toggle) { + return; + } // Create items - // Empty the menu - utils.emptyElement(list); - // Create items - this.options.speed.forEach(function (speed) { - var label = controls.getLabel.call(_this4, 'speed', speed); - controls.createMenuItem.call(_this4, speed, list, type, label); + this.options.speed.forEach(function (speed) { + controls.createMenuItem.call(_this7, { + value: speed, + list: list, + type: type, + title: controls.getLabel.call(_this7, 'speed', speed) }); - - controls.updateSetting.call(this, type, list); + }); + controls.updateSetting.call(this, type, list); }, - - // Check if we need to hide/show the settings menu checkMenu: function checkMenu() { - var tabs = this.elements.settings.tabs; - - var visible = !utils.is.empty(tabs) && Object.values(tabs).some(function (tab) { - return !tab.hidden; - }); - - utils.toggleHidden(this.elements.settings.menu, !visible); + var buttons = this.elements.settings.buttons; + var visible = !is.empty(buttons) && Object.values(buttons).some(function (button) { + return !button.hidden; + }); + toggleHidden(this.elements.settings.menu, !visible); }, + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem: function focusFirstMenuItem(pane) { + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (this.elements.settings.popup.hidden) { + return; + } - // Show/hide menu - toggleMenu: function toggleMenu(event) { - var form = this.elements.settings.form; - - var button = this.elements.buttons.settings; - - // Menu and button are required - if (!utils.is.element(form) || !utils.is.element(button)) { - return; - } + var target = pane; - var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden'); + if (!is.element(target)) { + target = Object.values(this.elements.settings.panels).find(function (pane) { + return !pane.hidden; + }); + } - if (utils.is.event(event)) { - var isMenuItem = utils.is.element(form) && form.contains(event.target); - var isButton = event.target === this.elements.buttons.settings; + var firstItem = target.querySelector('[role^="menuitem"]'); + setFocus.call(this, firstItem, tabFocus); + }, + // Show/hide menu + toggleMenu: function toggleMenu(input) { + var popup = this.elements.settings.popup; + var button = this.elements.buttons.settings; // Menu and button are required - // If the click was inside the form or if the click - // wasn't the button or menu item and we're trying to - // show the menu (a doc click shouldn't show the menu) - if (isMenuItem || !isMenuItem && !isButton && show) { - return; - } + if (!is.element(popup) || !is.element(button)) { + return; + } // True toggle by default - // Prevent the toggle being caught by the doc listener - if (isButton) { - event.stopPropagation(); - } - } - // Set form and button attributes - if (utils.is.element(button)) { - button.setAttribute('aria-expanded', show); - } + var hidden = popup.hidden; + var show = hidden; - if (utils.is.element(form)) { - utils.toggleHidden(form, !show); - utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); + if (is.boolean(input)) { + show = input; + } else if (is.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is.event(input)) { + var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) - if (show) { - form.removeAttribute('tabindex'); - } else { - form.setAttribute('tabindex', -1); - } + if (isMenuItem || !isMenuItem && input.target !== button && show) { + return; } - }, + } // Set button attributes - // Get the natural size of a tab - getTabSize: function getTabSize(tab) { - var clone = tab.cloneNode(true); - clone.style.position = 'absolute'; - clone.style.opacity = 0; - clone.removeAttribute('hidden'); + button.setAttribute('aria-expanded', show); // Show the actual popup - // Prevent input's being unchecked due to the name being identical - Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) { - var name = input.getAttribute('name'); - input.setAttribute('name', name + '-clone'); - }); + toggleHidden(popup, !show); // Add class hook - // Append to parent so we get the "real" size - tab.parentNode.appendChild(clone); + toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction - // Get the sizes before we remove - var width = clone.scrollWidth; - var height = clone.scrollHeight; + if (show && is.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is.keyboardEvent(input)); + } + }, + // Get the natural size of a menu panel + getMenuSize: function getMenuSize(tab) { + var clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.removeAttribute('hidden'); // Append to parent so we get the "real" size + + tab.parentNode.appendChild(clone); // Get the sizes before we remove + + var width = clone.scrollWidth; + var height = clone.scrollHeight; // Remove from the DOM + + removeElement(clone); + return { + width: width, + height: height + }; + }, + // Show a panel in the menu + showMenuPanel: function showMenuPanel() { + var _this8 = this; - // Remove from the DOM - utils.removeElement(clone); + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail - return { - width: width, - height: height - }; - }, + if (!is.element(target)) { + return; + } // Hide all other panels - // Toggle Menu - showTab: function showTab() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var menu = this.elements.settings.menu; + var container = target.parentNode; + var current = Array.from(container.children).find(function (node) { + return !node.hidden; + }); // If we can do fancy animations, we'll animate the height/width - var pane = document.getElementById(target); + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = "".concat(current.scrollWidth, "px"); + container.style.height = "".concat(current.scrollHeight, "px"); // Get potential sizes - // Nothing to show, bail - if (!utils.is.element(pane)) { - return; - } + var size = controls.getMenuSize.call(this, target); // Restore auto height/width - // Are we targetting a tab? If not, bail - var isTab = pane.getAttribute('role') === 'tabpanel'; - if (!isTab) { + var restore = function restore(event) { + // We're only bothered about height and width on the container + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { return; - } + } // Revert back to auto - // Hide all other tabs - // Get other tabs - var current = menu.querySelector('[role="tabpanel"]:not([hidden])'); - var container = current.parentNode; - // Set other toggles to be expanded false - Array.from(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]')).forEach(function (toggle) { - toggle.setAttribute('aria-expanded', false); - }); + container.style.width = ''; + container.style.height = ''; // Only listen once - // If we can do fancy animations, we'll animate the height/width - if (support.transitions && !support.reducedMotion) { - // Set the current width as a base - container.style.width = current.scrollWidth + 'px'; - container.style.height = current.scrollHeight + 'px'; + off.call(_this8, container, transitionEndEvent, restore); + }; // Listen for the transition finishing and restore auto height/width - // Get potential sizes - var size = controls.getTabSize.call(this, pane); - // Restore auto height/width - var restore = function restore(e) { - // We're only bothered about height and width on the container - if (e.target !== container || !['width', 'height'].includes(e.propertyName)) { - return; - } + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target - // Revert back to auto - container.style.width = ''; - container.style.height = ''; + container.style.width = "".concat(size.width, "px"); + container.style.height = "".concat(size.height, "px"); + } // Set attributes on current tab - // Only listen once - utils.off(container, utils.transitionEndEvent, restore); - }; - // Listen for the transition finishing and restore auto height/width - utils.on(container, utils.transitionEndEvent, restore); + toggleHidden(current, true); // Set attributes on target - // Set dimensions to target - container.style.width = size.width + 'px'; - container.style.height = size.height + 'px'; - } + toggleHidden(target, false); // Focus the first item - // Set attributes on current tab - utils.toggleHidden(current, true); - current.setAttribute('tabindex', -1); + controls.focusFirstMenuItem.call(this, target, tabFocus); + }, + // Set the download link + setDownloadLink: function setDownloadLink() { + var button = this.elements.buttons.download; // Bail if no button - // Set attributes on target - utils.toggleHidden(pane, false); + if (!is.element(button)) { + return; + } // Set download link - var tabs = utils.getElements.call(this, '[aria-controls="' + target + '"]'); - Array.from(tabs).forEach(function (tab) { - tab.setAttribute('aria-expanded', true); - }); - pane.removeAttribute('tabindex'); - // Focus the first item - pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus(); + button.setAttribute('href', this.download); }, - - // Build the default HTML // TODO: Set order based on order in the config.controls array? create: function create(data) { - var _this5 = this; + var _this9 = this; - // Do nothing if we want no controls - if (utils.is.empty(this.config.controls)) { - return null; - } + // Create the container + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button - // Create the container - var container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper)); + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } // Rewind button - // Restart button - if (this.config.controls.includes('restart')) { - container.appendChild(controls.createButton.call(this, 'restart')); - } - // Rewind button - if (this.config.controls.includes('rewind')) { - container.appendChild(controls.createButton.call(this, 'rewind')); - } + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } // Play/Pause button - // Play/Pause button - if (this.config.controls.includes('play')) { - container.appendChild(controls.createButton.call(this, 'play')); - } - // Fast forward button - if (this.config.controls.includes('fast-forward')) { - container.appendChild(controls.createButton.call(this, 'fast-forward')); - } + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + } // Fast forward button - // Progress - if (this.config.controls.includes('progress')) { - var progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress)); - // Seek range slider - var seek = controls.createRange.call(this, 'seek', { - id: 'plyr-seek-' + data.id - }); - progress.appendChild(seek.label); - progress.appendChild(seek.input); + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } // Progress - // Buffer progress - progress.appendChild(controls.createProgress.call(this, 'buffer')); - // TODO: Add loop display indicator + if (this.config.controls.includes('progress')) { + var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider - // Seek tooltip - if (this.config.tooltips.seek) { - var tooltip = utils.createElement('span', { - role: 'tooltip', - class: this.config.classNames.tooltip - }, '00:00'); + progress.appendChild(controls.createRange.call(this, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress - progress.appendChild(tooltip); - this.elements.display.seekTooltip = tooltip; - } + progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip - this.elements.progress = progress; - container.appendChild(this.elements.progress); + if (this.config.tooltips.seek) { + var tooltip = createElement('span', { + class: this.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; } - // Media current time display - if (this.config.controls.includes('current-time')) { - container.appendChild(controls.createTime.call(this, 'currentTime')); - } + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } // Media current time display - // Media duration display - if (this.config.controls.includes('duration')) { - container.appendChild(controls.createTime.call(this, 'duration')); - } - // Toggle mute button - if (this.config.controls.includes('mute')) { - container.appendChild(controls.createButton.call(this, 'mute')); - } + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } // Media duration display - // Volume range control - if (this.config.controls.includes('volume')) { - var volume = utils.createElement('div', { - class: 'plyr__volume' - }); - // Set the attributes - var attributes = { - max: 1, - step: 0.05, - value: this.config.volume - }; + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } // Volume controls - // Create the volume range slider - var range = controls.createRange.call(this, 'volume', utils.extend(attributes, { - id: 'plyr-volume-' + data.id - })); - volume.appendChild(range.label); - volume.appendChild(range.input); - this.elements.volume = volume; + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + var volume = createElement('div', { + class: 'plyr__volume' + }); // Toggle mute button - container.appendChild(volume); - } + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } // Volume range control - // Toggle captions button - if (this.config.controls.includes('captions')) { - container.appendChild(controls.createButton.call(this, 'captions')); + + if (this.config.controls.includes('volume')) { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: this.config.volume + }; // Create the volume range slider + + volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + this.elements.volume = volume; } - // Settings button / menu - if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { - var menu = utils.createElement('div', { - class: 'plyr__menu', - hidden: '' - }); + container.appendChild(volume); + } // Toggle captions button - menu.appendChild(controls.createButton.call(this, 'settings', { - id: 'plyr-settings-toggle-' + data.id, - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id, - 'aria-expanded': false - })); - - var form = utils.createElement('form', { - class: 'plyr__menu__container', - id: 'plyr-settings-' + data.id, - hidden: '', - 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, - role: 'tablist', - tabindex: -1 - }); - var inner = utils.createElement('div'); + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } // Settings button / menu - var home = utils.createElement('div', { - id: 'plyr-settings-' + data.id + '-home', - 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, - role: 'tabpanel' - }); - // Create the tab list - var tabs = utils.createElement('ul', { - role: 'tablist' - }); + if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + var control = createElement('div', { + class: 'plyr__menu', + hidden: '' + }); + control.appendChild(controls.createButton.call(this, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu - // Build the tabs - this.config.settings.forEach(function (type) { - var tab = utils.createElement('li', { - role: 'tab', - hidden: '' - }); + var menu = createElement('div', { + role: 'menu' + }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; // Build the menu items + + this.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + controls.showMenuPanel.call(_this9, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this9.config)); + var value = createElement('span', { + class: _this9.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this9.config))); // Screen reader label - var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this5.config.selectors.buttons.settings), { - type: 'button', - class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--forward', - id: 'plyr-settings-' + data.id + '-' + type + '-tab', - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id + '-' + type, - 'aria-expanded': false - }), i18n.get(type, _this5.config)); - - var value = utils.createElement('span', { - class: _this5.config.classNames.menu.value - }); + backButton.appendChild(createElement('span', { + class: _this9.config.classNames.hidden + }, i18n.get('menuBack', _this9.config))); // Go back via keyboard - // Speed contains HTML entities - value.innerHTML = data[type]; + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek - button.appendChild(value); - tab.appendChild(button); - tabs.appendChild(tab); - _this5.elements.settings.tabs[type] = tab; - }); + event.preventDefault(); + event.stopPropagation(); // Show the respective menu - home.appendChild(tabs); - inner.appendChild(home); - - // Build the panes - this.config.settings.forEach(function (type) { - var pane = utils.createElement('div', { - id: 'plyr-settings-' + data.id + '-' + type, - hidden: '', - 'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab', - role: 'tabpanel', - tabindex: -1 - }); + controls.showMenuPanel.call(_this9, 'home', true); + }, false); // Go back via button click - var back = utils.createElement('button', { - type: 'button', - class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--back', - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id + '-home', - 'aria-expanded': false - }, i18n.get(type, _this5.config)); + on(backButton, 'click', function () { + controls.showMenuPanel.call(_this9, 'home', false); + }); // Add to pane - pane.appendChild(back); + pane.appendChild(backButton); // Menu - var options = utils.createElement('ul'); + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this9.elements.settings.buttons[type] = menuItem; + _this9.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); + this.elements.settings.popup = popup; + this.elements.settings.menu = control; + } // Picture in picture button - pane.appendChild(options); - inner.appendChild(pane); - _this5.elements.settings.panes[type] = pane; - }); + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } // Airplay button - form.appendChild(inner); - menu.appendChild(form); - container.appendChild(menu); - this.elements.settings.form = form; - this.elements.settings.menu = menu; - } + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } // Download button - // Picture in picture button - if (this.config.controls.includes('pip') && support.pip) { - container.appendChild(controls.createButton.call(this, 'pip')); - } - // Airplay button - if (this.config.controls.includes('airplay') && support.airplay) { - container.appendChild(controls.createButton.call(this, 'airplay')); - } + if (this.config.controls.includes('download')) { + var _attributes = { + element: 'a', + href: this.download, + target: '_blank' + }; + var download = this.config.urls.download; - // Toggle fullscreen button - if (this.config.controls.includes('fullscreen')) { - container.appendChild(controls.createButton.call(this, 'fullscreen')); + if (!is.url(download) && this.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(this.provider), + label: this.provider + }); } - // Larger overlaid play button - if (this.config.controls.includes('play-large')) { - this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); - } + container.appendChild(controls.createButton.call(this, 'download', _attributes)); + } // Toggle fullscreen button - this.elements.controls = container; - if (this.isHTML5) { - controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); - } + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } // Larger overlaid play button - controls.setSpeedMenu.call(this); - return container; - }, + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } + this.elements.controls = container; // Set available quality levels + if (this.isHTML5) { + controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + } + + controls.setSpeedMenu.call(this); + return container; + }, // Insert controls inject: function inject() { - var _this6 = this; + var _this10 = this; - // Sprite - if (this.config.loadSprite) { - var icon = controls.getIconUrl.call(this); + // Sprite + if (this.config.loadSprite) { + var icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX - // Only load external sprite using AJAX - if (icon.cors) { - utils.loadSprite(icon.url, 'sprite-plyr'); - } + if (icon.cors) { + loadSprite(icon.url, 'sprite-plyr'); } + } // Create a unique ID - // Create a unique ID - this.id = Math.floor(Math.random() * 10000); - // Null by default - var container = null; - this.elements.controls = null; + this.id = Math.floor(Math.random() * 10000); // Null by default - // Set template properties - var props = { - id: this.id, - seektime: this.config.seekTime, - title: this.config.title - }; - var update = true; - - if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { - // String or HTMLElement passed as the option - container = this.config.controls; - } else if (utils.is.function(this.config.controls)) { - // A custom function to build controls - // The function can return a HTMLElement or String - container = this.config.controls.call(this, props); - } else { - // Create controls - container = controls.create.call(this, { - id: this.id, - seektime: this.config.seekTime, - speed: this.speed, - quality: this.quality, - captions: captions.getLabel.call(this) - // TODO: Looping - // loop: 'None', - }); - update = false; - } + var container = null; + this.elements.controls = null; // Set template properties - // Replace props with their value - var replace = function replace(input) { - var result = input; + var props = { + id: this.id, + seektime: this.config.seekTime, + title: this.config.title + }; + var update = true; // If function, run it and use output - Object.entries(props).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + if (is.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } // Convert falsy controls to empty array (primarily for empty strings) - result = utils.replaceAll(result, '{' + key + '}', value); - }); - return result; - }; + if (!this.config.controls) { + this.config.controls = []; + } - // Update markup - if (update) { - if (utils.is.string(this.config.controls)) { - container = replace(container); - } else if (utils.is.element(container)) { - container.innerHTML = replace(container.innerHTML); - } - } + if (is.element(this.config.controls) || is.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option + container = this.config.controls; + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: captions.getLabel.call(this) // TODO: Looping + // loop: 'None', - // Controls container - var target = void 0; + }); + update = false; + } // Replace props with their value - // Inject to custom location - if (utils.is.string(this.config.selectors.controls.container)) { - target = document.querySelector(this.config.selectors.controls.container); - } - // Inject into the container by default - if (!utils.is.element(target)) { - target = this.elements.container; - } + var replace = function replace(input) { + var result = input; + Object.entries(props).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + value = _ref3[1]; - // Inject controls HTML - if (utils.is.element(container)) { - target.appendChild(container); - } else if (container) { - target.insertAdjacentHTML('beforeend', container); - } + result = replaceAll(result, "{".concat(key, "}"), value); + }); + return result; + }; // Update markup - // Find the elements if need be - if (!utils.is.element(this.elements.controls)) { - controls.findElements.call(this); - } - // Edge sometimes doesn't finish the paint so force a redraw - if (window.navigator.userAgent.includes('Edge')) { - utils.repaint(target); + if (update) { + if (is.string(this.config.controls)) { + container = replace(container); + } else if (is.element(container)) { + container.innerHTML = replace(container.innerHTML); } + } // Controls container - // Setup tooltips - if (this.config.tooltips.controls) { - var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join('')); - Array.from(labels).forEach(function (label) { - utils.toggleClass(label, _this6.config.classNames.hidden, false); - utils.toggleClass(label, _this6.config.classNames.tooltip, true); - label.setAttribute('role', 'tooltip'); - }); - } - } -}; + var target; // Inject to custom location -// ========================================================================== + if (is.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } // Inject into the container by default -var captions = { - // Setup captions - setup: function setup() { - // Requires UI support - if (!this.supported.ui) { - return; - } - // Set default language if not set - var stored = this.storage.get('language'); + if (!is.element(target)) { + target = this.elements.container; + } // Inject controls HTML (needs to be before captions, hence "afterbegin") - if (!utils.is.empty(stored)) { - this.captions.language = stored; - } - if (utils.is.empty(this.captions.language)) { - this.captions.language = this.config.captions.language.toLowerCase(); - } + var insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be - // Set captions enabled state if not set - if (!utils.is.boolean(this.captions.active)) { - var active = this.storage.get('captions'); + if (!is.element(this.elements.controls)) { + controls.findElements.call(this); + } // Add pressed property to buttons - if (utils.is.boolean(active)) { - this.captions.active = active; - } else { - this.captions.active = this.config.captions.active; - } - } - // Only Vimeo and HTML5 video supported at this point - if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { - // Clear menu and hide - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { - controls.setCaptionsMenu.call(this); + if (!is.empty(this.elements.buttons)) { + var addProperty = function addProperty(button) { + var className = _this10.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get: function get() { + return hasClass(button, className); + }, + set: function set() { + var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + toggleClass(button, className, pressed); } + }); + }; // Toggle classname when pressed property is set - return; - } - // Inject the container - if (!utils.is.element(this.elements.captions)) { - this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions)); + Object.values(this.elements.buttons).filter(Boolean).forEach(function (button) { + if (is.array(button) || is.nodeList(button)) { + Array.from(button).filter(Boolean).forEach(addProperty); + } else { + addProperty(button); + } + }); + } // Edge sometimes doesn't finish the paint so force a repaint - utils.insertAfter(this.elements.captions, this.elements.wrapper); - } - // Set the class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); + if (browser.isEdge) { + repaint(target); + } // Setup tooltips - // Get tracks - var tracks = captions.getTracks.call(this); - // If no caption file exists, hide container for caption text - if (utils.is.empty(tracks)) { - return; - } + if (this.config.tooltips.controls) { + var _this$config = this.config, + classNames = _this$config.classNames, + selectors = _this$config.selectors; + var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); + var labels = getElements.call(this, selector); + Array.from(labels).forEach(function (label) { + toggleClass(label, _this10.config.classNames.hidden, false); + toggleClass(label, _this10.config.classNames.tooltip, true); + }); + } + } + }; - // Get browser info - var browser = utils.getBrowser(); + /** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ - // Fix IE captions if CORS is used - // Fetch captions and inject as blobs instead (data URIs not supported!) - if (browser.isIE && window.URL) { - var elements = this.media.querySelectorAll('track'); + function parseUrl(input) { + var safe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var url = input; - Array.from(elements).forEach(function (track) { - var src = track.getAttribute('src'); - var href = utils.parseUrl(src); + if (safe) { + var parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } - if (href.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(href.protocol)) { - utils.fetch(src, 'blob').then(function (blob) { - track.setAttribute('src', window.URL.createObjectURL(blob)); - }).catch(function () { - utils.removeElement(track); - }); - } - }); - } + try { + return new URL(url); + } catch (e) { + return null; + } + } // Convert object to URLSearchParams + + function buildUrlParams(input) { + var params = new URLSearchParams(); - // Set language - captions.setLanguage.call(this); + if (is.object(input)) { + Object.entries(input).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; - // Enable UI - captions.show.call(this); + params.set(key, value); + }); + } + + return params; + } + + var captions = { + // Setup captions + setup: function setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } // Only Vimeo and HTML5 video supported at this point - // Set available languages in list - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { - controls.setCaptionsMenu.call(this); + + if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { + // Clear menu and hide + if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); } - }, + return; + } // Inject the container - // Set the captions language - setLanguage: function setLanguage() { - var _this = this; - // Setup HTML5 track rendering - if (this.isHTML5 && this.isVideo) { - captions.getTracks.call(this).forEach(function (track) { - // Show track - utils.on(track, 'cuechange', function (event) { - return captions.setCue.call(_this, event); - }); + if (!is.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); + insertAfter(this.elements.captions, this.elements.wrapper); + } // Fix IE captions if CORS is used + // Fetch captions and inject as blobs instead (data URIs not supported!) - // Turn off native caption rendering to avoid double captions - // eslint-disable-next-line - track.mode = 'hidden'; + + if (browser.isIE && window.URL) { + var elements = this.media.querySelectorAll('track'); + Array.from(elements).forEach(function (track) { + var src = track.getAttribute('src'); + var url = parseUrl(src); + + if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + fetch(src, 'blob').then(function (blob) { + track.setAttribute('src', window.URL.createObjectURL(blob)); + }).catch(function () { + removeElement(track); }); + } + }); + } // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state - // Get current track - var currentTrack = captions.getCurrentTrack.call(this); - // Check if suported kind - if (utils.is.track(currentTrack)) { - // If we change the active track while a cue is already displayed we need to update it - if (Array.from(currentTrack.activeCues || []).length) { - captions.setCue.call(this, currentTrack); - } - } - } else if (this.isVimeo && this.captions.active) { - this.embed.enableTextTrack(this.language); - } - }, + var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + var languages = dedupe(browserLanguages.map(function (language) { + return language.split('-')[0]; + })); + var language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto' + if (language === 'auto') { + var _languages = _slicedToArray(languages, 1); - // Get the tracks - getTracks: function getTracks() { - // Return empty array at least - if (utils.is.nullOrUndefined(this.media)) { - return []; - } + language = _languages[0]; + } - // Only get accepted kinds - return Array.from(this.media.textTracks || []).filter(function (track) { - return ['captions', 'subtitles'].includes(track.kind); - }); + var active = this.storage.get('captions'); + + if (!is.boolean(active)) { + active = this.config.captions.active; + } + + Object.assign(this.captions, { + toggled: false, + active: active, + language: language, + languages: languages + }); // Watch changes to textTracks and update captions menu + + if (this.isHTML5) { + var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); + } // Update available languages in list next tick (the event must not be triggered before the listeners) + + + setTimeout(captions.update.bind(this), 0); }, + // Update available language options in settings based on tracks + update: function update() { + var _this = this; + var tracks = captions.getTracks.call(this, true); // Get the wanted language - // Get the current track for the current language - getCurrentTrack: function getCurrentTrack() { - var _this2 = this; + var _this$captions = this.captions, + active = _this$captions.active, + language = _this$captions.language, + meta = _this$captions.meta, + currentTrackNode = _this$captions.currentTrackNode; + var languageExists = Boolean(tracks.find(function (track) { + return track.language === language; + })); // Handle tracks (add event listener and "pseudo"-default) - var tracks = captions.getTracks.call(this); + if (this.isHTML5 && this.isVideo) { + tracks.filter(function (track) { + return !meta.get(track); + }).forEach(function (track) { + _this.debug.log('Track added', track); // Attempt to store if the original dom element was "default" - if (!tracks.length) { - return null; - } - // Get track based on current language - var track = tracks.find(function (track) { - return track.language.toLowerCase() === _this2.language; + meta.set(track, { + default: track.mode === 'showing' + }); // Turn off native caption rendering to avoid double captions + + track.mode = 'hidden'; // Add event listener for cue changes + + on.call(_this, track, 'cuechange', function () { + return captions.updateCues.call(_this); + }); }); + } // Update language first time it matches, or if the previous matching track was removed - // Get the <track> with default attribute - if (!track) { - track = utils.getElement.call(this, 'track[default]'); - } - // Get the first track - if (!track) { - var _tracks = slicedToArray(tracks, 1); + if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } // Enable or disable captions based on track length - track = _tracks[0]; - } - return track; + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks)); // Update available languages in list + + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } }, + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle: function toggle(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + // If there's no full support + if (!this.supported.ui) { + return; + } - // Get UI label for track - getLabel: function getLabel(track) { - var currentTrack = track; + var toggled = this.captions.toggled; // Current state - if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) { - currentTrack = captions.getCurrentTrack.call(this); - } + var activeClass = this.config.classNames.captions.active; // Get the next state + // If the method is called without parameter, toggle based on current value - if (utils.is.track(currentTrack)) { - if (!utils.is.empty(currentTrack.label)) { - return currentTrack.label; - } + var active = is.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event - if (!utils.is.empty(currentTrack.language)) { - return track.language.toUpperCase(); - } + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ + captions: active + }); + } // Force language if the call isn't passive and there is no matching language to toggle to - return i18n.get('enabled', this.config); - } - return i18n.get('disabled', this.config); - }, + if (!this.language && active && !passive) { + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [this.captions.language].concat(_toConsumableArray(this.captions.languages)), true); // Override user preferences to avoid switching languages if a matching track is added + this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference - // Display active caption if it contains text - setCue: function setCue(input) { - // Get the track from the event if needed - var track = utils.is.event(input) ? input.target : input; - var activeCues = track.activeCues; + captions.set.call(this, tracks.indexOf(track)); + return; + } // Toggle button if it's enabled - var active = activeCues.length && activeCues[0]; - var currentTrack = captions.getCurrentTrack.call(this); - // Only display current track - if (track !== currentTrack) { - return; - } + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } // Add class hook - // Display a cue, if there is one - if (utils.is.cue(active)) { - captions.setText.call(this, active.getCueAsHTML()); - } else { - captions.setText.call(this, null); - } - utils.dispatchEvent.call(this, this.media, 'cuechange'); + toggleClass(this.elements.container, activeClass, active); + this.captions.toggled = active; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) + + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } }, + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set: function set(index) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var tracks = captions.getTracks.call(this); // Disable captions if setting to -1 + + if (index === -1) { + captions.toggle.call(this, false, passive); + return; + } + if (!is.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } - // Set the current caption - setText: function setText(input) { - // Requires UI - if (!this.supported.ui) { - return; - } + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; + } - if (utils.is.element(this.elements.captions)) { - var content = utils.createElement('span'); + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + var track = tracks[index]; - // Empty the container - utils.emptyElement(this.elements.captions); + var _ref = track || {}, + language = _ref.language; // Store reference to node for invalidation on remove - // Default to empty - var caption = !utils.is.nullOrUndefined(input) ? input : ''; - // Set the span content - if (utils.is.string(caption)) { - content.textContent = caption.trim(); - } else { - content.appendChild(caption); - } + this.captions.currentTrackNode = track; // Update settings menu - // Set new caption text - this.elements.captions.appendChild(content); - } else { - this.debug.warn('No captions element to render to'); - } + controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences + + if (!passive) { + this.captions.language = language; + this.storage.set({ + language: language + }); + } // Handle Vimeo captions + + + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } // Trigger event + + + triggerEvent.call(this, this.media, 'languagechange'); + } // Show captions + + + captions.toggle.call(this, true, passive); + + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } }, + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage: function setLanguage(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + if (!is.string(input)) { + this.debug.warn('Invalid language argument', input); + return; + } // Normalize - // Display captions container and button (for initialization) - show: function show() { - // Try to load the value from storage - var active = this.storage.get('captions'); - // Otherwise fall back to the default config - if (!utils.is.boolean(active)) { - active = this.config.captions.active; - } else { - this.captions.active = active; + var language = input.toLowerCase(); + this.captions.language = language; // Set currentTrack + + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks: function getTracks() { + var _this2 = this; + + var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + // Handle media or textTracks missing or null + var tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + + return tracks.filter(function (track) { + return !_this2.isHTML5 || update || _this2.captions.meta.has(track); + }).filter(function (track) { + return ['captions', 'subtitles'].includes(track.kind); + }); + }, + // Match tracks based on languages and get the first + findTrack: function findTrack(languages) { + var _this3 = this; + + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var tracks = captions.getTracks.call(this); + + var sortIsDefault = function sortIsDefault(track) { + return Number((_this3.captions.meta.get(track) || {}).default); + }; + + var sorted = Array.from(tracks).sort(function (a, b) { + return sortIsDefault(b) - sortIsDefault(a); + }); + var track; + languages.every(function (language) { + track = sorted.find(function (track) { + return track.language === language; + }); + return !track; // Break iteration if there is a match + }); // If no match is found but is required, get first + + return track || (force ? sorted[0] : undefined); + }, + // Get the current track + getCurrentTrack: function getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; + }, + // Get UI label for track + getLabel: function getLabel(track) { + var currentTrack = track; + + if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) { + currentTrack = captions.getCurrentTrack.call(this); + } + + if (is.track(currentTrack)) { + if (!is.empty(currentTrack.label)) { + return currentTrack.label; } - if (active) { - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true); - utils.toggleState(this.elements.buttons.captions, true); + if (!is.empty(currentTrack.language)) { + return track.language.toUpperCase(); } - } -}; -// ========================================================================== -// Console wrapper -// ========================================================================== + return i18n.get('enabled', this.config); + } -var noop = function noop() {}; + return i18n.get('disabled', this.config); + }, + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues: function updateCues(input) { + // Requires UI + if (!this.supported.ui) { + return; + } -var Console = function () { - function Console() { - var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - classCallCheck(this, Console); + if (!is.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; + } // Only accept array or empty input - this.enabled = window.console && enabled; - if (this.enabled) { - this.log('Debugging enabled'); - } - } + if (!is.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); + return; + } - createClass(Console, [{ - key: 'log', - get: function get$$1() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; - } - }, { - key: 'warn', - get: function get$$1() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; - } - }, { - key: 'error', - get: function get$$1() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; - } - }]); - return Console; -}(); + var cues = input; // Get cues from track -// ========================================================================== -// Plyr default config -// ========================================================================== + if (!cues) { + var track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []).map(function (cue) { + return cue.getCueAsHTML(); + }).map(getHTML); + } // Set new caption text -var defaults$1 = { + + var content = cues.map(function (cueText) { + return cueText.trim(); + }).join('\n'); + var changed = content !== this.elements.captions.innerHTML; + + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + var caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); // Trigger event + + triggerEvent.call(this, this.media, 'cuechange'); + } + } + }; + + // ========================================================================== + // Plyr default config + // ========================================================================== + var defaults = { // Disable enabled: true, - // Custom media title title: '', - // Logging to console debug: false, - // Auto play (if supported) autoplay: false, - // Only allow one media playing at once (vimeo only) autopause: true, - + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, // Default time to skip when rewind/fast forward seekTime: 10, - // Default volume volume: 1, muted: false, - // Pass a custom duration duration: null, - // Display the media duration on load in the current time position // If you have opted to display both duration and currentTime, this is ignored displayDuration: true, - // Invert the current time to be a countdown invertTime: true, - // Clicking the currentTime inverts it's value to show time left rather than elapsed toggleInvert: true, - // Aspect ratio (for embeds) ratio: '16:9', - // Click video container to play/pause clickToPlay: true, - // Auto hide the controls hideControls: true, - // Reset to start when playback ended resetOnEnd: false, - // Disable the standard context menu disableContextMenu: true, - // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg', - + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', - // Quality default quality: { - default: 576, - options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default'] + default: 576, + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] }, - // Set loops loop: { - active: false - // start: null, - // end: null, - }, + active: false // start: null, + // end: null, + }, // Speed default and options to display speed: { - selected: 1, - options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] + selected: 1, + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }, - // Keyboard shortcut settings keyboard: { - focused: true, - global: false + focused: true, + global: false }, - // Display tooltips tooltips: { - controls: false, - seek: true + controls: false, + seek: true }, - // Captions settings captions: { - active: false, - language: (navigator.language || navigator.userLanguage).split('-')[0] + active: false, + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false }, - // Fullscreen settings fullscreen: { - enabled: true, // Allow fullscreen? - fallback: true, // Fallback for vintage browsers - iosNative: false // Use the native fullscreen in iOS (disables custom controls) - }, + enabled: true, + // Allow fullscreen? + fallback: true, + // Fallback using full viewport/window + iosNative: false // Use the native fullscreen in iOS (disables custom controls) + }, // Local storage storage: { - enabled: true, - key: 'plyr' + enabled: true, + key: 'plyr' }, - // Default controls - controls: ['play-large', - // 'restart', + controls: ['play-large', // 'restart', // 'rewind', - 'play', - // 'fast-forward', - 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen'], + 'play', // 'fast-forward', + 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download', + 'fullscreen'], settings: ['captions', 'quality', 'speed'], - // Localisation i18n: { - restart: 'Restart', - rewind: 'Rewind {seektime}s', - play: 'Play', - pause: 'Pause', - fastForward: 'Forward {seektime}s', - seek: 'Seek', - played: 'Played', - buffered: 'Buffered', - currentTime: 'Current time', - duration: 'Duration', - volume: 'Volume', - mute: 'Mute', - unmute: 'Unmute', - enableCaptions: 'Enable captions', - disableCaptions: 'Disable captions', - enterFullscreen: 'Enter fullscreen', - exitFullscreen: 'Exit fullscreen', - frameTitle: 'Player for {title}', - captions: 'Captions', - settings: 'Settings', - speed: 'Speed', - normal: 'Normal', - quality: 'Quality', - loop: 'Loop', - start: 'Start', - end: 'End', - all: 'All', - reset: 'Reset', - disabled: 'Disabled', - enabled: 'Enabled', - advertisement: 'Ad' + restart: 'Restart', + rewind: 'Rewind {seektime}s', + play: 'Play', + pause: 'Pause', + fastForward: 'Forward {seektime}s', + seek: 'Seek', + seekLabel: '{currentTime} of {duration}', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + download: 'Download', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + menuBack: 'Go back to previous menu', + speed: 'Speed', + normal: 'Normal', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + disabled: 'Disabled', + enabled: 'Enabled', + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } }, - // URLs urls: { - vimeo: { - sdk: 'https://player.vimeo.com/api/player.js', - iframe: 'https://player.vimeo.com/video/{0}?{1}', - api: 'https://vimeo.com/api/v2/video/{0}.json' - }, - youtube: { - sdk: 'https://www.youtube.com/iframe_api', - api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', - poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg' - }, - googleIMA: { - sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' - } + download: null, + vimeo: { + sdk: 'https://player.vimeo.com/api/player.js', + iframe: 'https://player.vimeo.com/video/{0}?{1}', + api: 'https://vimeo.com/api/v2/video/{0}.json' + }, + youtube: { + sdk: 'https://www.youtube.com/iframe_api', + api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + }, + googleIMA: { + sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' + } }, - // Custom control listeners listeners: { - seek: null, - play: null, - pause: null, - restart: null, - rewind: null, - fastForward: null, - mute: null, - volume: null, - captions: null, - fullscreen: null, - pip: null, - airplay: null, - speed: null, - quality: null, - loop: null, - language: null + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + fastForward: null, + mute: null, + volume: null, + captions: null, + download: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null }, - // Events to watch and bubble - events: [ - // Events to watch on HTML5 media elements and bubble + events: [// Events to watch on HTML5 media elements and bubble // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events - 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', - - // Custom events - 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', - - // YouTube - 'statechange', 'qualitychange', 'qualityrequested', - - // Ads + 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube + 'statechange', // Quality + 'qualitychange', // Ads 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], - // Selectors // Change these to match your template if using custom HTML selectors: { - editable: 'input, textarea, select, [contenteditable]', - container: '.plyr', - controls: { - container: null, - wrapper: '.plyr__controls' - }, - labels: '[data-plyr]', - buttons: { - play: '[data-plyr="play"]', - pause: '[data-plyr="pause"]', - restart: '[data-plyr="restart"]', - rewind: '[data-plyr="rewind"]', - fastForward: '[data-plyr="fast-forward"]', - mute: '[data-plyr="mute"]', - captions: '[data-plyr="captions"]', - fullscreen: '[data-plyr="fullscreen"]', - pip: '[data-plyr="pip"]', - airplay: '[data-plyr="airplay"]', - settings: '[data-plyr="settings"]', - loop: '[data-plyr="loop"]' - }, - inputs: { - seek: '[data-plyr="seek"]', - volume: '[data-plyr="volume"]', - speed: '[data-plyr="speed"]', - language: '[data-plyr="language"]', - quality: '[data-plyr="quality"]' - }, - display: { - currentTime: '.plyr__time--current', - duration: '.plyr__time--duration', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played', - loop: '.plyr__progress--loop', - volume: '.plyr__volume--display' - }, - progress: '.plyr__progress', - captions: '.plyr__captions', - menu: { - quality: '.js-plyr__menu__list--quality' - } + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls' + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + fastForward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]' + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]' + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', + // Used later + volume: '.plyr__volume--display' + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + caption: '.plyr__caption', + menu: { + quality: '.js-plyr__menu__list--quality' + } }, - // Class hooks added to the player in different states classNames: { - type: 'plyr--{0}', - provider: 'plyr--{0}', - video: 'plyr__video-wrapper', - embed: 'plyr__video-embed', - embedContainer: 'plyr__video-embed__container', - poster: 'plyr__poster', - ads: 'plyr__ads', - control: 'plyr__control', - playing: 'plyr--playing', - paused: 'plyr--paused', - stopped: 'plyr--stopped', - loading: 'plyr--loading', - error: 'plyr--has-error', - hover: 'plyr--hover', - tooltip: 'plyr__tooltip', - cues: 'plyr__cues', - hidden: 'plyr__sr-only', - hideControls: 'plyr--hide-controls', - isIos: 'plyr--is-ios', - isTouch: 'plyr--is-touch', - uiSupported: 'plyr--full-ui', - noTransition: 'plyr--no-transition', - menu: { - value: 'plyr__menu__value', - badge: 'plyr__badge', - open: 'plyr--menu-open' - }, - captions: { - enabled: 'plyr--captions-enabled', - active: 'plyr--captions-active' - }, - fullscreen: { - enabled: 'plyr--fullscreen-enabled', - fallback: 'plyr--fullscreen-fallback' - }, - pip: { - supported: 'plyr--pip-supported', - active: 'plyr--pip-active' - }, - airplay: { - supported: 'plyr--airplay-supported', - active: 'plyr--airplay-active' - }, - tabFocus: 'plyr__tab-focus' + type: 'plyr--{0}', + provider: 'plyr--{0}', + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + embedContainer: 'plyr__video-embed__container', + poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', + ads: 'plyr__ads', + control: 'plyr__control', + controlPressed: 'plyr__control--pressed', + playing: 'plyr--playing', + paused: 'plyr--paused', + stopped: 'plyr--stopped', + loading: 'plyr--loading', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + cues: 'plyr__cues', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time' + }, + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open' + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active' + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback' + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active' + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active' + }, + tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' + } }, - // Embed attributes attributes: { - embed: { - provider: 'data-plyr-provider', - id: 'data-plyr-embed-id' - } + embed: { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id' + } }, - // API keys keys: { - google: null + google: null }, - // Advertisements plugin // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio ads: { - enabled: false, - publisherId: '' + enabled: false, + publisherId: '', + tagUrl: '' + }, + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '' + }, + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false + }, + // YouTube plugin + youtube: { + noCookie: false, + // Whether to use an alternative version of YouTube without cookies + rel: 0, + // No related vids + showinfo: 0, + // Hide info + iv_load_policy: 3, + // Hide annotations + modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) + } -}; + }; -// ========================================================================== + // ========================================================================== + // Plyr states + // ========================================================================== + var pip = { + active: 'picture-in-picture', + inactive: 'inline' + }; -var browser$2 = utils.getBrowser(); + // ========================================================================== + // Plyr supported types and providers + // ========================================================================== + var providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo' + }; + var types = { + audio: 'audio', + video: 'video' + }; + /** + * Get provider by URL + * @param {String} url + */ -function onChange() { - if (!this.enabled) { - return; + function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } // Vimeo + + + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; } - // Update toggle button - var button = this.player.elements.buttons.fullscreen; - if (utils.is.element(button)) { - utils.toggleState(button, this.active); + return null; + } + + // ========================================================================== + // Console wrapper + // ========================================================================== + var noop = function noop() {}; + + var Console = + /*#__PURE__*/ + function () { + function Console() { + var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + _classCallCheck(this, Console); + + this.enabled = window.console && enabled; + + if (this.enabled) { + this.log('Debugging enabled'); + } } - // Trigger an event - utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); + _createClass(Console, [{ + key: "log", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + }, { + key: "warn", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + }, { + key: "error", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } + }]); + + return Console; + }(); + + function onChange() { + if (!this.enabled) { + return; + } // Update toggle button + + + var button = this.player.elements.buttons.fullscreen; + + if (is.element(button)) { + button.pressed = this.active; + } // Trigger an event + - // Trap focus in container - if (!browser$2.isIos) { - utils.trapFocus.call(this.player, this.target, this.active); + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container + + if (!browser.isIos) { + trapFocus.call(this.player, this.target, this.active); } -} + } + + function toggleFallback() { + var _this = this; -function toggleFallback() { var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; // Store or restore scroll position if (toggle) { - this.scrollPosition = { - x: window.scrollX || 0, - y: window.scrollY || 0 - }; + this.scrollPosition = { + x: window.scrollX || 0, + y: window.scrollY || 0 + }; } else { - window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); - } + window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + } // Toggle scroll - // Toggle scroll - document.body.style.overflow = toggle ? 'hidden' : ''; - // Toggle class hook - utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); + document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook - // Toggle button and fire events - onChange.call(this); -} + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+ -var Fullscreen = function () { - function Fullscreen(player) { - var _this = this; + if (browser.isIos) { + var viewport = document.head.querySelector('meta[name="viewport"]'); + var property = 'viewport-fit=cover'; // Inject the viewport meta if required - classCallCheck(this, Fullscreen); + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } // Check if the property already exists - // Keep reference to parent - this.player = player; - // Get prefix - this.prefix = Fullscreen.prefix; - this.property = Fullscreen.property; + var hasProperty = is.string(viewport.content) && viewport.content.includes(property); - // Scroll position - this.scrollPosition = { x: 0, y: 0 }; + if (toggle) { + this.cleanupViewport = !hasProperty; - // Register event listeners - // Handle event (incase user presses escape etc) - utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : this.prefix + 'fullscreenchange', function () { - // TODO: Filter for target?? - onChange.call(_this); - }); + if (!hasProperty) { + viewport.content += ",".concat(property); + } + } else if (this.cleanupViewport) { + viewport.content = viewport.content.split(',').filter(function (part) { + return part.trim() !== property; + }).join(','); + } // Force a repaint as sometimes Safari doesn't want to fill the screen - // Fullscreen toggle on double click - utils.on(this.player.elements.container, 'dblclick', function (event) { - // Ignore double click in controls - if (utils.is.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) { - return; - } - _this.toggle(); - }); + setTimeout(function () { + return repaint(_this.target); + }, 100); + } // Toggle button and fire events - // Update the UI - this.update(); - } - // Determine if native supported + onChange.call(this); + } + var Fullscreen = + /*#__PURE__*/ + function () { + function Fullscreen(player) { + var _this2 = this; - createClass(Fullscreen, [{ - key: 'update', + _classCallCheck(this, Fullscreen); + // Keep reference to parent + this.player = player; // Get prefix - // Update UI - value: function update() { - if (this.enabled) { - this.player.debug.log((Fullscreen.native ? 'Native' : 'Fallback') + ' fullscreen enabled'); - } else { - this.player.debug.log('Fullscreen not supported and fallback disabled'); - } + this.prefix = Fullscreen.prefix; + this.property = Fullscreen.property; // Scroll position - // Add styling hook to show button - utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); - } + this.scrollPosition = { + x: 0, + y: 0 + }; // Force the use of 'full window/browser' rather than fullscreen - // Make an element fullscreen + this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners + // Handle event (incase user presses escape etc) - }, { - key: 'enter', - value: function enter() { - if (!this.enabled) { - return; - } + on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { + // TODO: Filter for target?? + onChange.call(_this2); + }); // Fullscreen toggle on double click - // iOS native fullscreen doesn't need the request step - if (browser$2.isIos && this.player.config.fullscreen.iosNative) { - if (this.player.playing) { - this.target.webkitEnterFullscreen(); - } - } else if (!Fullscreen.native) { - toggleFallback.call(this, true); - } else if (!this.prefix) { - this.target.requestFullscreen(); - } else if (!utils.is.empty(this.prefix)) { - this.target[this.prefix + 'Request' + this.property](); - } + on.call(this.player, this.player.elements.container, 'dblclick', function (event) { + // Ignore double click in controls + if (is.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) { + return; } - // Bail from fullscreen + _this2.toggle(); + }); // Update the UI - }, { - key: 'exit', - value: function exit() { - if (!this.enabled) { - return; - } + this.update(); + } // Determine if native supported - // iOS native fullscreen - if (browser$2.isIos && this.player.config.fullscreen.iosNative) { - this.target.webkitExitFullscreen(); - this.player.play(); - } else if (!Fullscreen.native) { - toggleFallback.call(this, false); - } else if (!this.prefix) { - (document.cancelFullScreen || document.exitFullscreen).call(document); - } else if (!utils.is.empty(this.prefix)) { - var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; - document['' + this.prefix + action + this.property](); - } - } - // Toggle state + _createClass(Fullscreen, [{ + key: "update", + // Update UI + value: function update() { + if (this.enabled) { + var mode; - }, { - key: 'toggle', - value: function toggle() { - if (!this.active) { - this.enter(); - } else { - this.exit(); - } - } - }, { - key: 'enabled', + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } + this.player.debug.log("".concat(mode, " fullscreen enabled")); + } else { + this.player.debug.log('Fullscreen not supported and fallback disabled'); + } // Add styling hook to show button - // Determine if fullscreen is enabled - get: function get$$1() { - return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; - } - // Get active state + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + } // Make an element fullscreen }, { - key: 'active', - get: function get$$1() { - if (!this.enabled) { - return false; - } - - // Fallback using classname - if (!Fullscreen.native) { - return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); - } + key: "enter", + value: function enter() { + if (!this.enabled) { + return; + } // iOS native fullscreen doesn't need the request step - var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.property + 'Element']; - return element === this.target; + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, true); + } else if (!this.prefix) { + this.target.requestFullscreen(); + } else if (!is.empty(this.prefix)) { + this.target["".concat(this.prefix, "Request").concat(this.property)](); } + } // Bail from fullscreen - // Get target element + }, { + key: "exit", + value: function exit() { + if (!this.enabled) { + return; + } // iOS native fullscreen + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitExitFullscreen(); + this.player.play(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, false); + } else if (!this.prefix) { + (document.cancelFullScreen || document.exitFullscreen).call(document); + } else if (!is.empty(this.prefix)) { + var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; + document["".concat(this.prefix).concat(action).concat(this.property)](); + } + } // Toggle state }, { - key: 'target', - get: function get$$1() { - return browser$2.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; - } - }], [{ - key: 'native', - get: function get$$1() { - return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + key: "toggle", + value: function toggle() { + if (!this.active) { + this.enter(); + } else { + this.exit(); } + } + }, { + key: "usingNative", + // If we're actually using native + get: function get() { + return Fullscreen.native && !this.forceFallback; + } // Get the prefix for handlers - // Get the prefix for handlers + }, { + key: "enabled", + // Determine if fullscreen is enabled + get: function get() { + return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + } // Get active state }, { - key: 'prefix', - get: function get$$1() { - // No prefix - if (utils.is.function(document.exitFullscreen)) { - return ''; - } + key: "active", + get: function get() { + if (!this.enabled) { + return false; + } // Fallback using classname - // Check for fullscreen support by vendor prefix - var value = ''; - var prefixes = ['webkit', 'moz', 'ms']; - prefixes.some(function (pre) { - if (utils.is.function(document[pre + 'ExitFullscreen']) || utils.is.function(document[pre + 'CancelFullScreen'])) { - value = pre; - return true; - } + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + } - return false; - }); + var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; + return element === this.target; + } // Get target element - return value; - } }, { - key: 'property', - get: function get$$1() { - return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; - } + key: "target", + get: function get() { + return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + } + }], [{ + key: "native", + get: function get() { + return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + } + }, { + key: "prefix", + get: function get() { + // No prefix + if (is.function(document.exitFullscreen)) { + return ''; + } // Check for fullscreen support by vendor prefix + + + var value = ''; + var prefixes = ['webkit', 'moz', 'ms']; + prefixes.some(function (pre) { + if (is.function(document["".concat(pre, "ExitFullscreen")]) || is.function(document["".concat(pre, "CancelFullScreen")])) { + value = pre; + return true; + } + + return false; + }); + return value; + } + }, { + key: "property", + get: function get() { + return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + } }]); + return Fullscreen; -}(); + }(); + + // ========================================================================== + // Load image avoiding xhr/fetch CORS issues + // Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded + // By default it checks if it is at least 1px, but you can add a second argument to change this + // ========================================================================== + function loadImage(src) { + var minWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return new Promise(function (resolve, reject) { + var image = new Image(); + + var handler = function handler() { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { + onload: handler, + onerror: handler, + src: src + }); + }); + } + + // ========================================================================== + var ui = { + addStyleHook: function addStyleHook() { + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + }, + // Toggle native HTML5 media controls + toggleNativeControls: function toggleNativeControls() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + // Setup the UI + build: function build() { + var _this = this; -// ========================================================================== + // Re-attach media element listeners + // TODO: Use event bubbling? + this.listeners.media(); // Don't setup interface if no support -// Sniff out the browser -var browser$3 = utils.getBrowser(); + if (!this.supported.ui) { + this.debug.warn("Basic support only for ".concat(this.provider, " ").concat(this.type)); // Restore native controls -var Listeners = function () { - function Listeners(player) { - classCallCheck(this, Listeners); + ui.toggleNativeControls.call(this, true); // Bail + + return; + } // Inject custom controls if not present + + + if (!is.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); // Re-attach control listeners + + this.listeners.controls(); + } // Remove native controls + + + ui.toggleNativeControls.call(this); // Setup captions for HTML5 + + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume + + + this.volume = null; // Reset mute state + + this.muted = null; // Reset speed + + this.speed = null; // Reset loop state + + this.loop = null; // Reset quality setting + + this.quality = null; // Reset volume display + + controls.updateVolume.call(this); // Reset time display + + controls.timeUpdate.call(this); // Update the UI + + ui.checkPlaying.call(this); // Check for picture-in-picture support + + toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support + + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class + + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class - this.player = player; - this.lastKey = null; + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls - this.handleKey = this.handleKey.bind(this); - this.toggleMenu = this.toggleMenu.bind(this); - this.firstTouch = this.firstTouch.bind(this); + this.ready = true; // Ready event at end of execution stack + + setTimeout(function () { + triggerEvent.call(_this, _this.media, 'ready'); + }, 0); // Set the title + + ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created + + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(function () {}); + } // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + + + if (this.config.duration) { + controls.durationUpdate.call(this); + } + }, + // Setup aria attribute for play and iframe title + setTitle: function setTitle() { + // Find the current text + var label = i18n.get('play', this.config); // If there's a media title set, use that for the label + + if (is.string(this.config.title) && !is.empty(this.config.title)) { + label += ", ".concat(this.config.title); + } // If there's a play button, set label + + + Array.from(this.elements.buttons.play || []).forEach(function (button) { + button.setAttribute('aria-label', label); + }); // Set iframe title + // https://github.com/sampotts/plyr/issues/124 + + if (this.isEmbed) { + var iframe = getElement.call(this, 'iframe'); + + if (!is.element(iframe)) { + return; + } // Default to media type + + + var title = !is.empty(this.config.title) ? this.config.title : 'video'; + var format = i18n.get('frameTitle', this.config); + iframe.setAttribute('title', format.replace('{title}', title)); + } + }, + // Toggle poster + togglePoster: function togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster: function setPoster(poster) { + var _this2 = this; + + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); + } // Set property synchronously to respect the call order + + + this.media.setAttribute('poster', poster); // Wait until ui is ready + + return ready.call(this) // Load image + .then(function () { + return loadImage(poster); + }).catch(function (err) { + // Hide poster on error unless it's been set by another call + if (poster === _this2.poster) { + ui.togglePoster.call(_this2, false); + } // Rethrow + + + throw err; + }).then(function () { + // Prevent race conditions + if (poster !== _this2.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }).then(function () { + Object.assign(_this2.elements.poster.style, { + backgroundImage: "url('".concat(poster, "')"), + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '' + }); + ui.togglePoster.call(_this2, true); + return poster; + }); + }, + // Check playing state + checkPlaying: function checkPlaying(event) { + var _this3 = this; + + // Class hooks + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state + + Array.from(this.elements.buttons.play || []).forEach(function (target) { + target.pressed = _this3.playing; + }); // Only update controls on non timeupdate events + + if (is.event(event) && event.type === 'timeupdate') { + return; + } // Toggle controls + + + ui.toggleControls.call(this); + }, + // Check if media is loading + checkLoading: function checkLoading(event) { + var _this4 = this; + + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer + + clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking + + this.timers.loading = setTimeout(function () { + // Update progress bar loading class state + toggleClass(_this4.elements.container, _this4.config.classNames.loading, _this4.loading); // Update controls visibility + + ui.toggleControls.call(_this4); + }, this.loading ? 250 : 0); + }, + // Toggle controls based on state and `force` argument + toggleControls: function toggleControls(force) { + var controls$$1 = this.elements.controls; + + if (controls$$1 && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide + + this.toggleControls(Boolean(force || this.loading || this.paused || controls$$1.pressed || controls$$1.hover || recentTouchSeek)); + } } + }; - // Handle key presses + /* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; + } */ + // Set aspect ratio for responsive container + function setAspectRatio(input) { + var ratio = input; - createClass(Listeners, [{ - key: 'handleKey', - value: function handleKey(event) { - var _this = this; + if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { + ratio = this.embed.ratio; + } - var code = event.keyCode ? event.keyCode : event.which; - var pressed = event.type === 'keydown'; - var repeat = pressed && code === this.lastKey; + if (!is.string(ratio)) { + ratio = this.config.ratio; + } - // Bail if a modifier key is set - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return; - } + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + x = _ratio$split$map2[0], + y = _ratio$split$map2[1]; - // If the event is bubbled from the media element - // Firefox doesn't get the keycode for whatever reason - if (!utils.is.number(code)) { - return; - } + var padding = 100 / x * y; + this.elements.wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI - // Seek by the number keys - var seekByKey = function seekByKey() { - // Divide the max duration into 10th's and times by the number value - _this.player.currentTime = _this.player.duration / 10 * (code - 48); - }; + if (this.isVimeo && this.supported.ui) { + var height = 240; + var offset = (height - padding) / (height / 50); + this.media.style.transform = "translateY(-".concat(offset, "%)"); + } - // Handle the key on keydown - // Reset on keyup - if (pressed) { - // Which keycodes should we prevent default - var preventDefault = [48, 49, 50, 51, 52, 53, 54, 56, 57, 32, 75, 38, 40, 77, 39, 37, 70, 67, 73, 76, 79]; - - // Check focused element - // and if the focused element is not editable (e.g. text input) - // and any that accept key input http://webaim.org/techniques/keyboard/ - var focused = utils.getFocusElement(); - if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) { - return; - } + return { + padding: padding, + ratio: ratio + }; + } - // If the code is found prevent default (e.g. prevent scrolling for arrows) - if (preventDefault.includes(code)) { - event.preventDefault(); - event.stopPropagation(); - } + var Listeners = + /*#__PURE__*/ + function () { + function Listeners(player) { + _classCallCheck(this, Listeners); + + this.player = player; + this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; + this.handleKey = this.handleKey.bind(this); + this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); + this.firstTouch = this.firstTouch.bind(this); + } // Handle key presses + + + _createClass(Listeners, [{ + key: "handleKey", + value: function handleKey(event) { + var player = this.player; + var elements = player.elements; + var code = event.keyCode ? event.keyCode : event.which; + var pressed = event.type === 'keydown'; + var repeat = pressed && code === this.lastKey; // Bail if a modifier key is set + + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason + + + if (!is.number(code)) { + return; + } // Seek by the number keys + + + var seekByKey = function seekByKey() { + // Divide the max duration into 10th's and times by the number value + player.currentTime = player.duration / 10 * (code - 48); + }; // Handle the key on keydown + // Reset on keyup + + + if (pressed) { + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + var focused = document.activeElement; + + if (is.element(focused)) { + var editable = player.config.selectors.editable; + var seek = elements.inputs.seek; + + if (focused !== seek && matches(focused, editable)) { + return; + } + + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } + } // Which keycodes should we prevent default + + + var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows) + + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } + + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + player.togglePlay(); + } + + break; + + case 38: + // Arrow up + player.increaseVolume(0.1); + break; + + case 40: + // Arrow down + player.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + player.muted = !player.muted; + } + + break; + + case 39: + // Arrow forward + player.forward(); + break; + + case 37: + // Arrow back + player.rewind(); + break; + + case 70: + // F key + player.fullscreen.toggle(); + break; + + case 67: + // C key + if (!repeat) { + player.toggleCaptions(); + } + + break; + + case 76: + // L key + player.loop = !player.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ - switch (code) { - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: - // 0-9 - if (!repeat) { - seekByKey(); - } - break; - - case 32: - case 75: - // Space and K key - if (!repeat) { - this.player.togglePlay(); - } - break; - - case 38: - // Arrow up - this.player.increaseVolume(0.1); - break; - - case 40: - // Arrow down - this.player.decreaseVolume(0.1); - break; - - case 77: - // M key - if (!repeat) { - this.player.muted = !this.player.muted; - } - break; - - case 39: - // Arrow forward - this.player.forward(); - break; - - case 37: - // Arrow back - this.player.rewind(); - break; - - case 70: - // F key - this.player.fullscreen.toggle(); - break; - - case 67: - // C key - if (!repeat) { - this.player.toggleCaptions(); - } - break; - - case 76: - // L key - this.player.loop = !this.player.loop; - break; - - /* case 73: - this.setLoop('start'); - break; - case 76: - this.setLoop(); - break; - case 79: - this.setLoop('end'); - break; */ - - default: - break; - } + default: + break; + } // Escape is handle natively when in full screen + // So we only need to worry about non native - // Escape is handle natively when in full screen - // So we only need to worry about non native - if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) { - this.player.fullscreen.toggle(); - } - // Store last code for next cycle - this.lastKey = code; - } else { - this.lastKey = null; - } - } + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); + } // Store last code for next cycle - // Toggle menu - }, { - key: 'toggleMenu', - value: function toggleMenu(event) { - controls.toggleMenu.call(this.player, event); + this.lastKey = code; + } else { + this.lastKey = null; } + } // Toggle menu - // Device is touch enabled + }, { + key: "toggleMenu", + value: function toggleMenu(event) { + controls.toggleMenu.call(this.player, event); + } // Device is touch enabled }, { - key: 'firstTouch', - value: function firstTouch() { - this.player.touch = true; + key: "firstTouch", + value: function firstTouch() { + var player = this.player; + var elements = player.elements; + player.touch = true; // Add touch class - // Add touch class - utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true); + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + }, { + key: "setTabFocus", + value: function setTabFocus(event) { + var player = this.player; + var elements = player.elements; + clearTimeout(this.focusTimer); // Ignore any key other than tab - // Clean up - utils.off(document.body, 'touchstart', this.firstTouch); - } + if (event.type === 'keydown' && event.which !== 9) { + return; + } // Store reference to event timeStamp + + + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } // Remove current classes + + + var removeCurrent = function removeCurrent() { + var className = player.config.classNames.tabFocus; + var current = getElements.call(player, ".".concat(className)); + toggleClass(current, className, false); + }; // Determine if a key was pressed to trigger this event + + + var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior - // Global window & document listeners + if (event.type === 'focus' && !wasKeyDown) { + return; + } // Remove all current + + + removeCurrent(); // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + + this.focusTimer = setTimeout(function () { + var focused = document.activeElement; // Ignore if current focus element isn't inside the player + + if (!elements.container.contains(focused)) { + return; + } + + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); + } // Global window & document listeners }, { - key: 'global', - value: function global() { - var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + key: "global", + value: function global() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var player = this.player; // Keyboard shortcuts - // Keyboard shortcuts - if (this.player.config.keyboard.global) { - utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false); - } + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); + } // Click anywhere closes menu - // Click anywhere closes menu - utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); - // Detect touch by events - utils.on(document.body, 'touchstart', this.firstTouch); - } + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events + + once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection - // Container listeners + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); + } // Container listeners }, { - key: 'container', - value: function container() { - var _this2 = this; + key: "container", + value: function container() { + var player = this.player; + var config = player.config, + elements = player.elements, + timers = player.timers; // Keyboard shortcuts - // Keyboard shortcuts - if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) { - utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false); - } + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); + } // Toggle controls on mouse events and entering fullscreen - // Detect tab focus - // Remove class on blur/focusout - utils.on(this.player.elements.container, 'focusout', function (event) { - utils.toggleClass(event.target, _this2.player.config.classNames.tabFocus, false); - }); - // Add classname to tabbed elements - utils.on(this.player.elements.container, 'keydown', function (event) { - if (event.keyCode !== 9) { - return; - } + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen - // Delay the adding of classname until the focus has changed - // This event fires before the focusin event - setTimeout(function () { - utils.toggleClass(utils.getFocusElement(), _this2.player.config.classNames.tabFocus, true); - }, 0); - }); + if (controls$$1 && event.type === 'enterfullscreen') { + controls$$1.pressed = false; + controls$$1.hover = false; + } // Show, then hide after a timeout unless another control event occurs - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', function (event) { - _this2.player.toggleControls(event); - }); - } - } - // Listen for media events + var show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + var delay = 0; - }, { - key: 'media', - value: function media() { - var _this3 = this; + if (show) { + ui.toggleControls.call(player, true); // Use longer timeout for touch devices - // Time change on media - utils.on(this.player.media, 'timeupdate seeking', function (event) { - return ui.timeUpdate.call(_this3.player, event); - }); + delay = player.touch ? 3000 : 2000; + } // Clear timer - // Display duration - utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', function (event) { - return ui.durationUpdate.call(_this3.player, event); - }); - // Check for audio tracks on load - // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point - utils.on(this.player.media, 'loadeddata', function () { - utils.toggleHidden(_this3.player.elements.volume, !_this3.player.hasAudio); - utils.toggleHidden(_this3.player.elements.buttons.mute, !_this3.player.hasAudio); - }); + clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking - // Handle the media finishing - utils.on(this.player.media, 'ended', function () { - // Show poster on end - if (_this3.player.isHTML5 && _this3.player.isVideo && _this3.player.config.resetOnEnd) { - // Restart - _this3.player.restart(); - } - }); + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen - // Check for buffer progress - utils.on(this.player.media, 'progress playing', function (event) { - return ui.updateProgress.call(_this3.player, event); + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); }); + } */ + // Set a gutter for Vimeo - // Handle volume changes - utils.on(this.player.media, 'volumechange', function (event) { - return ui.updateVolume.call(_this3.player, event); - }); + var setGutter = function setGutter(ratio, padding, toggle) { + if (!player.isVimeo) { + return; + } - // Handle play/pause - utils.on(this.player.media, 'playing play pause ended emptied timeupdate', function (event) { - return ui.checkPlaying.call(_this3.player, event); - }); + var target = player.elements.wrapper.firstChild; - // Loading state - utils.on(this.player.media, 'waiting canplay seeked playing', function (event) { - return ui.checkLoading.call(_this3.player, event); - }); + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + height = _ratio$split$map2[1]; - // Check if media failed to load - // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event)); + var _player$embed$ratio$s = player.embed.ratio.split(':').map(Number), + _player$embed$ratio$s2 = _slicedToArray(_player$embed$ratio$s, 2), + videoWidth = _player$embed$ratio$s2[0], + videoHeight = _player$embed$ratio$s2[1]; - // If autoplay, then load advertisement if required - // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows - utils.on(this.player.media, 'playing', function () { - if (!_this3.player.ads) { - return; - } + target.style.maxWidth = toggle ? "".concat(height / videoHeight * videoWidth, "px") : null; + target.style.margin = toggle ? '0 auto' : null; + }; // Resize on fullscreen change - // If ads are enabled, wait for them first - if (_this3.player.ads.enabled && !_this3.player.ads.initialized) { - // Wait for manager response - _this3.player.ads.managerPromise.then(function () { - return _this3.player.ads.play(); - }).catch(function () { - return _this3.player.play(); - }); - } + + var setPlayerSize = function setPlayerSize(measure) { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } + + var rect = elements.container.getBoundingClientRect(); + var width = rect.width, + height = rect.height; + return setAspectRatio.call(player, "".concat(width, ":").concat(height)); + }; + + var resized = function resized() { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; + + on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) { + var _player$fullscreen = player.fullscreen, + target = _player$fullscreen.target, + usingNative = _player$fullscreen.usingNative; // Ignore for iOS native + + if (!player.isEmbed || target !== elements.container) { + return; + } + + var isEnter = event.type === 'enterfullscreen'; // Set the player size when entering fullscreen to viewport size + + var _setPlayerSize = setPlayerSize(isEnter), + padding = _setPlayerSize.padding, + ratio = _setPlayerSize.ratio; // Set Vimeo gutter + + + setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport + + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); + } + } + }); + } // Listen for media events + + }, { + key: "media", + value: function media() { + var _this = this; + + var player = this.player; + var elements = player.elements; // Time change on media + + on.call(player, player.media, 'timeupdate seeking seeked', function (event) { + return controls.timeUpdate.call(player, event); + }); // Display duration + + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) { + return controls.durationUpdate.call(player, event); + }); // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point + + on.call(player, player.media, 'canplay loadeddata', function () { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); + }); // Handle the media finishing + + on.call(player, player.media, 'ended', function () { + // Show poster on end + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { + // Restart + player.restart(); + } + }); // Check for buffer progress + + on.call(player, player.media, 'progress playing seeking seeked', function (event) { + return controls.updateProgress.call(player, event); + }); // Handle volume changes + + on.call(player, player.media, 'volumechange', function (event) { + return controls.updateVolume.call(player, event); + }); // Handle play/pause + + on.call(player, player.media, 'playing play pause ended emptied timeupdate', function (event) { + return ui.checkPlaying.call(player, event); + }); // Loading state + + on.call(player, player.media, 'waiting canplay seeked playing', function (event) { + return ui.checkLoading.call(player, event); + }); // If autoplay, then load advertisement if required + // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows + + on.call(player, player.media, 'playing', function () { + if (!player.ads) { + return; + } // If ads are enabled, wait for them first + + + if (player.ads.enabled && !player.ads.initialized) { + // Wait for manager response + player.ads.managerPromise.then(function () { + return player.ads.play(); + }).catch(function () { + return player.play(); }); + } + }); // Click video - // Click video - if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) { - // Re-fetch the wrapper - var wrapper = utils.getElement.call(this.player, '.' + this.player.config.classNames.video); + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { + // Re-fetch the wrapper + var wrapper = getElement.call(player, ".".concat(player.config.classNames.video)); // Bail if there's no wrapper (this should never happen) - // Bail if there's no wrapper (this should never happen) - if (!utils.is.element(wrapper)) { - return; - } + if (!is.element(wrapper)) { + return; + } // On click play, pause or restart - // On click play, pause ore restart - utils.on(wrapper, 'click', function () { - // Touch devices will just show controls (if we're hiding controls) - if (_this3.player.config.hideControls && _this3.player.touch && !_this3.player.paused) { - return; - } - - if (_this3.player.paused) { - _this3.player.play(); - } else if (_this3.player.ended) { - _this3.player.restart(); - _this3.player.play(); - } else { - _this3.player.pause(); - } - }); + + on.call(player, elements.container, 'click', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper + + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } // Touch devices will just show controls (if hidden) + + + if (player.touch && player.config.hideControls) { + return; } - // Disable right click - if (this.player.supported.ui && this.player.config.disableContextMenu) { - utils.on(this.player.elements.wrapper, 'contextmenu', function (event) { - event.preventDefault(); - }, false); + if (player.ended) { + _this.proxy(event, player.restart, 'restart'); + + _this.proxy(event, player.play, 'play'); + } else { + _this.proxy(event, player.togglePlay, 'play'); } + }); + } // Disable right click - // Volume change - utils.on(this.player.media, 'volumechange', function () { - // Save to storage - _this3.player.storage.set({ volume: _this3.player.volume, muted: _this3.player.muted }); - }); - // Speed change - utils.on(this.player.media, 'ratechange', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'speed'); + if (player.supported.ui && player.config.disableContextMenu) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { + event.preventDefault(); + }, false); + } // Volume change - // Save to storage - _this3.player.storage.set({ speed: _this3.player.speed }); - }); - // Quality request - utils.on(this.player.media, 'qualityrequested', function (event) { - // Save to storage - _this3.player.storage.set({ quality: event.detail.quality }); - }); + on.call(player, player.media, 'volumechange', function () { + // Save to storage + player.storage.set({ + volume: player.volume, + muted: player.muted + }); + }); // Speed change - // Quality change - utils.on(this.player.media, 'qualitychange', function (event) { - // Update UI - controls.updateSetting.call(_this3.player, 'quality', null, event.detail.quality); - }); + on.call(player, player.media, 'ratechange', function () { + // Update UI + controls.updateSetting.call(player, 'speed'); // Save to storage - // Caption language change - utils.on(this.player.media, 'languagechange', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'captions'); - // Save to storage - _this3.player.storage.set({ language: _this3.player.language }); - }); + player.storage.set({ + speed: player.speed + }); + }); // Quality change - // Captions toggle - utils.on(this.player.media, 'captionsenabled captionsdisabled', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'captions'); + on.call(player, player.media, 'qualitychange', function (event) { + // Update UI + controls.updateSetting.call(player, 'quality', null, event.detail.quality); + }); // Update download link when ready and if quality changes - // Save to storage - _this3.player.storage.set({ captions: _this3.player.captions.active }); - }); + on.call(player, player.media, 'ready qualitychange', function () { + controls.setDownloadLink.call(player); + }); // Proxy events to container + // Bubble up key events for Edge - // Proxy events to container - // Bubble up key events for Edge - utils.on(this.player.media, this.player.config.events.concat(['keyup', 'keydown']).join(' '), function (event) { - var detail = {}; + var proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + on.call(player, player.media, proxyEvents, function (event) { + var _event$detail = event.detail, + detail = _event$detail === void 0 ? {} : _event$detail; // Get error details from media - // Get error details from media - if (event.type === 'error') { - detail = _this3.player.media.error; - } + if (event.type === 'error') { + detail = player.media.error; + } - utils.dispatchEvent.call(_this3.player, _this3.player.elements.container, event.type, true, detail); - }); + triggerEvent.call(player, elements.container, event.type, true, detail); + }); + } // Run default and custom handlers + + }, { + key: "proxy", + value: function proxy(event, defaultHandler, customHandlerKey) { + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + var returned = true; // Execute custom handler + + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } // Only call default handler if not prevented in custom handler + + + if (returned && is.function(defaultHandler)) { + defaultHandler.call(player, event); } + } // Trigger custom and default handlers - // Listen for control events + }, { + key: "bind", + value: function bind(element, type, defaultHandler, customHandlerKey) { + var _this2 = this; + + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + on.call(player, element, type, function (event) { + return _this2.proxy(event, defaultHandler, customHandlerKey); + }, passive && !hasCustomHandler); + } // Listen for control events }, { - key: 'controls', - value: function controls$$1() { - var _this4 = this; - - // IE doesn't support input event, so we fallback to change - var inputEvent = browser$3.isIE ? 'change' : 'input'; - - // Run default and custom handlers - var proxy = function proxy(event, defaultHandler, customHandlerKey) { - var customHandler = _this4.player.config.listeners[customHandlerKey]; - var hasCustomHandler = utils.is.function(customHandler); - var returned = true; - - // Execute custom handler - if (hasCustomHandler) { - returned = customHandler.call(_this4.player, event); - } + key: "controls", + value: function controls$$1() { + var _this3 = this; - // Only call default handler if not prevented in custom handler - if (returned && utils.is.function(defaultHandler)) { - defaultHandler.call(_this4.player, event); - } - }; + var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change - // Trigger custom and default handlers - var on = function on(element, type, defaultHandler, customHandlerKey) { - var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle - var customHandler = _this4.player.config.listeners[customHandlerKey]; - var hasCustomHandler = utils.is.function(customHandler); + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { + _this3.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause - utils.on(element, type, function (event) { - return proxy(event, defaultHandler, customHandlerKey); - }, passive && !hasCustomHandler); - }; - // Play/pause toggle - on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play'); + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind + + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind + + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle - // Pause - on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart'); + this.bind(elements.buttons.mute, 'click', function () { + player.muted = !player.muted; + }, 'mute'); // Captions toggle - // Rewind - on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind'); + this.bind(elements.buttons.captions, 'click', function () { + return player.toggleCaptions(); + }); // Download - // Rewind - on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward'); + this.bind(elements.buttons.download, 'click', function () { + triggerEvent.call(player, player.media, 'download'); + }, 'download'); // Fullscreen toggle - // Mute toggle - on(this.player.elements.buttons.mute, 'click', function () { - _this4.player.muted = !_this4.player.muted; - }, 'mute'); + this.bind(elements.buttons.fullscreen, 'click', function () { + player.fullscreen.toggle(); + }, 'fullscreen'); // Picture-in-Picture - // Captions toggle - on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions); + this.bind(elements.buttons.pip, 'click', function () { + player.pip = 'toggle'; + }, 'pip'); // Airplay - // Fullscreen toggle - on(this.player.elements.buttons.fullscreen, 'click', function () { - _this4.player.fullscreen.toggle(); - }, 'fullscreen'); + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle - // Picture-in-Picture - on(this.player.elements.buttons.pip, 'click', function () { - _this4.player.pip = 'toggle'; - }, 'pip'); + this.bind(elements.buttons.settings, 'click', function (event) { + // Prevent the document click listener closing the menu + event.stopPropagation(); - // Airplay - on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay'); + controls.toggleMenu.call(player, event); + }); // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 - // Settings menu - on(this.player.elements.buttons.settings, 'click', function (event) { - controls.toggleMenu.call(_this4.player, event); + this.bind(elements.buttons.settings, 'keyup', function (event) { + var code = event.which; // We only care about space and return + + if (![13, 32].includes(code)) { + return; + } // Because return triggers a click anyway, all we need to do is set focus + + + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); + + return; + } // Prevent scroll + + + event.preventDefault(); // Prevent playing video (Firefox) + + event.stopPropagation(); // Toggle menu + + controls.toggleMenu.call(player, event); + }, null, false // Can't be passive as we're preventing default + ); // Escape closes menu + + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); // Set range input alternative "value", which matches the tooltip time (#954) + + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); + var percent = 100 / rect.width * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); // Pause while seeking + + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var attribute = 'play-on-seeked'; + + if (is.keyboardEvent(event) && code !== 39 && code !== 37) { + return; + } // Record seek time so we can prevent hiding controls for a few seconds after seek + + + player.lastSeekTime = Date.now(); // Was playing before? + + var play = seek.hasAttribute(attribute); // Done seeking + + var done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback + + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); + } + }); // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + + if (browser.isIos) { + var inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(function (input) { + return _this3.bind(input, inputEvent, function (event) { + return repaint(event.target); }); + }); + } // Seek - // Settings menu - on(this.player.elements.settings.form, 'click', function (event) { - event.stopPropagation(); - - // Go back to home tab on click - var showHomeTab = function showHomeTab() { - var id = 'plyr-settings-' + _this4.player.id + '-home'; - controls.showTab.call(_this4.player, id); - }; - - // Settings menu items - use event delegation as items are added/removed - if (utils.matches(event.target, _this4.player.config.selectors.inputs.language)) { - proxy(event, function () { - _this4.player.language = event.target.value; - showHomeTab(); - }, 'language'); - } else if (utils.matches(event.target, _this4.player.config.selectors.inputs.quality)) { - proxy(event, function () { - _this4.player.quality = event.target.value; - showHomeTab(); - }, 'quality'); - } else if (utils.matches(event.target, _this4.player.config.selectors.inputs.speed)) { - proxy(event, function () { - _this4.player.speed = parseFloat(event.target.value); - showHomeTab(); - }, 'speed'); - } else { - var tab = event.target; - controls.showTab.call(_this4.player, tab.getAttribute('aria-controls')); - } + + this.bind(elements.inputs.seek, inputEvent, function (event) { + var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) + + var seekTo = seek.getAttribute('seek-value'); + + if (is.empty(seekTo)) { + seekTo = seek.value; + } + + seek.removeAttribute('seek-value'); + player.currentTime = seekTo / seek.max * player.duration; + }, 'seek'); // Seek tooltip + + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this + + this.bind(elements.progress, 'mousemove touchmove', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + + this.bind(elements.progress, 'mouseleave click', function () { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); // Show scrubbing preview + + this.bind(elements.progress, 'mousedown touchstart', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } + }); + this.bind(elements.progress, 'mouseup touchend', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); // Polyfill for lower fill in <input type="range"> for webkit + + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this3.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); }); + }); + } // Current time invert + // Only if one time element is used for both currentTime and duration - // Seek - on(this.player.elements.inputs.seek, inputEvent, function (event) { - _this4.player.currentTime = event.target.value / event.target.max * _this4.player.duration; - }, 'seek'); - - // Current time invert - // Only if one time element is used for both currentTime and duration - if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) { - on(this.player.elements.display.currentTime, 'click', function () { - // Do nothing if we're at the start - if (_this4.player.currentTime === 0) { - return; - } - - _this4.player.config.invertTime = !_this4.player.config.invertTime; - ui.timeUpdate.call(_this4.player); - }); + + if (player.config.toggleInvert && !is.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { + // Do nothing if we're at the start + if (player.currentTime === 0) { + return; } - // Volume - on(this.player.elements.inputs.volume, inputEvent, function (event) { - _this4.player.volume = event.target.value; - }, 'volume'); + player.config.invertTime = !player.config.invertTime; - // Polyfill for lower fill in <input type="range"> for webkit - if (browser$3.isWebkit) { - on(utils.getElements.call(this.player, 'input[type="range"]'), 'input', function (event) { - controls.updateRangeFill.call(_this4.player, event.target); - }); - } + controls.timeUpdate.call(player); + }); + } // Volume - // Seek tooltip - on(this.player.elements.progress, 'mouseenter mouseleave mousemove', function (event) { - return controls.updateSeekTooltip.call(_this4.player, event); - }); - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mouseenter mouseleave', function (event) { - _this4.player.elements.controls.hover = !_this4.player.touch && event.type === 'mouseenter'; - }); + this.bind(elements.inputs.volume, inputEvent, function (event) { + player.volume = event.target.value; + }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { - _this4.player.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); - }); + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) - // Focus in/out on controls - on(this.player.elements.controls, 'focusin focusout', function (event) { - _this4.player.toggleControls(event); - }); - } + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); // Show controls when they receive focus (e.g., when using keyboard tab key) - // Mouse wheel for volume - on(this.player.elements.inputs.volume, 'wheel', function (event) { - // Detect "natural" scroll - suppored on OS X Safari only - // Other browsers on OS X will be inverted until support improves - var inverted = event.webkitDirectionInvertedFromDevice; - var step = 1 / 50; - var direction = 0; - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - _this4.player.decreaseVolume(step); - direction = -1; - } else { - _this4.player.increaseVolume(step); - direction = 1; - } - } + this.bind(elements.controls, 'focusin', function () { + var config = player.config, + elements = player.elements, + timers = player.timers; // Skip transition to prevent focus from scrolling the parent element - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - _this4.player.increaseVolume(step); - direction = 1; - } else { - _this4.player.decreaseVolume(step); - direction = -1; - } - } + toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle - // Don't break page scrolling at max and min - if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) { - event.preventDefault(); - } - }, 'volume', false); - } + ui.toggleControls.call(player, true); // Restore transition - // Reset on destroy + setTimeout(function () { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); // Delay a little more for mouse users - }, { - key: 'clear', - value: function clear() { - this.global(false); - } - }]); - return Listeners; -}(); + var delay = _this3.touch ? 3000 : 4000; // Clear timer -// ========================================================================== + clearTimeout(timers.controls); // Hide again after delay -var vimeo = { - setup: function setup() { - var _this = this; + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Mouse wheel for volume - // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + this.bind(elements.inputs.volume, 'wheel', function (event) { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + var inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true - // Set intial ratio - vimeo.setAspectRatio.call(this); + var _map = [event.deltaX, -event.deltaY].map(function (value) { + return inverted ? -value : value; + }), + _map2 = _slicedToArray(_map, 2), + x = _map2[0], + y = _map2[1]; // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) - // Load the API if not already - if (!utils.is.object(window.Vimeo)) { - utils.loadScript(this.config.urls.vimeo.sdk).then(function () { - vimeo.ready.call(_this); - }).catch(function (error) { - _this.debug.warn('Vimeo API failed to load', error); - }); - } else { - vimeo.ready.call(this); - } - }, + var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2% - // Set aspect ratio - // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI - setAspectRatio: function setAspectRatio(input) { - var ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':'); - var padding = 100 / ratio[0] * ratio[1]; - this.elements.wrapper.style.paddingBottom = padding + '%'; + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min - if (this.supported.ui) { - var height = 240; - var offset = (height - padding) / (height / 50); + var volume = player.media.volume; - this.media.style.transform = 'translateY(-' + offset + '%)'; - } - }, + if (direction === 1 && volume < 1 || direction === -1 && volume > 0) { + event.preventDefault(); + } + }, 'volume', false); + } + }]); + return Listeners; + }(); - // API Ready - ready: function ready() { - var _this2 = this; + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - var player = this; - - // Get Vimeo params for the iframe - var options = { - loop: player.config.loop.active, - autoplay: player.autoplay, - // muted: player.muted, - byline: false, - portrait: false, - title: false, - speed: true, - transparent: 0, - gesture: 'media', - playsinline: !this.config.fullscreen.iosNative - }; - var params = utils.buildUrlParams(options); + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } - // Get the source URL or ID - var source = player.media.getAttribute('src'); + var loadjs_umd = createCommonjsModule(function (module, exports) { + (function(root, factory) { + { + module.exports = factory(); + } + }(commonjsGlobal, function() { + /** + * Global dependencies. + * @global {Object} document - DOM + */ + + var devnull = function() {}, + bundleIdCache = {}, + bundleResultCache = {}, + bundleCallbackQueue = {}; + + + /** + * Subscribe to bundle load event. + * @param {string[]} bundleIds - Bundle ids + * @param {Function} callbackFn - The callback function + */ + function subscribe(bundleIds, callbackFn) { + // listify + bundleIds = bundleIds.push ? bundleIds : [bundleIds]; + + var depsNotFound = [], + i = bundleIds.length, + numWaiting = i, + fn, + bundleId, + r, + q; + + // define callback function + fn = function (bundleId, pathsNotFound) { + if (pathsNotFound.length) depsNotFound.push(bundleId); + + numWaiting--; + if (!numWaiting) callbackFn(depsNotFound); + }; + + // register callback + while (i--) { + bundleId = bundleIds[i]; + + // execute callback if in result cache + r = bundleResultCache[bundleId]; + if (r) { + fn(bundleId, r); + continue; + } - // Get from <div> if needed - if (utils.is.empty(source)) { - source = player.media.getAttribute(player.config.attributes.embed.id); - } + // add to callback queue + q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; + q.push(fn); + } + } - var id = utils.parseVimeoId(source); - - // Build an iframe - var iframe = utils.createElement('iframe'); - var src = utils.format(player.config.urls.vimeo.iframe, id, params); - iframe.setAttribute('src', src); - iframe.setAttribute('allowfullscreen', ''); - iframe.setAttribute('allowtransparency', ''); - iframe.setAttribute('allow', 'autoplay'); - - // Inject the package - var wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer }); - wrapper.appendChild(iframe); - player.media = utils.replaceElement(wrapper, player.media); - - // Get poster image - utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(function (response) { - if (utils.is.empty(response)) { - return; - } - // Get the URL for thumbnail - var url = new URL(response[0].thumbnail_large); + /** + * Publish bundle load event. + * @param {string} bundleId - Bundle id + * @param {string[]} pathsNotFound - List of files not found + */ + function publish(bundleId, pathsNotFound) { + // exit if id isn't defined + if (!bundleId) return; - // Get original image - url.pathname = url.pathname.split('_')[0] + '.jpg'; + var q = bundleCallbackQueue[bundleId]; - // Set attribute - player.media.setAttribute('poster', url.href); + // cache result + bundleResultCache[bundleId] = pathsNotFound; - // Update - ui.setPoster.call(player); - }); + // exit if queue is empty + if (!q) return; - // Setup instance - // https://github.com/vimeo/player.js - player.embed = new window.Vimeo.Player(iframe, { - autopause: player.config.autopause, - muted: player.muted - }); + // empty callback queue + while (q.length) { + q[0](bundleId, pathsNotFound); + q.splice(0, 1); + } + } + + + /** + * Execute callbacks. + * @param {Object or Function} args - The callback args + * @param {string[]} depsNotFound - List of dependencies not found + */ + function executeCallbacks(args, depsNotFound) { + // accept function as argument + if (args.call) args = {success: args}; + + // success and error callbacks + if (depsNotFound.length) (args.error || devnull)(depsNotFound); + else (args.success || devnull)(args); + } - player.media.paused = true; - player.media.currentTime = 0; - // Disable native text track rendering - if (player.supported.ui) { - player.embed.disableTextTrack(); + /** + * Load individual file. + * @param {string} path - The file path + * @param {Function} callbackFn - The callback function + */ + function loadFile(path, callbackFn, args, numTries) { + var doc = document, + async = args.async, + maxTries = (args.numRetries || 0) + 1, + beforeCallbackFn = args.before || devnull, + pathStripped = path.replace(/^(css|img)!/, ''), + isCss, + e; + + numTries = numTries || 0; + + if (/(^css!|\.css$)/.test(path)) { + isCss = true; + + // css + e = doc.createElement('link'); + e.rel = 'stylesheet'; + e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix + } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { + // image + e = doc.createElement('img'); + e.src = pathStripped; + } else { + // javascript + e = doc.createElement('script'); + e.src = path; + e.async = async === undefined ? true : async; + } + + e.onload = e.onerror = e.onbeforeload = function (ev) { + var result = ev.type[0]; + + // Note: The following code isolates IE using `hideFocus` and treats empty + // stylesheets as failures to get around lack of onerror support + if (isCss && 'hideFocus' in e) { + try { + if (!e.sheet.cssText.length) result = 'e'; + } catch (x) { + // sheets objects created from load errors don't allow access to + // `cssText` (unless error is Code:18 SecurityError) + if (x.code != 18) result = 'e'; } + } - // Create a faux HTML5 API using the Vimeo API - player.media.play = function () { - player.embed.play().then(function () { - player.media.paused = false; - }); - }; + // handle retries in case of load failure + if (result == 'e') { + // increment counter + numTries += 1; - player.media.pause = function () { - player.embed.pause().then(function () { - player.media.paused = true; - }); - }; + // exit function and try again + if (numTries < maxTries) { + return loadFile(path, callbackFn, args, numTries); + } + } - player.media.stop = function () { - player.pause(); - player.currentTime = 0; - }; + // execute callback + callbackFn(path, result, ev.defaultPrevented); + }; - // Seeking - var currentTime = player.media.currentTime; + // add to document (unless callback returns `false`) + if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); + } - Object.defineProperty(player.media, 'currentTime', { - get: function get() { - return currentTime; - }, - set: function set(time) { - // Get current paused state - // Vimeo will automatically play on seek - var paused = player.media.paused; - // Set seeking flag + /** + * Load multiple files. + * @param {string[]} paths - The file paths + * @param {Function} callbackFn - The callback function + */ + function loadFiles(paths, callbackFn, args) { + // listify paths + paths = paths.push ? paths : [paths]; + + var numWaiting = paths.length, + x = numWaiting, + pathsNotFound = [], + fn, + i; + + // define callback function + fn = function(path, result, defaultPrevented) { + // handle error + if (result == 'e') pathsNotFound.push(path); + + // handle beforeload event. If defaultPrevented then that means the load + // will be blocked (ex. Ghostery/ABP on Safari) + if (result == 'b') { + if (defaultPrevented) pathsNotFound.push(path); + else return; + } - player.media.seeking = true; + numWaiting--; + if (!numWaiting) callbackFn(pathsNotFound); + }; - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); + // load scripts + for (i=0; i < x; i++) loadFile(paths[i], fn, args); + } - // Seek after events - player.embed.setCurrentTime(time).catch(function () { - // Do nothing - }); - // Restore pause state - if (paused) { - player.pause(); - } - } - }); + /** + * Initiate script load and register bundle. + * @param {(string|string[])} paths - The file paths + * @param {(string|Function)} [arg1] - The bundleId or success callback + * @param {Function} [arg2] - The success or error callback + * @param {Function} [arg3] - The error callback + */ + function loadjs(paths, arg1, arg2) { + var bundleId, + args; + + // bundleId (if string) + if (arg1 && arg1.trim) bundleId = arg1; + + // args (default is {}) + args = (bundleId ? arg2 : arg1) || {}; + + // throw error if bundle is already defined + if (bundleId) { + if (bundleId in bundleIdCache) { + throw "LoadJS"; + } else { + bundleIdCache[bundleId] = true; + } + } - // Playback speed - var speed = player.config.speed.selected; - Object.defineProperty(player.media, 'playbackRate', { - get: function get() { - return speed; - }, - set: function set(input) { - player.embed.setPlaybackRate(input).then(function () { - speed = input; - utils.dispatchEvent.call(player, player.media, 'ratechange'); - }).catch(function (error) { - // Hide menu item (and menu if empty) - if (error.name === 'Error') { - controls.setSpeedMenu.call(player, []); - } - }); - } - }); + // load scripts + loadFiles(paths, function (pathsNotFound) { + // execute callbacks + executeCallbacks(args, pathsNotFound); - // Volume - var volume = player.config.volume; + // publish bundle load event + publish(bundleId, pathsNotFound); + }, args); + } - Object.defineProperty(player.media, 'volume', { - get: function get() { - return volume; - }, - set: function set(input) { - player.embed.setVolume(input).then(function () { - volume = input; - utils.dispatchEvent.call(player, player.media, 'volumechange'); - }); - } - }); - // Muted - var muted = player.config.muted; + /** + * Execute callbacks when dependencies have been satisfied. + * @param {(string|string[])} deps - List of bundle ids + * @param {Object} args - success/error arguments + */ + loadjs.ready = function ready(deps, args) { + // subscribe to bundle load event + subscribe(deps, function (depsNotFound) { + // execute callbacks + executeCallbacks(args, depsNotFound); + }); - Object.defineProperty(player.media, 'muted', { - get: function get() { - return muted; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : false; + return loadjs; + }; - player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { - muted = toggle; - utils.dispatchEvent.call(player, player.media, 'volumechange'); - }); - } - }); - // Loop - var loop = player.config.loop; + /** + * Manually satisfy bundle dependencies. + * @param {string} bundleId - The bundle id + */ + loadjs.done = function done(bundleId) { + publish(bundleId, []); + }; - Object.defineProperty(player.media, 'loop', { - get: function get() { - return loop; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : player.config.loop.active; - player.embed.setLoop(toggle).then(function () { - loop = toggle; - }); - } - }); + /** + * Reset loadjs dependencies statuses + */ + loadjs.reset = function reset() { + bundleIdCache = {}; + bundleResultCache = {}; + bundleCallbackQueue = {}; + }; - // Source - var currentSrc = void 0; - player.embed.getVideoUrl().then(function (value) { - currentSrc = value; - }).catch(function (error) { - _this2.debug.warn(error); - }); - Object.defineProperty(player.media, 'currentSrc', { - get: function get() { - return currentSrc; - } - }); + /** + * Determine if bundle has already been defined + * @param String} bundleId - The bundle id + */ + loadjs.isDefined = function isDefined(bundleId) { + return bundleId in bundleIdCache; + }; - // Ended - Object.defineProperty(player.media, 'ended', { - get: function get() { - return player.currentTime === player.duration; - } - }); - // Set aspect ratio based on video size - Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { - var ratio = utils.getAspectRatio(dimensions[0], dimensions[1]); - vimeo.setAspectRatio.call(_this2, ratio); - }); + // export + return loadjs; - // Set autopause - player.embed.setAutopause(player.config.autopause).then(function (state) { - player.config.autopause = state; - }); + })); + }); - // Get title - player.embed.getVideoTitle().then(function (title) { - player.config.title = title; - ui.setTitle.call(_this2); - }); + // ========================================================================== + function loadScript(url) { + return new Promise(function (resolve, reject) { + loadjs_umd(url, { + success: resolve, + error: reject + }); + }); + } - // Get current time - player.embed.getCurrentTime().then(function (value) { - currentTime = value; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }); + function parseId(url) { + if (is.empty(url)) { + return null; + } - // Get duration - player.embed.getDuration().then(function (value) { - player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); - }); + if (is.number(Number(url))) { + return url; + } - // Get captions - player.embed.getTextTracks().then(function (tracks) { - player.media.textTracks = tracks; - captions.setup.call(player); - }); + var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) - player.embed.on('cuechange', function (data) { - var cue = null; - if (data.cues.length) { - cue = utils.stripHTML(data.cues[0].text); - } + function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } - captions.setText.call(player, cue); - }); + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } - player.embed.on('loaded', function () { - if (utils.is.element(player.embed.element) && player.supported.ui) { - var frame = player.embed.element; + var vimeo = { + setup: function setup() { + var _this = this; - // Fix keyboard focus issues - // https://github.com/sampotts/plyr/issues/317 - frame.setAttribute('tabindex', -1); - } - }); + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio - player.embed.on('play', function () { - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - utils.dispatchEvent.call(player, player.media, 'playing'); - }); + setAspectRatio.call(this); // Load the API if not already - player.embed.on('pause', function () { - player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'pause'); + if (!is.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk).then(function () { + vimeo.ready.call(_this); + }).catch(function (error) { + _this.debug.warn('Vimeo API failed to load', error); }); + } else { + vimeo.ready.call(this); + } + }, + // API Ready + ready: function ready$$1() { + var _this2 = this; - player.embed.on('timeupdate', function (data) { - player.media.seeking = false; - currentTime = data.seconds; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }); + var player = this; + var config = player.config.vimeo; // Get Vimeo params for the iframe - player.embed.on('progress', function (data) { - player.media.buffered = data.percent; - utils.dispatchEvent.call(player, player.media, 'progress'); + var params = buildUrlParams(extend({}, { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative + }, config)); // Get the source URL or ID - // Check all loaded - if (parseInt(data.percent, 10) === 1) { - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); - } + var source = player.media.getAttribute('src'); // Get from <div> if needed - // Get duration as if we do it before load, it gives an incorrect value - // https://github.com/sampotts/plyr/issues/891 - player.embed.getDuration().then(function (value) { - if (value !== player.media.duration) { - player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); - } - }); - }); + if (is.empty(source)) { + source = player.media.getAttribute(player.config.attributes.embed.id); + } - player.embed.on('seeked', function () { - player.media.seeking = false; - utils.dispatchEvent.call(player, player.media, 'seeked'); - utils.dispatchEvent.call(player, player.media, 'play'); - }); + var id = parseId(source); // Build an iframe - player.embed.on('ended', function () { - player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'ended'); - }); + var iframe = createElement('iframe'); + var src = format(player.config.urls.vimeo.iframe, id, params); + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + iframe.setAttribute('allowtransparency', ''); + iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set - player.embed.on('error', function (detail) { - player.media.error = detail; - utils.dispatchEvent.call(player, player.media, 'error'); - }); + var poster = player.poster; // Inject the package - // Rebuild UI - setTimeout(function () { - return ui.build.call(player); - }, 0); - } -}; + var wrapper = createElement('div', { + poster: poster, + class: player.config.classNames.embedContainer + }); + wrapper.appendChild(iframe); + player.media = replaceElement(wrapper, player.media); // Get poster image -// ========================================================================== + fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { + if (is.empty(response)) { + return; + } // Get the URL for thumbnail -// Standardise YouTube quality unit -function mapQualityUnit(input) { - switch (input) { - case 'hd2160': - return 2160; - case 2160: - return 'hd2160'; + var url = new URL(response[0].thumbnail_large); // Get original image - case 'hd1440': - return 1440; + url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster - case 1440: - return 'hd1440'; + ui.setPoster.call(player, url.href).catch(function () {}); + }); // Setup instance + // https://github.com/vimeo/player.js - case 'hd1080': - return 1080; + player.embed = new window.Vimeo.Player(iframe, { + autopause: player.config.autopause, + muted: player.muted + }); + player.media.paused = true; + player.media.currentTime = 0; // Disable native text track rendering - case 1080: - return 'hd1080'; + if (player.supported.ui) { + player.embed.disableTextTrack(); + } // Create a faux HTML5 API using the Vimeo API - case 'hd720': - return 720; - case 720: - return 'hd720'; + player.media.play = function () { + assurePlaybackState.call(player, true); + return player.embed.play(); + }; - case 'large': - return 480; + player.media.pause = function () { + assurePlaybackState.call(player, false); + return player.embed.pause(); + }; - case 480: - return 'large'; + player.media.stop = function () { + player.pause(); + player.currentTime = 0; + }; // Seeking - case 'medium': - return 360; - case 360: - return 'medium'; + var currentTime = player.media.currentTime; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return currentTime; + }, + set: function set(time) { + // Vimeo will automatically play on seek if the video hasn't been played before + // Get current paused state and volume etc + var embed = player.embed, + media = player.media, + paused = player.paused, + volume = player.volume; + var restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event + + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete + + Promise.resolve(restorePause && embed.setVolume(0)) // Seek + .then(function () { + return embed.setCurrentTime(time); + }) // Restore paused + .then(function () { + return restorePause && embed.pause(); + }) // Restore volume + .then(function () { + return restorePause && embed.setVolume(volume); + }).catch(function () {// Do nothing + }); + } + }); // Playback speed + + var speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return speed; + }, + set: function set(input) { + player.embed.setPlaybackRate(input).then(function () { + speed = input; + triggerEvent.call(player, player.media, 'ratechange'); + }).catch(function (error) { + // Hide menu item (and menu if empty) + if (error.name === 'Error') { + controls.setSpeedMenu.call(player, []); + } + }); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + player.embed.setVolume(input).then(function () { + volume = input; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : false; + player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { + muted = toggle; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Loop + + var loop = player.config.loop; + Object.defineProperty(player.media, 'loop', { + get: function get() { + return loop; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : player.config.loop.active; + player.embed.setLoop(toggle).then(function () { + loop = toggle; + }); + } + }); // Source + + var currentSrc; + player.embed.getVideoUrl().then(function (value) { + currentSrc = value; + controls.setDownloadLink.call(player); + }).catch(function (error) { + _this2.debug.warn(error); + }); + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return currentSrc; + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Set aspect ratio based on video size + + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { + var _dimensions = _slicedToArray(dimensions, 2), + width = _dimensions[0], + height = _dimensions[1]; + + player.embed.ratio = "".concat(width, ":").concat(height); + setAspectRatio.call(_this2, player.embed.ratio); + }); // Set autopause + + player.embed.setAutopause(player.config.autopause).then(function (state) { + player.config.autopause = state; + }); // Get title + + player.embed.getVideoTitle().then(function (title) { + player.config.title = title; + ui.setTitle.call(_this2); + }); // Get current time + + player.embed.getCurrentTime().then(function (value) { + currentTime = value; + triggerEvent.call(player, player.media, 'timeupdate'); + }); // Get duration + + player.embed.getDuration().then(function (value) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + }); // Get captions + + player.embed.getTextTracks().then(function (tracks) { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + player.embed.on('cuechange', function (_ref) { + var _ref$cues = _ref.cues, + cues = _ref$cues === void 0 ? [] : _ref$cues; + var strippedCues = cues.map(function (cue) { + return stripHTML(cue.text); + }); + captions.updateCues.call(player, strippedCues); + }); + player.embed.on('loaded', function () { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(function (paused) { + assurePlaybackState.call(player, !paused); + + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); - case 'small': - return 240; + if (is.element(player.embed.element) && player.supported.ui) { + var frame = player.embed.element; // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 + + frame.setAttribute('tabindex', -1); + } + }); + player.embed.on('play', function () { + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); + }); + player.embed.on('pause', function () { + assurePlaybackState.call(player, false); + }); + player.embed.on('timeupdate', function (data) { + player.media.seeking = false; + currentTime = data.seconds; + triggerEvent.call(player, player.media, 'timeupdate'); + }); + player.embed.on('progress', function (data) { + player.media.buffered = data.percent; + triggerEvent.call(player, player.media, 'progress'); // Check all loaded + + if (parseInt(data.percent, 10) === 1) { + triggerEvent.call(player, player.media, 'canplaythrough'); + } // Get duration as if we do it before load, it gives an incorrect value + // https://github.com/sampotts/plyr/issues/891 - case 240: - return 'small'; - default: - return 'default'; + player.embed.getDuration().then(function (value) { + if (value !== player.media.duration) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + } + }); + }); + player.embed.on('seeked', function () { + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + }); + player.embed.on('ended', function () { + player.media.paused = true; + triggerEvent.call(player, player.media, 'ended'); + }); + player.embed.on('error', function (detail) { + player.media.error = detail; + triggerEvent.call(player, player.media, 'error'); + }); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 0); } -} + }; + + // ========================================================================== -function mapQualityUnits(levels) { - if (utils.is.empty(levels)) { - return levels; + function parseId$1(url) { + if (is.empty(url)) { + return null; } - return utils.dedupe(levels.map(function (level) { - return mapQualityUnit(level); - })); -} + var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) -var youtube = { - setup: function setup() { - var _this = this; - // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + function assurePlaybackState$1(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } - // Set aspect ratio - youtube.setAspectRatio.call(this); + var youtube = { + setup: function setup() { + var _this = this; - // Setup API - if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) { - youtube.ready.call(this); - } else { - // Load the API - utils.loadScript(this.config.urls.youtube.sdk).catch(function (error) { - _this.debug.warn('YouTube API failed to load', error); - }); + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio - // Setup callback for the API - // YouTube has it's own system of course... - window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; + setAspectRatio.call(this); // Setup API - // Add to queue - window.onYouTubeReadyCallbacks.push(function () { - youtube.ready.call(_this); - }); + if (is.object(window.YT) && is.function(window.YT.Player)) { + youtube.ready.call(this); + } else { + // Load the API + loadScript(this.config.urls.youtube.sdk).catch(function (error) { + _this.debug.warn('YouTube API failed to load', error); + }); // Setup callback for the API + // YouTube has it's own system of course... - // Set callback to process queue - window.onYouTubeIframeAPIReady = function () { - window.onYouTubeReadyCallbacks.forEach(function (callback) { - callback(); - }); - }; - } - }, + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue + window.onYouTubeReadyCallbacks.push(function () { + youtube.ready.call(_this); + }); // Set callback to process queue + window.onYouTubeIframeAPIReady = function () { + window.onYouTubeReadyCallbacks.forEach(function (callback) { + callback(); + }); + }; + } + }, // Get the media title getTitle: function getTitle(videoId) { - var _this2 = this; + var _this2 = this; - // Try via undocumented API method first - // This method disappears now and then though... - // https://github.com/sampotts/plyr/issues/709 - if (utils.is.function(this.embed.getVideoData)) { - var _embed$getVideoData = this.embed.getVideoData(), - title = _embed$getVideoData.title; - - if (utils.is.empty(title)) { - this.config.title = title; - ui.setTitle.call(this); - return; - } + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (is.function(this.embed.getVideoData)) { + var _this$embed$getVideoD = this.embed.getVideoData(), + title = _this$embed$getVideoD.title; + + if (is.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; } + } // Or via Google API - // Or via Google API - var key = this.config.keys.google; - if (utils.is.string(key) && !utils.is.empty(key)) { - var url = utils.format(this.config.urls.youtube.api, videoId, key); - utils.fetch(url).then(function (result) { - if (utils.is.object(result)) { - _this2.config.title = result.items[0].snippet.title; - ui.setTitle.call(_this2); - } - }).catch(function () {}); - } + var key = this.config.keys.google; + + if (is.string(key) && !is.empty(key)) { + var url = format(this.config.urls.youtube.api, videoId, key); + fetch(url).then(function (result) { + if (is.object(result)) { + _this2.config.title = result.items[0].snippet.title; + ui.setTitle.call(_this2); + } + }).catch(function () {}); + } }, + // API ready + ready: function ready$$1() { + var player = this; // Ignore already setup (race condition) + var currentId = player.media.getAttribute('id'); - // Set aspect ratio - setAspectRatio: function setAspectRatio() { - var ratio = this.config.ratio.split(':'); - this.elements.wrapper.style.paddingBottom = 100 / ratio[0] * ratio[1] + '%'; - }, + if (!is.empty(currentId) && currentId.startsWith('youtube-')) { + return; + } // Get the source URL or ID + + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is.empty(source)) { + source = player.media.getAttribute(this.config.attributes.embed.id); + } // Replace the <iframe> with a <div> due to YouTube API issues + + + var videoId = parseId$1(source); + var id = generateId(player.provider); // Get poster, if already set + + var poster = player.poster; // Replace media element + + var container = createElement('div', { + id: id, + poster: poster + }); + player.media = replaceElement(container, player.media); // Id to poster wrapper + + var posterSrc = function posterSrc(format$$1) { + return "https://img.youtube.com/vi/".concat(videoId, "/").concat(format$$1, "default.jpg"); + }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + + + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(function () { + return loadImage(posterSrc('sd'), 121); + }) // 480p padded 4:3 + .catch(function () { + return loadImage(posterSrc('hq')); + }) // 360p padded 4:3. Always exists + .then(function (image) { + return ui.setPoster.call(player, image.src); + }).then(function (posterSrc) { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }).catch(function () {}); + var config = player.config.youtube; // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + + player.embed = new window.YT.Player(id, { + videoId: videoId, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend({}, { + autoplay: player.config.autoplay ? 1 : 0, + // Autoplay + hl: player.config.hl, + // iframe interface language + controls: player.supported.ui ? 0 : 1, + // Only show controls if not fully supported + disablekb: 1, + // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, + // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null + }, config), + events: { + onError: function onError(event) { + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + var code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + + var message = { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.' + }[code] || 'An unknown error occured'; + player.media.error = { + code: code, + message: message + }; + triggerEvent.call(player, player.media, 'error'); + } + }, + onPlaybackRateChange: function onPlaybackRateChange(event) { + // Get the instance + var instance = event.target; // Get current speed + + player.media.playbackRate = instance.getPlaybackRate(); + triggerEvent.call(player, player.media, 'ratechange'); + }, + onReady: function onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is.function(player.media.play)) { + return; + } // Get the instance + + + var instance = event.target; // Get the title + + youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API + + player.media.play = function () { + assurePlaybackState$1.call(player, true); + instance.playVideo(); + }; + player.media.pause = function () { + assurePlaybackState$1.call(player, false); + instance.pauseVideo(); + }; - // API ready - ready: function ready() { - var player = this; + player.media.stop = function () { + instance.stopVideo(); + }; - // Ignore already setup (race condition) - var currentId = player.media.getAttribute('id'); - if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) { - return; - } + player.media.duration = instance.getDuration(); + player.media.paused = true; // Seeking - // Get the source URL or ID - var source = player.media.getAttribute('src'); + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return Number(instance.getCurrentTime()); + }, + set: function set(time) { + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } // Set seeking state and trigger event - // Get from <div> if needed - if (utils.is.empty(source)) { - source = player.media.getAttribute(this.config.attributes.embed.id); - } - // Replace the <iframe> with a <div> due to YouTube API issues - var videoId = utils.parseYouTubeId(source); - var id = utils.generateId(player.provider); - var container = utils.createElement('div', { id: id }); - player.media = utils.replaceElement(container, player.media); - - // Set poster image - player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId)); - - // Setup instance - // https://developers.google.com/youtube/iframe_api_reference - player.embed = new window.YT.Player(id, { - videoId: videoId, - playerVars: { - autoplay: player.config.autoplay ? 1 : 0, // Autoplay - controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported - rel: 0, // No related vids - showinfo: 0, // Hide info - iv_load_policy: 3, // Hide annotations - modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) - disablekb: 1, // Disable keyboard as we handle it - playsinline: 1, // Allow iOS inline playback - - // Tracking for stats - // origin: window ? `${window.location.protocol}//${window.location.host}` : null, - widget_referrer: window ? window.location.href : null, - - // Captions are flaky on YouTube - cc_load_policy: player.captions.active ? 1 : 0, - cc_lang_pref: player.config.captions.language - }, - events: { - onError: function onError(event) { - // If we've already fired an error, don't do it again - // YouTube fires onError twice - if (utils.is.object(player.media.error)) { - return; - } - - var detail = { - code: event.data - }; + player.media.seeking = true; + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent + + instance.seekTo(time); + } + }); // Playback speed + + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return instance.getPlaybackRate(); + }, + set: function set(input) { + instance.setPlaybackRate(input); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + volume = input; + instance.setVolume(volume * 100); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Source + + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return instance.getVideoUrl(); + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Get available speeds - // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError - switch (event.data) { - case 2: - detail.message = 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.'; - break; - - case 5: - detail.message = 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.'; - break; - - case 100: - detail.message = 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.'; - break; - - case 101: - case 150: - detail.message = 'The owner of the requested video does not allow it to be played in embedded players.'; - break; - - default: - detail.message = 'An unknown error occured'; - break; - } - - player.media.error = detail; - - utils.dispatchEvent.call(player, player.media, 'error'); - }, - onPlaybackQualityChange: function onPlaybackQualityChange() { - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { - quality: player.media.quality - }); - }, - onPlaybackRateChange: function onPlaybackRateChange(event) { - // Get the instance - var instance = event.target; - - // Get current speed - player.media.playbackRate = instance.getPlaybackRate(); - - utils.dispatchEvent.call(player, player.media, 'ratechange'); - }, - onReady: function onReady(event) { - // Get the instance - var instance = event.target; - - // Get the title - youtube.getTitle.call(player, videoId); - - // Create a faux HTML5 API using the YouTube API - player.media.play = function () { - instance.playVideo(); - }; + player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe - player.media.pause = function () { - instance.pauseVideo(); - }; + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } - player.media.stop = function () { - instance.stopVideo(); - }; + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer + + clearInterval(player.timers.buffering); // Setup buffering + + player.timers.buffering = setInterval(function () { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something + + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + triggerEvent.call(player, player.media, 'progress'); + } // Set last buffer point + + + player.media.lastBuffered = player.media.buffered; // Bail if we're at 100% + + if (player.media.buffered === 1) { + clearInterval(player.timers.buffering); // Trigger event + + triggerEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 50); + }, + onStateChange: function onStateChange(event) { + // Get the instance + var instance = event.target; // Reset timer + + clearInterval(player.timers.playing); + var seeked = player.media.seeking && [1, 2].includes(event.data); + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued + + + switch (event.data) { + case -1: + // Update scrubber + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube + + player.media.buffered = instance.getVideoLoadedFraction(); + triggerEvent.call(player, player.media, 'progress'); + break; + + case 0: + assurePlaybackState$1.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. + + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + triggerEvent.call(player, player.media, 'ended'); + } + + break; + + case 1: + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState$1.call(player, true); + triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress + + player.timers.playing = setInterval(function () { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + + if (player.media.duration !== instance.getDuration()) { player.media.duration = instance.getDuration(); - player.media.paused = true; - - // Seeking - player.media.currentTime = 0; - Object.defineProperty(player.media, 'currentTime', { - get: function get() { - return Number(instance.getCurrentTime()); - }, - set: function set(time) { - // Vimeo will automatically play on seek - var paused = player.media.paused; - - // Set seeking flag - - player.media.seeking = true; - - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); - - // Seek after events sent - instance.seekTo(time); - - // Restore pause state - if (paused) { - player.pause(); - } - } - }); - - // Playback speed - Object.defineProperty(player.media, 'playbackRate', { - get: function get() { - return instance.getPlaybackRate(); - }, - set: function set(input) { - instance.setPlaybackRate(input); - } - }); - - // Quality - Object.defineProperty(player.media, 'quality', { - get: function get() { - return mapQualityUnit(instance.getPlaybackQuality()); - }, - set: function set(input) { - var quality = input; - - // Set via API - instance.setPlaybackQuality(mapQualityUnit(quality)); - - // Trigger request event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality: quality - }); - } - }); - - // Volume - var volume = player.config.volume; - - Object.defineProperty(player.media, 'volume', { - get: function get() { - return volume; - }, - set: function set(input) { - volume = input; - instance.setVolume(volume * 100); - utils.dispatchEvent.call(player, player.media, 'volumechange'); - } - }); - - // Muted - var muted = player.config.muted; - - Object.defineProperty(player.media, 'muted', { - get: function get() { - return muted; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : muted; - muted = toggle; - instance[toggle ? 'mute' : 'unMute'](); - utils.dispatchEvent.call(player, player.media, 'volumechange'); - } - }); - - // Source - Object.defineProperty(player.media, 'currentSrc', { - get: function get() { - return instance.getVideoUrl(); - } - }); - - // Ended - Object.defineProperty(player.media, 'ended', { - get: function get() { - return player.currentTime === player.duration; - } - }); - - // Get available speeds - player.options.speed = instance.getAvailablePlaybackRates(); - - // Set the tabindex to avoid focus entering iframe - if (player.supported.ui) { - player.media.setAttribute('tabindex', -1); - } - - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - utils.dispatchEvent.call(player, player.media, 'durationchange'); - - // Reset timer - clearInterval(player.timers.buffering); - - // Setup buffering - player.timers.buffering = setInterval(function () { - // Get loaded % from YouTube - player.media.buffered = instance.getVideoLoadedFraction(); - - // Trigger progress only when we actually buffer something - if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { - utils.dispatchEvent.call(player, player.media, 'progress'); - } - - // Set last buffer point - player.media.lastBuffered = player.media.buffered; - - // Bail if we're at 100% - if (player.media.buffered === 1) { - clearInterval(player.timers.buffering); - - // Trigger event - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); - } - }, 200); - - // Rebuild UI - setTimeout(function () { - return ui.build.call(player); - }, 50); - }, - onStateChange: function onStateChange(event) { - // Get the instance - var instance = event.target; - - // Reset timer - clearInterval(player.timers.playing); - - // Handle events - // -1 Unstarted - // 0 Ended - // 1 Playing - // 2 Paused - // 3 Buffering - // 5 Video cued - switch (event.data) { - case -1: - // Update scrubber - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - - // Get loaded % from YouTube - player.media.buffered = instance.getVideoLoadedFraction(); - utils.dispatchEvent.call(player, player.media, 'progress'); - - break; - - case 0: - player.media.paused = true; - - // YouTube doesn't support loop for a single video, so mimick it. - if (player.media.loop) { - // YouTube needs a call to `stopVideo` before playing again - instance.stopVideo(); - instance.playVideo(); - } else { - utils.dispatchEvent.call(player, player.media, 'ended'); - } - - break; - - case 1: - // If we were seeking, fire seeked event - if (player.media.seeking) { - utils.dispatchEvent.call(player, player.media, 'seeked'); - } - player.media.seeking = false; - - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - - utils.dispatchEvent.call(player, player.media, 'playing'); - - // Poll to get playback progress - player.timers.playing = setInterval(function () { - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }, 50); - - // Check duration again due to YouTube bug - // https://github.com/sampotts/plyr/issues/374 - // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - if (player.media.duration !== instance.getDuration()) { - player.media.duration = instance.getDuration(); - utils.dispatchEvent.call(player, player.media, 'durationchange'); - } - - // Get quality - controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels())); - - break; - - case 2: - player.media.paused = true; - - utils.dispatchEvent.call(player, player.media, 'pause'); - - break; - - default: - break; - } - - utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, { - code: event.data - }); + triggerEvent.call(player, player.media, 'durationchange'); + } } + + break; + + case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } + + assurePlaybackState$1.call(player, false); + break; + + default: + break; } - }); - } -}; -// ========================================================================== + triggerEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data + }); + } + } + }); + } + }; -var media = { + // ========================================================================== + var media = { // Setup media setup: function setup() { - // If there's no media, bail - if (!this.media) { - this.debug.warn('No media element found!'); - return; - } + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } // Add type class - // Add type class - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); - // Add provider class - utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class - // Add video class for embeds - // This will require changes if audio embeds are added - if (this.isEmbed) { - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); - } + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds + // This will require changes if audio embeds are added - // Inject the player wrapper - if (this.isVideo) { - // Create the wrapper div - this.elements.wrapper = utils.createElement('div', { - class: this.config.classNames.video - }); + if (this.isEmbed) { + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } // Inject the player wrapper - // Wrap the video in a container - utils.wrap(this.media, this.elements.wrapper); - // Faux poster container - this.elements.poster = utils.createElement('div', { - class: this.config.classNames.poster - }); + if (this.isVideo) { + // Create the wrapper div + this.elements.wrapper = createElement('div', { + class: this.config.classNames.video + }); // Wrap the video in a container - this.elements.wrapper.appendChild(this.elements.poster); - } - - if (this.isEmbed) { - switch (this.provider) { - case 'youtube': - youtube.setup.call(this); - break; + wrap(this.media, this.elements.wrapper); // Faux poster container - case 'vimeo': - vimeo.setup.call(this); - break; + this.elements.poster = createElement('div', { + class: this.config.classNames.poster + }); + this.elements.wrapper.appendChild(this.elements.poster); + } - default: - break; - } - } else if (this.isHTML5) { - html5.extend.call(this); - } + if (this.isHTML5) { + html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); + } } -}; - -// ========================================================================== + }; -var Ads = function () { + var Ads = + /*#__PURE__*/ + function () { /** * Ads constructor. * @param {object} player * @return {Ads} */ function Ads(player) { - var _this = this; + var _this = this; + + _classCallCheck(this, Ads); + + this.player = player; + this.config = player.config.ads; + this.playing = false; + this.initialized = false; + this.elements = { + container: null, + displayContainer: null + }; + this.manager = null; + this.loader = null; + this.cuePoints = null; + this.events = {}; + this.safetyTimer = null; + this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready + + this.managerPromise = new Promise(function (resolve, reject) { + // The ad is loaded and ready + _this.on('loaded', resolve); // Ads failed + + + _this.on('error', reject); + }); + this.load(); + } - classCallCheck(this, Ads); + _createClass(Ads, [{ + key: "load", - this.player = player; - this.publisherId = player.config.ads.publisherId; - this.playing = false; - this.initialized = false; - this.elements = { - container: null, - displayContainer: null - }; - this.manager = null; - this.loader = null; - this.cuePoints = null; - this.events = {}; - this.safetyTimer = null; - this.countdownTimer = null; - - // Setup a promise to resolve when the IMA manager is ready - this.managerPromise = new Promise(function (resolve, reject) { - // The ad is loaded and ready - _this.on('loaded', resolve); - - // Ads failed - _this.on('error', reject); + /** + * Load the IMA SDK + */ + value: function load() { + var _this2 = this; + + if (this.enabled) { + // Check if the Google IMA3 SDK is loaded or load it ourselves + if (!is.object(window.google) || !is.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); + } + } + } + /** + * Get the ads instance ready + */ + + }, { + key: "ready", + value: function ready$$1() { + var _this3 = this; + + // Start ticking our safety timer. If the whole advertisement + // thing doesn't resolve within our set time; we bail + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer + + this.managerPromise.then(function () { + _this3.clearSafetyTimer('onAdsManagerLoaded()'); + }); // Set listeners on the Plyr instance + + this.listeners(); // Setup the IMA SDK + + this.setupIMA(); + } // Build the tag URL + + }, { + key: "setupIMA", + + /** + * In order for the SDK to display ads for our video, we need to tell it where to put them, + * so here we define our ad container. This div is set up to render on top of the video player. + * Using the code below, we tell the SDK to render ads within that div. We also provide a + * handle to the content video player - the SDK will poll the current time of our player to + * properly place mid-rolls. After we create the ad display container, we initialize it. On + * mobile devices, this initialization is done as the result of a user action. + */ + value: function setupIMA() { + // Create the container for our advertisements + this.elements.container = createElement('div', { + class: this.player.config.classNames.ads }); + this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2 - this.load(); - } + google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language - createClass(Ads, [{ - key: 'load', - - - /** - * Load the IMA SDK - */ - value: function load() { - var _this2 = this; - - if (this.enabled) { - // Check if the Google IMA3 SDK is loaded or load it ourselves - if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) { - utils.loadScript(this.player.config.urls.googleIMA.sdk).then(function () { - _this2.ready(); - }).catch(function () { - // Script failed to load or is blocked - _this2.trigger('error', new Error('Google IMA SDK failed to load')); - }); - } else { - this.ready(); - } - } - } + google.ima.settings.setLocale(this.player.config.ads.language); // We assume the adContainer is the video container of the plyr element + // that will house the ads + + this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); // Request video ads to be pre-loaded - /** - * Get the ads instance ready - */ + this.requestAds(); + } + /** + * Request advertisements + */ }, { - key: 'ready', - value: function ready() { - var _this3 = this; + key: "requestAds", + value: function requestAds() { + var _this4 = this; - // Start ticking our safety timer. If the whole advertisement - // thing doesn't resolve within our set time; we bail - this.startSafetyTimer(12000, 'ready()'); + var container = this.player.elements.container; - // Clear the safety timer - this.managerPromise.then(function () { - _this3.clearSafetyTimer('onAdsManagerLoaded()'); - }); + try { + // Create ads loader + this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events - // Set listeners on the Plyr instance - this.listeners(); + this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { + return _this4.onAdsManagerLoaded(event); + }, false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this4.onAdError(error); + }, false); // Request video ads - // Setup the IMA SDK - this.setupIMA(); - } + var request = new google.ima.AdsRequest(); + request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK + // to select the correct creative if multiple are returned - // Build the default tag URL + request.linearAdSlotWidth = container.offsetWidth; + request.linearAdSlotHeight = container.offsetHeight; + request.nonLinearAdSlotWidth = container.offsetWidth; + request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video. - }, { - key: 'setupIMA', - - - /** - * In order for the SDK to display ads for our video, we need to tell it where to put them, - * so here we define our ad container. This div is set up to render on top of the video player. - * Using the code below, we tell the SDK to render ads within that div. We also provide a - * handle to the content video player - the SDK will poll the current time of our player to - * properly place mid-rolls. After we create the ad display container, we initialize it. On - * mobile devices, this initialization is done as the result of a user action. - */ - value: function setupIMA() { - // Create the container for our advertisements - this.elements.container = utils.createElement('div', { - class: this.player.config.classNames.ads - }); - this.player.elements.container.appendChild(this.elements.container); + request.forceNonLinearFullSlot = false; // Mute based on current state - // So we can run VPAID2 - google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); + request.setAdWillPlayMuted(!this.player.muted); + this.loader.requestAds(request); + } catch (e) { + this.onAdError(e); + } + } + /** + * Update the ad countdown + * @param {boolean} start + */ - // Set language - google.ima.settings.setLocale(this.player.config.ads.language); + }, { + key: "pollCountdown", + value: function pollCountdown() { + var _this5 = this; - // We assume the adContainer is the video container of the plyr element - // that will house the ads - this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); + var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - // Request video ads to be pre-loaded - this.requestAds(); + if (!start) { + clearInterval(this.countdownTimer); + this.elements.container.removeAttribute('data-badge-text'); + return; } - /** - * Request advertisements - */ + var update = function update() { + var time = formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); + var label = "".concat(i18n.get('advertisement', _this5.player.config), " - ").concat(time); + + _this5.elements.container.setAttribute('data-badge-text', label); + }; + + this.countdownTimer = setInterval(update, 100); + } + /** + * This method is called whenever the ads are ready inside the AdDisplayContainer + * @param {Event} adsManagerLoadedEvent + */ }, { - key: 'requestAds', - value: function requestAds() { - var _this4 = this; + key: "onAdsManagerLoaded", + value: function onAdsManagerLoaded(event) { + var _this6 = this; - var container = this.player.elements.container; + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } // Get the ads manager - try { - // Create ads loader - this.loader = new google.ima.AdsLoader(this.elements.displayContainer); - - // Listen and respond to ads loaded and error events - this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { - return _this4.onAdsManagerLoaded(event); - }, false); - this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { - return _this4.onAdError(error); - }, false); - - // Request video ads - var request = new google.ima.AdsRequest(); - request.adTagUrl = this.tagUrl; - - // Specify the linear and nonlinear slot sizes. This helps the SDK - // to select the correct creative if multiple are returned - request.linearAdSlotWidth = container.offsetWidth; - request.linearAdSlotHeight = container.offsetHeight; - request.nonLinearAdSlotWidth = container.offsetWidth; - request.nonLinearAdSlotHeight = container.offsetHeight; - - // We only overlay ads as we only support video. - request.forceNonLinearFullSlot = false; - - // Mute based on current state - request.setAdWillPlayMuted(!this.player.muted); - - this.loader.requestAds(request); - } catch (e) { - this.onAdError(e); - } - } + var settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf - /** - * Update the ad countdown - * @param {boolean} start - */ + settings.restoreCustomPlaybackStateOnAdBreakComplete = true; + settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration + // so it can determine when to start the mid- and post-roll - }, { - key: 'pollCountdown', - value: function pollCountdown() { - var _this5 = this; + this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll + + this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available - var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + if (!is.empty(this.cuePoints)) { + this.cuePoints.forEach(function (cuePoint) { + if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { + var seekElement = _this6.player.elements.progress; - if (!start) { - clearInterval(this.countdownTimer); - this.elements.container.removeAttribute('data-badge-text'); - return; + if (is.element(seekElement)) { + var cuePercentage = 100 / _this6.player.duration * cuePoint; + var cue = createElement('span', { + class: _this6.player.config.classNames.cues + }); + cue.style.left = "".concat(cuePercentage.toString(), "%"); + seekElement.appendChild(cue); + } } + }); + } // Set volume to match player - var update = function update() { - var time = utils.formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); - var label = i18n.get('advertisement', _this5.player.config) + ' - ' + time; - _this5.elements.container.setAttribute('data-badge-text', label); - }; - this.countdownTimer = setInterval(update, 100); - } + this.manager.setVolume(this.player.volume); // Add listeners to the required events + // Advertisement error events + + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this6.onAdError(error); + }); // Advertisement regular events - /** - * This method is called whenever the ads are ready inside the AdDisplayContainer - * @param {Event} adsManagerLoadedEvent - */ + Object.keys(google.ima.AdEvent.Type).forEach(function (type) { + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { + return _this6.onAdEvent(event); + }); + }); // Resolve our adsManager + + this.trigger('loaded'); + } + /** + * This is where all the event handling takes place. Retrieve the ad from the event. Some + * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated + * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type + * @param {Event} event + */ }, { - key: 'onAdsManagerLoaded', - value: function onAdsManagerLoaded(event) { - var _this6 = this; - - // Get the ads manager - var settings = new google.ima.AdsRenderingSettings(); - - // Tell the SDK to save and restore content video state on our behalf - settings.restoreCustomPlaybackStateOnAdBreakComplete = true; - settings.enablePreloading = true; - - // The SDK is polling currentTime on the contentPlayback. And needs a duration - // so it can determine when to start the mid- and post-roll - this.manager = event.getAdsManager(this.player, settings); - - // Get the cue points for any mid-rolls by filtering out the pre- and post-roll - this.cuePoints = this.manager.getCuePoints(); - - // Add advertisement cue's within the time line if available - if (!utils.is.empty(this.cuePoints)) { - this.cuePoints.forEach(function (cuePoint) { - if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { - var seekElement = _this6.player.elements.progress; - - if (utils.is.element(seekElement)) { - var cuePercentage = 100 / _this6.player.duration * cuePoint; - var cue = utils.createElement('span', { - class: _this6.player.config.classNames.cues - }); - - cue.style.left = cuePercentage.toString() + '%'; - seekElement.appendChild(cue); - } - } - }); - } + key: "onAdEvent", + value: function onAdEvent(event) { + var _this7 = this; - // Get skippable state - // TODO: Skip button - // this.player.debug.warn(this.manager.getAdSkippableState()); + var container = this.player.elements.container; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) + // don't have ad object associated - // Set volume to match player - this.manager.setVolume(this.player.volume); + var ad = event.getAd(); + var adData = event.getAdData(); // Proxy event - // Add listeners to the required events - // Advertisement error events - this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { - return _this6.onAdError(error); - }); + var dispatchEvent = function dispatchEvent(type) { + var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); + triggerEvent.call(_this7.player, _this7.player.media, event); + }; - // Advertisement regular events - Object.keys(google.ima.AdEvent.Type).forEach(function (type) { - _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { - return _this6.onAdEvent(event); - }); - }); + switch (event.type) { + case google.ima.AdEvent.Type.LOADED: + // This is the first event sent for an ad - it is possible to determine whether the + // ad is a video ad or an overlay + this.trigger('loaded'); // Bubble event + + dispatchEvent(event.type); // Start countdown + + this.pollCountdown(true); + + if (!ad.isLinear()) { + // Position AdDisplayContainer correctly for overlay + ad.width = container.offsetWidth; + ad.height = container.offsetHeight; + } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); + // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); + + + break; + + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: + // All ads for the current videos are done. We can now request new advertisements + // in case the video is re-played + // Fire event + dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // So here we load a new video when all ads are done. + // Then we load new ads within a new adsManager. When the video + // Is started - after - the ads are loaded, then we get ads. + // You can also easily test cancelling and reloading by running + // player.ads.cancel() and player.ads.play from the console I guess. + // this.player.source = { + // type: 'video', + // title: 'View From A Blue Moon', + // sources: [{ + // src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: + // 'video/mp4', }], poster: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: + // [ { kind: 'captions', label: 'English', srclang: 'en', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], + // }; + // TODO: So there is still this thing where a video should only be allowed to start + // playing when the IMA SDK is ready or has failed - // Resolve our adsManager - this.trigger('loaded'); + this.loadAds(); + break; + + case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: + // This event indicates the ad has started - the video player can adjust the UI, + // for example display a pause button and remaining time. Fired when content should + // be paused. This usually happens right before an ad is about to cover the content + dispatchEvent(event.type); + this.pauseContent(); + break; + + case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: + // This event indicates the ad has finished - the video player can perform + // appropriate UI actions, such as removing the timer for remaining time detection. + // Fired when content should be resumed. This usually happens when an ad finishes + // or collapses + dispatchEvent(event.type); + this.pollCountdown(); + this.resumeContent(); + break; + + case google.ima.AdEvent.Type.STARTED: + case google.ima.AdEvent.Type.MIDPOINT: + case google.ima.AdEvent.Type.COMPLETE: + case google.ima.AdEvent.Type.IMPRESSION: + case google.ima.AdEvent.Type.CLICK: + dispatchEvent(event.type); + break; + + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); + } + + break; + + default: + break; } + } + /** + * Any ad error handling comes through here + * @param {Event} event + */ - /** - * This is where all the event handling takes place. Retrieve the ad from the event. Some - * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated - * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type - * @param {Event} event - */ + }, { + key: "onAdError", + value: function onAdError(event) { + this.cancel(); + this.player.debug.warn('Ads error', event); + } + /** + * Setup hooks for Plyr and window events. This ensures + * the mid- and post-roll launch at the correct time. And + * resize the advertisement when the player resizes + */ }, { - key: 'onAdEvent', - value: function onAdEvent(event) { - var _this7 = this; + key: "listeners", + value: function listeners() { + var _this8 = this; - var container = this.player.elements.container; + var container = this.player.elements.container; + var time; // Add listeners to the required events - // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) - // don't have ad object associated + this.player.on('ended', function () { + _this8.loader.contentComplete(); + }); + this.player.on('timeupdate', function () { + time = _this8.player.currentTime; + }); + this.player.on('seeked', function () { + var seekedTime = _this8.player.currentTime; - var ad = event.getAd(); + if (is.empty(_this8.cuePoints)) { + return; + } - // Proxy event - var dispatchEvent = function dispatchEvent(type) { - var event = 'ads' + type.replace(/_/g, '').toLowerCase(); - utils.dispatchEvent.call(_this7.player, _this7.player.media, event); - }; + _this8.cuePoints.forEach(function (cuePoint, index) { + if (time < cuePoint && cuePoint < seekedTime) { + _this8.manager.discardAdBreak(); - switch (event.type) { - case google.ima.AdEvent.Type.LOADED: - // This is the first event sent for an ad - it is possible to determine whether the - // ad is a video ad or an overlay - this.trigger('loaded'); - - // Bubble event - dispatchEvent(event.type); - - // Start countdown - this.pollCountdown(true); - - if (!ad.isLinear()) { - // Position AdDisplayContainer correctly for overlay - ad.width = container.offsetWidth; - ad.height = container.offsetHeight; - } - - // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); - // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); - break; - - case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: - // All ads for the current videos are done. We can now request new advertisements - // in case the video is re-played - - // Fire event - dispatchEvent(event.type); - - // TODO: Example for what happens when a next video in a playlist would be loaded. - // So here we load a new video when all ads are done. - // Then we load new ads within a new adsManager. When the video - // Is started - after - the ads are loaded, then we get ads. - // You can also easily test cancelling and reloading by running - // player.ads.cancel() and player.ads.play from the console I guess. - // this.player.source = { - // type: 'video', - // title: 'View From A Blue Moon', - // sources: [{ - // src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: - // 'video/mp4', }], poster: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: - // [ { kind: 'captions', label: 'English', srclang: 'en', src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', - // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], - // }; - - // TODO: So there is still this thing where a video should only be allowed to start - // playing when the IMA SDK is ready or has failed - - this.loadAds(); - break; - - case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: - // This event indicates the ad has started - the video player can adjust the UI, - // for example display a pause button and remaining time. Fired when content should - // be paused. This usually happens right before an ad is about to cover the content - - dispatchEvent(event.type); - - this.pauseContent(); - - break; - - case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: - // This event indicates the ad has finished - the video player can perform - // appropriate UI actions, such as removing the timer for remaining time detection. - // Fired when content should be resumed. This usually happens when an ad finishes - // or collapses - - dispatchEvent(event.type); - - this.pollCountdown(); - - this.resumeContent(); - - break; - - case google.ima.AdEvent.Type.STARTED: - case google.ima.AdEvent.Type.MIDPOINT: - case google.ima.AdEvent.Type.COMPLETE: - case google.ima.AdEvent.Type.IMPRESSION: - case google.ima.AdEvent.Type.CLICK: - dispatchEvent(event.type); - break; - - default: - break; + _this8.cuePoints.splice(index, 1); } - } + }); + }); // Listen to the resizing of the window. And resize ad accordingly + // TODO: eventually implement ResizeObserver - /** - * Any ad error handling comes through here - * @param {Event} event - */ + window.addEventListener('resize', function () { + if (_this8.manager) { + _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); + } + }); + } + /** + * Initialize the adsManager and start playing advertisements + */ }, { - key: 'onAdError', - value: function onAdError(event) { - this.cancel(); - this.player.debug.warn('Ads error', event); - } + key: "play", + value: function play() { + var _this9 = this; - /** - * Setup hooks for Plyr and window events. This ensures - * the mid- and post-roll launch at the correct time. And - * resize the advertisement when the player resizes - */ + var container = this.player.elements.container; - }, { - key: 'listeners', - value: function listeners() { - var _this8 = this; + if (!this.managerPromise) { + this.resumeContent(); + } // Play the requested advertisement whenever the adsManager is ready - var container = this.player.elements.container; - var time = void 0; + this.managerPromise.then(function () { + // Initialize the container. Must be done via a user action on mobile devices + _this9.elements.displayContainer.initialize(); - // Add listeners to the required events - this.player.on('ended', function () { - _this8.loader.contentComplete(); - }); + try { + if (!_this9.initialized) { + // Initialize the ads manager. Ad rules playlist will start at this time + _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will + // start at this time; the call will be ignored for ad rules - this.player.on('seeking', function () { - time = _this8.player.currentTime; - return time; - }); - this.player.on('seeked', function () { - var seekedTime = _this8.player.currentTime; + _this9.manager.start(); + } - if (utils.is.empty(_this8.cuePoints)) { - return; - } + _this9.initialized = true; + } catch (adError) { + // An error may be thrown if there was a problem with the + // VAST response + _this9.onAdError(adError); + } + }).catch(function () {}); + } + /** + * Resume our video + */ - _this8.cuePoints.forEach(function (cuePoint, index) { - if (time < cuePoint && cuePoint < seekedTime) { - _this8.manager.discardAdBreak(); - _this8.cuePoints.splice(index, 1); - } - }); - }); + }, { + key: "resumeContent", + value: function resumeContent() { + // Hide the advertisement container + this.elements.container.style.zIndex = ''; // Ad is stopped - // Listen to the resizing of the window. And resize ad accordingly - // TODO: eventually implement ResizeObserver - window.addEventListener('resize', function () { - if (_this8.manager) { - _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); - } - }); - } + this.playing = false; // Play our video - /** - * Initialize the adsManager and start playing advertisements - */ + if (this.player.currentTime < this.player.duration) { + this.player.play(); + } + } + /** + * Pause our video + */ }, { - key: 'play', - value: function play() { - var _this9 = this; + key: "pauseContent", + value: function pauseContent() { + // Show the advertisement container + this.elements.container.style.zIndex = 3; // Ad is playing. - var container = this.player.elements.container; + this.playing = true; // Pause our video. + this.player.pause(); + } + /** + * Destroy the adsManager so we can grab new ads after this. If we don't then we're not + * allowed to call new ads based on google policies, as they interpret this as an accidental + * video requests. https://developers.google.com/interactive- + * media-ads/docs/sdks/android/faq#8 + */ - if (!this.managerPromise) { - this.resumeContent(); - } + }, { + key: "cancel", + value: function cancel() { + // Pause our video + if (this.initialized) { + this.resumeContent(); + } // Tell our instance that we're done for now - // Play the requested advertisement whenever the adsManager is ready - this.managerPromise.then(function () { - // Initialize the container. Must be done via a user action on mobile devices - _this9.elements.displayContainer.initialize(); - - try { - if (!_this9.initialized) { - // Initialize the ads manager. Ad rules playlist will start at this time - _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); - - // Call play to start showing the ad. Single video and overlay ads will - // start at this time; the call will be ignored for ad rules - _this9.manager.start(); - } - - _this9.initialized = true; - } catch (adError) { - // An error may be thrown if there was a problem with the - // VAST response - _this9.onAdError(adError); - } - }).catch(function () {}); - } - /** - * Resume our video - */ + this.trigger('error'); // Re-create our adsManager + + this.loadAds(); + } + /** + * Re-create our adsManager + */ }, { - key: 'resumeContent', - value: function resumeContent() { - // Hide the advertisement container - this.elements.container.style.zIndex = ''; + key: "loadAds", + value: function loadAds() { + var _this10 = this; - // Ad is stopped - this.playing = false; + // Tell our adsManager to go bye bye + this.managerPromise.then(function () { + // Destroy our adsManager + if (_this10.manager) { + _this10.manager.destroy(); + } // Re-set our adsManager promises - // Play our video - if (this.player.currentTime < this.player.duration) { - this.player.play(); - } - } - /** - * Pause our video - */ + _this10.managerPromise = new Promise(function (resolve) { + _this10.on('loaded', resolve); - }, { - key: 'pauseContent', - value: function pauseContent() { - // Show the advertisement container - this.elements.container.style.zIndex = 3; + _this10.player.debug.log(_this10.manager); + }); // Now request some new advertisements + + _this10.requestAds(); + }).catch(function () {}); + } + /** + * Handles callbacks after an ad event was invoked + * @param {string} event - Event type + */ - // Ad is playing. - this.playing = true; + }, { + key: "trigger", + value: function trigger(event) { + var _this11 = this; - // Pause our video. - this.player.pause(); + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; } - /** - * Destroy the adsManager so we can grab new ads after this. If we don't then we're not - * allowed to call new ads based on google policies, as they interpret this as an accidental - * video requests. https://developers.google.com/interactive- - * media-ads/docs/sdks/android/faq#8 - */ + var handlers = this.events[event]; - }, { - key: 'cancel', - value: function cancel() { - // Pause our video - if (this.initialized) { - this.resumeContent(); + if (is.array(handlers)) { + handlers.forEach(function (handler) { + if (is.function(handler)) { + handler.apply(_this11, args); } + }); + } + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + * @return {Ads} + */ - // Tell our instance that we're done for now - this.trigger('error'); - - // Re-create our adsManager - this.loadAds(); + }, { + key: "on", + value: function on$$1(event, callback) { + if (!is.array(this.events[event])) { + this.events[event] = []; } - /** - * Re-create our adsManager - */ + this.events[event].push(callback); + return this; + } + /** + * Setup a safety timer for when the ad network doesn't respond for whatever reason. + * The advertisement has 12 seconds to get its things together. We stop this timer when the + * advertisement is playing, or when a user action is required to start, then we clear the + * timer on ad ready + * @param {number} time + * @param {string} from + */ }, { - key: 'loadAds', - value: function loadAds() { - var _this10 = this; - - // Tell our adsManager to go bye bye - this.managerPromise.then(function () { - // Destroy our adsManager - if (_this10.manager) { - _this10.manager.destroy(); - } - - // Re-set our adsManager promises - _this10.managerPromise = new Promise(function (resolve) { - _this10.on('loaded', resolve); - _this10.player.debug.log(_this10.manager); - }); + key: "startSafetyTimer", + value: function startSafetyTimer(time, from) { + var _this12 = this; - // Now request some new advertisements - _this10.requestAds(); - }).catch(function () {}); - } + this.player.debug.log("Safety timer invoked from: ".concat(from)); + this.safetyTimer = setTimeout(function () { + _this12.cancel(); - /** - * Handles callbacks after an ad event was invoked - * @param {string} event - Event type - */ + _this12.clearSafetyTimer('startSafetyTimer()'); + }, time); + } + /** + * Clear our safety timer(s) + * @param {string} from + */ }, { - key: 'trigger', - value: function trigger(event) { - var _this11 = this; + key: "clearSafetyTimer", + value: function clearSafetyTimer(from) { + if (!is.nullOrUndefined(this.safetyTimer)) { + this.player.debug.log("Safety timer cleared from: ".concat(from)); + clearTimeout(this.safetyTimer); + this.safetyTimer = null; + } + } + }, { + key: "enabled", + get: function get() { + var config = this.config; + return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl)); + } + }, { + key: "tagUrl", + get: function get() { + var config = this.config; + + if (is.url(config.tagUrl)) { + return config.tagUrl; + } + + var params = { + AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', + AV_CHANNELID: '5a0458dc28a06145e4519d21', + AV_URL: window.location.hostname, + cb: Date.now(), + AV_WIDTH: 640, + AV_HEIGHT: 480, + AV_CDIM2: this.publisherId + }; + var base = 'https://go.aniview.com/api/adserver6/vast/'; + return "".concat(base, "?").concat(buildUrlParams(params)); + } + }]); - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + return Ads; + }(); + + var parseVtt = function parseVtt(vttDataString) { + var processedList = []; + var frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + frames.forEach(function (frame) { + var result = {}; + var lines = frame.split(/\r\n|\n|\r/); + lines.forEach(function (line) { + if (!is.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + var matchTimes = line.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = Number(matchTimes[1]) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number("0.".concat(matchTimes[4])); + result.endTime = Number(matchTimes[6]) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number("0.".concat(matchTimes[9])); + } + } else if (!is.empty(line.trim()) && is.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + var lineSplit = line.trim().split('#xywh='); + + var _lineSplit = _slicedToArray(lineSplit, 1); + + result.text = _lineSplit[0]; + + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + var _lineSplit$1$split = lineSplit[1].split(','); + + var _lineSplit$1$split2 = _slicedToArray(_lineSplit$1$split, 4); + + result.x = _lineSplit$1$split2[0]; + result.y = _lineSplit$1$split2[1]; + result.w = _lineSplit$1$split2[2]; + result.h = _lineSplit$1$split2[3]; + } + } + }); + + if (result.text) { + processedList.push(result); + } + }); + return processedList; + }; + /** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + + + var PreviewThumbnails = + /*#__PURE__*/ + function () { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + function PreviewThumbnails(player) { + _classCallCheck(this, PreviewThumbnails); + + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + this.elements = { + thumb: {}, + scrubbing: {} + }; + this.load(); + } - var handlers = this.events[event]; + _createClass(PreviewThumbnails, [{ + key: "load", + value: function load() { + var _this = this; - if (utils.is.array(handlers)) { - handlers.forEach(function (handler) { - if (utils.is.function(handler)) { - handler.apply(_this11, args); - } - }); - } + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; } - /** - * Add event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - * @return {Ads} - */ + if (!this.enabled) { + return; + } - }, { - key: 'on', - value: function on(event, callback) { - if (!utils.is.array(this.events[event])) { - this.events[event] = []; - } + this.getThumbnails().then(function () { + // Render DOM elements + _this.render(); // Check to see if thumb container size was specified manually in CSS - this.events[event].push(callback); - return this; - } + _this.determineContainerAutoSizing(); - /** - * Setup a safety timer for when the ad network doesn't respond for whatever reason. - * The advertisement has 12 seconds to get its things together. We stop this timer when the - * advertisement is playing, or when a user action is required to start, then we clear the - * timer on ad ready - * @param {number} time - * @param {string} from - */ + _this.loaded = true; + }); + } // Download VTT files and parse them }, { - key: 'startSafetyTimer', - value: function startSafetyTimer(time, from) { - var _this12 = this; + key: "getThumbnails", + value: function getThumbnails() { + var _this2 = this; - this.player.debug.log('Safety timer invoked from: ' + from); + return new Promise(function (resolve) { + var src = _this2.player.config.previewThumbnails.src; - this.safetyTimer = setTimeout(function () { - _this12.cancel(); - _this12.clearSafetyTimer('startSafetyTimer()'); - }, time); - } + if (is.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } // If string, convert into single-element list - /** - * Clear our safety timer(s) - * @param {string} from - */ - }, { - key: 'clearSafetyTimer', - value: function clearSafetyTimer(from) { - if (!utils.is.nullOrUndefined(this.safetyTimer)) { - this.player.debug.log('Safety timer cleared from: ' + from); + var urls = is.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails + + var promises = urls.map(function (u) { + return _this2.getThumbnail(u); + }); + Promise.all(promises).then(function () { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + _this2.thumbnails.sort(function (x, y) { + return x.height - y.height; + }); + + _this2.player.debug.log('Preview thumbnails', _this2.thumbnails); + + resolve(); + }); + }); + } // Process individual VTT file - clearTimeout(this.safetyTimer); - this.safetyTimer = null; - } - } - }, { - key: 'enabled', - get: function get$$1() { - return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId); - } }, { - key: 'tagUrl', - get: function get$$1() { - var params = { - AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', - AV_CHANNELID: '5a0458dc28a06145e4519d21', - AV_URL: location.hostname, - cb: Date.now(), - AV_WIDTH: 640, - AV_HEIGHT: 480, - AV_CDIM2: this.publisherId - }; + key: "getThumbnail", + value: function getThumbnail(url) { + var _this3 = this; - var base = 'https://go.aniview.com/api/adserver6/vast/'; + return new Promise(function (resolve) { + fetch(url).then(function (response) { + var thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '' + }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank - return base + '?' + utils.buildUrlParams(params); - } - }]); - return Ads; -}(); + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } // Download the first frame, so that we can determine/set the height of this thumbnailsDef -// ========================================================================== -var source = { - // Add elements to HTML5 media (source, tracks, etc) - insertElements: function insertElements(type, attributes) { - var _this = this; + var tempImage = new Image(); - if (utils.is.string(attributes)) { - utils.insertElement(type, this.media, { - src: attributes - }); - } else if (utils.is.array(attributes)) { - attributes.forEach(function (attribute) { - utils.insertElement(type, _this.media, attribute); - }); - } - }, + tempImage.onload = function () { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; + _this3.thumbnails.push(thumbnail); - // Update source - // Sources are not checked for support so be careful - change: function change(input) { - var _this2 = this; + resolve(); + }; - if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) { - this.debug.warn('Invalid source format'); - return; + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } + }, { + key: "startMove", + value: function startMove(event) { + if (!this.loaded) { + return; } - // Cancel current network requests - html5.cancelRequests.call(this); + if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } // Wait until media has a duration - // Destroy instance and re-setup - this.destroy.call(this, function () { - // Reset quality options - _this2.options.quality = []; - // Remove elements - utils.removeElement(_this2.media); - _this2.media = null; + if (!this.player.media.duration) { + return; + } - // Reset class name - if (utils.is.element(_this2.elements.container)) { - _this2.elements.container.removeAttribute('class'); - } + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + var clientRect = this.player.elements.progress.getBoundingClientRect(); + var percentage = 100 / clientRect.width * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); - // Set the type and provider - _this2.type = input.type; - _this2.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5; + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } - // Check for support - _this2.supported = support.check(_this2.type, _this2.provider, _this2.config.playsinline); + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } - // Create new markup - switch (_this2.provider + ':' + _this2.type) { - case 'html5:video': - _this2.media = utils.createElement('video'); - break; + this.mousePosX = event.pageX; // Set time text inside image container - case 'html5:audio': - _this2.media = utils.createElement('audio'); - break; + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } // Download and show image - case 'youtube:video': - case 'vimeo:video': - _this2.media = utils.createElement('div', { - src: input.sources[0].src - }); - break; - default: - break; - } + this.showImageAtCurrentTime(); + } + }, { + key: "endMove", + value: function endMove() { + this.toggleThumbContainer(false, true); + } + }, { + key: "startScrubbing", + value: function startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; // Wait until media has a duration - // Inject the new element - _this2.elements.container.appendChild(_this2.media); + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); // Download and show image - // Autoplay the new source? - if (utils.is.boolean(input.autoplay)) { - _this2.config.autoplay = input.autoplay; - } + this.showImageAtCurrentTime(); + } + } + } + }, { + key: "finishScrubbing", + value: function finishScrubbing() { + var _this4 = this; - // Set attributes for audio and video - if (_this2.isHTML5) { - if (_this2.config.crossorigin) { - _this2.media.setAttribute('crossorigin', ''); - } - if (_this2.config.autoplay) { - _this2.media.setAttribute('autoplay', ''); - } - if (!utils.is.empty(input.poster)) { - _this2.poster = input.poster; - } - if (_this2.config.loop.active) { - _this2.media.setAttribute('loop', ''); - } - if (_this2.config.muted) { - _this2.media.setAttribute('muted', ''); - } - if (_this2.config.playsinline) { - _this2.media.setAttribute('playsinline', ''); - } + this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview + + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', function () { + // Re-check mousedown - we might have already started scrubbing again + if (!_this4.mouseDown) { + _this4.toggleScrubbingContainer(false); } + }); + } + } + /** + * Setup hooks for Plyr and window events + */ - // Restore class hook - ui.addStyleHook.call(_this2); + }, { + key: "listeners", + value: function listeners() { + var _this5 = this; - // Set new sources for html5 - if (_this2.isHTML5) { - source.insertElements.call(_this2, 'source', input.sources); - } + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', function () { + _this5.toggleThumbContainer(false, true); + }); + this.player.on('seeked', function () { + _this5.toggleThumbContainer(false); + }); + this.player.on('timeupdate', function () { + _this5.lastTime = _this5.player.media.currentTime; + }); + } + /** + * Create HTML elements for image containers + */ - // Set video title - _this2.config.title = input.title; + }, { + key: "render", + value: function render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer + }); // Wrapper for the image for styling + + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00) - // Set up from scratch - media.setup.call(_this2); + var timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer + }); + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb - // HTML5 stuff - if (_this2.isHTML5) { - // Setup captions - if ('tracks' in input) { - source.insertElements.call(_this2, 'track', input.tracks); - } + this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container - // Load HTML5 sources - _this2.media.load(); - } + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer + }); + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + }, { + key: "showImageAtCurrentTime", + value: function showImageAtCurrentTime() { + var _this6 = this; - // If HTML5 or embed but not fully supported, setupInterface and call ready now - if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { - // Setup interface - ui.build.call(_this2); - } + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null - // Update the fullscreen support - _this2.fullscreen.update(); - }, true); - } -}; -// ========================================================================== + var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) { + return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime; + }); + var hasThumb = thumbNum >= 0; + var qualityIndex = 0; + this.toggleThumbContainer(hasThumb); // No matching thumb found -var Storage = function () { - function Storage(player) { - classCallCheck(this, Storage); + if (!hasThumb) { + return; + } // Check to see if we've already downloaded higher quality versions of this image - this.enabled = player.config.storage.enabled; - this.key = player.config.storage.key; - } - // Check for actual support (see if we can use it) + this.thumbnails.forEach(function (thumbnail, index) { + if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); // Only proceed if either thumbnum or thumbfilename has changed + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); + } + } // Show the image that's currently specified in this.showingThumb - createClass(Storage, [{ - key: 'get', - value: function get$$1(key) { - if (!Storage.supported) { - return null; - } + }, { + key: "loadImage", + value: function loadImage() { + var _this7 = this; + + var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var thumbNum = this.showingThumb; + var thumbnail = this.thumbnails[qualityIndex]; + var urlPrefix = thumbnail.urlPrefix; + var frame = thumbnail.frames[thumbNum]; + var thumbFilename = thumbnail.frames[thumbNum].text; + var thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + + + var previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + + previewImage.onload = function () { + return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + }; + + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); + } + } + }, { + key: "showImage", + value: function showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename) { + var newImage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this.player.debug.log("Showing thumb: ".concat(thumbFilename, ". num: ").concat(thumbNum, ". qual: ").concat(qualityIndex, ". newimg: ").concat(newImage)); + this.setImageSizeAndOffset(previewImage, frame); - var store = window.localStorage.getItem(this.key); + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; - if (utils.is.empty(store)) { - return null; - } + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading - var json = JSON.parse(store); - return utils.is.string(key) && key.length ? json[key] : json; - } + this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } // Remove all preview images that aren't the designated current image + }, { - key: 'set', - value: function set$$1(object) { - // Bail if we don't have localStorage support or it's disabled - if (!Storage.supported || !this.enabled) { - return; - } + key: "removeOldImages", + value: function removeOldImages(currentImage) { + var _this8 = this; - // Can only store objectst - if (!utils.is.object(object)) { - return; - } + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(function (image) { + if (image.tagName.toLowerCase() !== 'img') { + return; + } - // Get current storage - var storage = this.get(); + var removeDelay = _this8.usingSprites ? 500 : 1000; - // Default to empty object - if (utils.is.empty(storage)) { - storage = {}; - } + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub - // Update the working copy of the values - utils.extend(storage, object); + var currentImageContainer = _this8.currentImageContainer; + setTimeout(function () { + currentImageContainer.removeChild(image); - // Update storage - window.localStorage.setItem(this.key, JSON.stringify(storage)); - } - }], [{ - key: 'supported', - get: function get$$1() { - try { - if (!('localStorage' in window)) { - return false; - } + _this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename)); + }, removeDelay); + } + }); + } // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality - var test = '___test'; + }, { + key: "preloadNearby", + value: function preloadNearby(thumbNum) { + var _this9 = this; - // Try to use it (it might be disabled, e.g. user is in private mode) - // see: https://github.com/sampotts/plyr/issues/131 - window.localStorage.setItem(test, test); - window.localStorage.removeItem(test); + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return new Promise(function (resolve) { + setTimeout(function () { + var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text; - return true; - } catch (e) { - return false; - } - } - }]); - return Storage; -}(); + if (_this9.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + var thumbnailsClone; -// ========================================================================== + if (forward) { + thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } -// Private properties -// TODO: Use a WeakMap for private globals -// const globals = new WeakMap(); + var foundOne = false; + thumbnailsClone.forEach(function (frame) { + var newThumbFilename = frame.text; -// Plyr instance + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!_this9.loadedImages.includes(newThumbFilename)) { + foundOne = true; -var Plyr = function () { - function Plyr(target, options) { - var _this = this; + _this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename)); - classCallCheck(this, Plyr); + var urlPrefix = _this9.thumbnails[0].urlPrefix; + var thumbURL = urlPrefix + newThumbFilename; + var previewImage = new Image(); + previewImage.src = thumbURL; - this.timers = {}; + previewImage.onload = function () { + _this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename)); - // State - this.ready = false; - this.loading = false; - this.failed = false; + if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded - // Touch device - this.touch = support.touch; + resolve(); + }; + } + } + }); // If there are none to preload then we want to resolve immediately - // Set the media element - this.media = target; + if (!foundOne) { + resolve(); + } + } + }, 300); + }); + } // If user has been hovering current image for half a second, look for a higher quality one - // String selector passed - if (utils.is.string(this.media)) { - this.media = document.querySelectorAll(this.media); + }, { + key: "getHigherQuality", + value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + var _this10 = this; + + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + var previewImageHeight = previewImage.naturalHeight; + + if (this.usingSprites) { + previewImageHeight = frame.h; + } + + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(function () { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (_this10.showingThumbFilename === thumbFilename) { + _this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename)); + + _this10.loadImage(currentQualityIndex + 1); + } + }, 300); + } } + } + }, { + key: "toggleThumbContainer", + value: function toggleThumbContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var clearShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); - // jQuery, NodeList or Array passed, use first element - if (window.jQuery && this.media instanceof jQuery || utils.is.nodeList(this.media) || utils.is.array(this.media)) { - // eslint-disable-next-line - this.media = this.media[0]; + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; } + } + }, { + key: "toggleScrubbingContainer", + value: function toggleScrubbingContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); - // Set config - this.config = utils.extend({}, defaults$1, options || {}, function () { - try { - return JSON.parse(_this.media.getAttribute('data-plyr-config')); - } catch (e) { - return {}; - } - }()); - - // Elements cache - this.elements = { - container: null, - buttons: {}, - display: {}, - progress: {}, - inputs: {}, - settings: { - menu: null, - panes: {}, - tabs: {} - }, - captions: null - }; + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "determineContainerAutoSizing", + value: function determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS - // Captions - this.captions = { - active: null, - currentTrack: null - }; + }, { + key: "setThumbContainerSizeAndPos", + value: function setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px"); + this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px"); + } - // Fullscreen - this.fullscreen = { - active: false - }; + this.setThumbContainerPos(); + } + }, { + key: "setThumbContainerPos", + value: function setThumbContainerPos() { + var seekbarRect = this.player.elements.progress.getBoundingClientRect(); + var plyrRect = this.player.elements.container.getBoundingClientRect(); + var container = this.elements.thumb.container; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container - // Options - this.options = { - speed: [], - quality: [], - captions: [] - }; + var minVal = plyrRect.left - seekbarRect.left + 10; + var maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth - // Debugging - // TODO: move to globals - this.debug = new Console(this.config.debug); + var previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; - // Log config options and support - this.debug.log('Config', this.config); - this.debug.log('Support', support); + if (previewPos < minVal) { + previewPos = minVal; + } - // We need an element to setup - if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) { - this.debug.error('Setup failed: no suitable element passed'); - return; + if (previewPos > maxVal) { + previewPos = maxVal; } - // Bail if the element is initialized - if (this.media.plyr) { - this.debug.warn('Target already setup'); - return; + container.style.left = "".concat(previewPos, "px"); + } // Can't use 100% width, in case the video is a different aspect ratio to the video container + + }, { + key: "setScrubbingContainerSize", + value: function setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below + + this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px"); + } // Sprites need to be offset to the correct location + + }, { + key: "setImageSizeAndOffset", + value: function setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } // Find difference between height and preview container height + + + var multiplier = this.thumbContainerHeight / frame.h; + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); + } + }, { + key: "enabled", + get: function get() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + }, { + key: "currentImageContainer", + get: function get() { + if (this.mouseDown) { + return this.elements.scrubbing.container; } - // Bail if not enabled - if (!this.config.enabled) { - this.debug.error('Setup failed: disabled by config'); - return; + return this.elements.thumb.imageContainer; + } + }, { + key: "usingSprites", + get: function get() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } + }, { + key: "thumbAspectRatio", + get: function get() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; } - // Bail if disabled or no basic support - // You may want to disable certain UAs etc - if (!support.check().api) { - this.debug.error('Setup failed: no support'); - return; + return this.thumbnails[0].width / this.thumbnails[0].height; + } + }, { + key: "thumbContainerHeight", + get: function get() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); } - // Cache original element state for .destroy() - var clone = this.media.cloneNode(true); - clone.autoplay = false; - this.elements.original = clone; + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + }, { + key: "currentImageElement", + get: function get() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } - // Set media type based on tag or data attribute - // Supported: video, audio, vimeo, youtube - var type = this.media.tagName.toLowerCase(); + return this.currentThumbnailImageElement; + }, + set: function set(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; + } + } + }]); - // Embed properties - var iframe = null; - var url = null; - var params = null; + return PreviewThumbnails; + }(); - // Different setup based on type - switch (type) { - case 'div': - // Find the frame - iframe = this.media.querySelector('iframe'); - - // <iframe> type - if (utils.is.element(iframe)) { - // Detect provider - url = iframe.getAttribute('src'); - this.provider = utils.getProviderByUrl(url); - - // Rework elements - this.elements.container = this.media; - this.media = iframe; - - // Reset classname - this.elements.container.className = ''; - - // Get attributes from URL and set config - params = utils.getUrlParams(url); - if (!utils.is.empty(params)) { - var truthy = ['1', 'true']; - - if (truthy.includes(params.autoplay)) { - this.config.autoplay = true; - } - if (truthy.includes(params.loop)) { - this.config.loop.active = true; - } - - // TODO: replace fullscreen.iosNative with this playsinline config option - // YouTube requires the playsinline in the URL - if (this.isYouTube) { - this.config.playsinline = truthy.includes(params.playsinline); - } else { - this.config.playsinline = true; - } - } - } else { - // <div> with attributes - this.provider = this.media.getAttribute(this.config.attributes.embed.provider); + var source = { + // Add elements to HTML5 media (source, tracks, etc) + insertElements: function insertElements(type, attributes) { + var _this = this; - // Remove attribute - this.media.removeAttribute(this.config.attributes.embed.provider); - } + if (is.string(attributes)) { + insertElement(type, this.media, { + src: attributes + }); + } else if (is.array(attributes)) { + attributes.forEach(function (attribute) { + insertElement(type, _this.media, attribute); + }); + } + }, + // Update source + // Sources are not checked for support so be careful + change: function change(input) { + var _this2 = this; - // Unsupported or missing provider - if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { - this.debug.error('Setup failed: Invalid provider'); - return; - } + if (!getDeep(input, 'sources.length')) { + this.debug.warn('Invalid source format'); + return; + } // Cancel current network requests - // Audio will come later for external providers - this.type = types.video; - break; + html5.cancelRequests.call(this); // Destroy instance and re-setup - case 'video': - case 'audio': - this.type = type; - this.provider = providers.html5; + this.destroy.call(this, function () { + // Reset quality options + _this2.options.quality = []; // Remove elements - // Get config from attributes - if (this.media.hasAttribute('crossorigin')) { - this.config.crossorigin = true; - } - if (this.media.hasAttribute('autoplay')) { - this.config.autoplay = true; - } - if (this.media.hasAttribute('playsinline')) { - this.config.playsinline = true; - } - if (this.media.hasAttribute('muted')) { - this.config.muted = true; - } - if (this.media.hasAttribute('loop')) { - this.config.loop.active = true; - } + removeElement(_this2.media); + _this2.media = null; // Reset class name - break; + if (is.element(_this2.elements.container)) { + _this2.elements.container.removeAttribute('class'); + } // Set the type and provider - default: - this.debug.error('Setup failed: unsupported type'); - return; - } - // Check for support again but with type - this.supported = support.check(this.type, this.provider, this.config.playsinline); + var sources = input.sources, + type = input.type; - // If no support for even API, bail - if (!this.supported.api) { - this.debug.error('Setup failed: no support'); - return; - } + var _sources = _slicedToArray(sources, 1), + _sources$ = _sources[0], + _sources$$provider = _sources$.provider, + provider = _sources$$provider === void 0 ? providers.html5 : _sources$$provider, + src = _sources$.src; - // Create listeners - this.listeners = new Listeners(this); + var tagName = provider === 'html5' ? type : 'div'; + var attributes = provider === 'html5' ? {} : { + src: src + }; + Object.assign(_this2, { + provider: provider, + type: type, + // Check for support + supported: support.check(type, provider, _this2.config.playsinline), + // Create new element + media: createElement(tagName, attributes) + }); // Inject the new element - // Setup local storage for user settings - this.storage = new Storage(this); + _this2.elements.container.appendChild(_this2.media); // Autoplay the new source? - // Store reference - this.media.plyr = this; - // Wrap media - if (!utils.is.element(this.elements.container)) { - this.elements.container = utils.createElement('div'); - utils.wrap(this.media, this.elements.container); - } + if (is.boolean(input.autoplay)) { + _this2.config.autoplay = input.autoplay; + } // Set attributes for audio and video - // Allow focus to be captured - this.elements.container.setAttribute('tabindex', 0); - // Add style hook - ui.addStyleHook.call(this); + if (_this2.isHTML5) { + if (_this2.config.crossorigin) { + _this2.media.setAttribute('crossorigin', ''); + } - // Setup media - media.setup.call(this); + if (_this2.config.autoplay) { + _this2.media.setAttribute('autoplay', ''); + } - // Listen for events if debugging - if (this.config.debug) { - utils.on(this.elements.container, this.config.events.join(' '), function (event) { - _this.debug.log('event: ' + event.type); - }); - } + if (!is.empty(input.poster)) { + _this2.poster = input.poster; + } - // Setup interface - // If embed but not fully supported, build interface now to avoid flash of controls - if (this.isHTML5 || this.isEmbed && !this.supported.ui) { - ui.build.call(this); - } + if (_this2.config.loop.active) { + _this2.media.setAttribute('loop', ''); + } - // Container listeners - this.listeners.container(); + if (_this2.config.muted) { + _this2.media.setAttribute('muted', ''); + } - // Global listeners - this.listeners.global(); + if (_this2.config.playsinline) { + _this2.media.setAttribute('playsinline', ''); + } + } // Restore class hook - // Setup fullscreen - this.fullscreen = new Fullscreen(this); - // Setup ads if provided - this.ads = new Ads(this); + ui.addStyleHook.call(_this2); // Set new sources for html5 - // Autoplay if required - if (this.config.autoplay) { - this.play(); - } - } + if (_this2.isHTML5) { + source.insertElements.call(_this2, 'source', sources); + } // Set video title - // --------------------------------------- - // API - // --------------------------------------- - /** - * Types and provider helpers - */ + _this2.config.title = input.title; // Set up from scratch + media.setup.call(_this2); // HTML5 stuff - createClass(Plyr, [{ - key: 'play', + if (_this2.isHTML5) { + // Setup captions + if (Object.keys(input).includes('tracks')) { + source.insertElements.call(_this2, 'track', input.tracks); + } + } // If HTML5 or embed but not fully supported, setupInterface and call ready now - /** - * Play the media, or play the advertisement (if they are not blocked) - */ - value: function play() { - if (!utils.is.function(this.media.play)) { - return null; - } + if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { + // Setup interface + ui.build.call(_this2); + } // Load HTML5 sources - // Return the promise (for HTML5) - return this.media.play(); - } - /** - * Pause the media - */ + if (_this2.isHTML5) { + _this2.media.load(); + } // Reload thumbnails - }, { - key: 'pause', - value: function pause() { - if (!this.playing || !utils.is.function(this.media.pause)) { - return; - } - this.media.pause(); - } + if (_this2.previewThumbnails) { + _this2.previewThumbnails.load(); + } // Update the fullscreen support - /** - * Get playing state - */ - }, { - key: 'togglePlay', + _this2.fullscreen.update(); + }, true); + } + }; + // TODO: Use a WeakMap for private globals + // const globals = new WeakMap(); + // Plyr instance - /** - * Toggle playback based on current status - * @param {boolean} input - */ - value: function togglePlay(input) { - // Toggle based on current state if nothing passed - var toggle = utils.is.boolean(input) ? input : !this.playing; + var Plyr = + /*#__PURE__*/ + function () { + function Plyr(target, options) { + var _this = this; - if (toggle) { - this.play(); - } else { - this.pause(); - } - } + _classCallCheck(this, Plyr); - /** - * Stop playback - */ + this.timers = {}; // State - }, { - key: 'stop', - value: function stop() { - if (this.isHTML5) { - this.pause(); - this.restart(); - } else if (utils.is.function(this.media.stop)) { - this.media.stop(); - } - } + this.ready = false; + this.loading = false; + this.failed = false; // Touch device - /** - * Restart playback - */ + this.touch = support.touch; // Set the media element - }, { - key: 'restart', - value: function restart() { - this.currentTime = 0; - } + this.media = target; // String selector passed - /** - * Rewind - * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime - */ + if (is.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } // jQuery, NodeList or Array passed, use first element - }, { - key: 'rewind', - value: function rewind(seekTime) { - this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime); - } - /** - * Fast forward - * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime - */ + if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } // Set config - }, { - key: 'forward', - value: function forward(seekTime) { - this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime); + + this.config = extend({}, defaults, Plyr.defaults, options || {}, function () { + try { + return JSON.parse(_this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; } + }()); // Elements cache - /** - * Seek to a time - * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) - */ + this.elements = { + container: null, + captions: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + popup: null, + menu: null, + panels: {}, + buttons: {} + } + }; // Captions + + this.captions = { + active: null, + currentTrack: -1, + meta: new WeakMap() + }; // Fullscreen + + this.fullscreen = { + active: false + }; // Options - }, { - key: 'increaseVolume', + this.options = { + speed: [], + quality: [] + }; // Debugging + // TODO: move to globals + this.debug = new Console(this.config.debug); // Log config options and support - /** - * Increase volume - * @param {boolean} step - How much to decrease by (between 0 and 1) - */ - value: function increaseVolume(step) { - var volume = this.media.muted ? 0 : this.volume; - this.volume = volume + (utils.is.number(step) ? step : 1); - } + this.debug.log('Config', this.config); + this.debug.log('Support', support); // We need an element to setup - /** - * Decrease volume - * @param {boolean} step - How much to decrease by (between 0 and 1) - */ + if (is.nullOrUndefined(this.media) || !is.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); + return; + } // Bail if the element is initialized - }, { - key: 'decreaseVolume', - value: function decreaseVolume(step) { - var volume = this.media.muted ? 0 : this.volume; - this.volume = volume - (utils.is.number(step) ? step : 1); - } - /** - * Set muted state - * @param {boolean} mute - */ + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; + } // Bail if not enabled - }, { - key: 'toggleCaptions', + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; + } // Bail if disabled or no basic support + // You may want to disable certain UAs etc - /** - * Toggle captions - * @param {boolean} input - Whether to enable captions - */ - value: function toggleCaptions(input) { - // If there's no full support - if (!this.supported.ui) { - return; - } - // If the method is called without parameter, toggle based on current value - var show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active); + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; + } // Cache original element state for .destroy() - // Nothing to change... - if (this.captions.active === show) { - return; - } - // Set global - this.captions.active = show; + var clone = this.media.cloneNode(true); + clone.autoplay = false; + this.elements.original = clone; // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube - // Toggle state - utils.toggleState(this.elements.buttons.captions, this.captions.active); + var type = this.media.tagName.toLowerCase(); // Embed properties - // Add class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active); + var iframe = null; + var url = null; // Different setup based on type - // Trigger an event - utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); - } + switch (type) { + case 'div': + // Find the frame + iframe = this.media.querySelector('iframe'); // <iframe> type - /** - * Set the captions language - * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) - */ + if (is.element(iframe)) { + // Detect provider + url = parseUrl(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements - }, { - key: 'airplay', + this.elements.container = this.media; + this.media = iframe; // Reset classname + this.elements.container.className = ''; // Get attributes from URL and set config - /** - * Trigger the airplay dialog - * TODO: update player with state, support, enabled - */ - value: function airplay() { - // Show dialog if supported - if (support.airplay) { - this.media.webkitShowPlaybackTargetPicker(); - } - } + if (url.search.length) { + var truthy = ['1', 'true']; - /** - * Toggle the player controls - * @param {boolean} toggle - Whether to show the controls - */ + if (truthy.includes(url.searchParams.get('autoplay'))) { + this.config.autoplay = true; + } - }, { - key: 'toggleControls', - value: function toggleControls(toggle) { - var _this2 = this; + if (truthy.includes(url.searchParams.get('loop'))) { + this.config.loop.active = true; + } // TODO: replace fullscreen.iosNative with this playsinline config option + // YouTube requires the playsinline in the URL - // We need controls of course... - if (!utils.is.element(this.elements.controls)) { - return; - } - // Don't hide if no UI support or it's audio - if (!this.supported.ui || this.isAudio) { - return; + if (this.isYouTube) { + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? + } else { + this.config.playsinline = true; + } } + } else { + // <div> with attributes + this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute - var delay = 0; - var show = toggle; - var isEnterFullscreen = false; + this.media.removeAttribute(this.config.attributes.embed.provider); + } // Unsupported or missing provider - // Get toggle state if not set - if (!utils.is.boolean(toggle)) { - if (utils.is.event(toggle)) { - // Is the enter fullscreen event - isEnterFullscreen = toggle.type === 'enterfullscreen'; - // Events that show the controls - var showEvents = ['touchstart', 'touchmove', 'mouseenter', 'mousemove', 'focusin']; + if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } // Audio will come later for external providers - // Events that delay hiding - var delayEvents = ['touchmove', 'touchend', 'mousemove']; - // Whether to show controls - show = showEvents.includes(toggle.type); + this.type = types.video; + break; - // Delay hiding on move events - if (delayEvents.includes(toggle.type)) { - delay = 2000; - } + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; // Get config from attributes - // Delay a little more for keyboard users - if (!this.touch && toggle.type === 'focusin') { - delay = 3000; - utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); - } - } else { - show = utils.hasClass(this.elements.container, this.config.classNames.hideControls); - } - } + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } - // Clear timer on every call - clearTimeout(this.timers.controls); + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } - // If the mouse is not over the controls, set a timeout to hide them - if (show || this.paused || this.loading) { - // Check if controls toggled - var toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false); + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { + this.config.playsinline = true; + } - // Trigger event - if (toggled) { - utils.dispatchEvent.call(this, this.media, 'controlsshown'); - } + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } - // Always show controls when paused or if touch - if (this.paused || this.loading) { - return; - } + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } - // Delay for hiding on touch - if (this.touch) { - delay = 3000; - } - } + break; - // If toggle is false or if we're playing (regardless of toggle), - // then set the timer to hide the controls - if (!show || this.playing) { - this.timers.controls = setTimeout(function () { - // We need controls of course... - if (!utils.is.element(_this2.elements.controls)) { - return; - } - - // If the mouse is over the controls (and not entering fullscreen), bail - if ((_this2.elements.controls.pressed || _this2.elements.controls.hover) && !isEnterFullscreen) { - return; - } - - // Restore transition behaviour - if (!utils.hasClass(_this2.elements.container, _this2.config.classNames.hideControls)) { - utils.toggleClass(_this2.elements.controls, _this2.config.classNames.noTransition, false); - } - - // Set hideControls class - var toggled = utils.toggleClass(_this2.elements.container, _this2.config.classNames.hideControls, _this2.config.hideControls); - - // Trigger event and close menu - if (toggled) { - utils.dispatchEvent.call(_this2, _this2.media, 'controlshidden'); - - if (_this2.config.controls.includes('settings') && !utils.is.empty(_this2.config.settings)) { - controls.toggleMenu.call(_this2, false); - } - } - }, delay); - } - } + default: + this.debug.error('Setup failed: unsupported type'); + return; + } // Check for support again but with type - /** - * Add event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - */ - }, { - key: 'on', - value: function on(event, callback) { - utils.on(this.elements.container, event, callback); - } + this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail - /** - * Remove event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - */ + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); + return; + } - }, { - key: 'off', - value: function off(event, callback) { - utils.off(this.elements.container, event, callback); - } + this.eventListeners = []; // Create listeners - /** - * Destroy an instance - * Event listeners are removed when elements are removed - * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory - * @param {function} callback - Callback for when destroy is complete - * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) - */ + this.listeners = new Listeners(this); // Setup local storage for user settings - }, { - key: 'destroy', - value: function destroy(callback) { - var _this3 = this; + this.storage = new Storage(this); // Store reference - var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + this.media.plyr = this; // Wrap media - if (!this.ready) { - return; - } + if (!is.element(this.elements.container)) { + this.elements.container = createElement('div', { + tabindex: 0 + }); + wrap(this.media, this.elements.container); + } // Add style hook - var done = function done() { - // Reset overflow (incase destroyed while in fullscreen) - document.body.style.overflow = ''; - - // GC for embed - _this3.embed = null; - - // If it's a soft destroy, make minimal changes - if (soft) { - if (Object.keys(_this3.elements).length) { - // Remove elements - utils.removeElement(_this3.elements.buttons.play); - utils.removeElement(_this3.elements.captions); - utils.removeElement(_this3.elements.controls); - utils.removeElement(_this3.elements.wrapper); - - // Clear for GC - _this3.elements.buttons.play = null; - _this3.elements.captions = null; - _this3.elements.controls = null; - _this3.elements.wrapper = null; - } - - // Callback - if (utils.is.function(callback)) { - callback(); - } - } else { - // Unbind listeners - _this3.listeners.clear(); - // Replace the container with the original element provided - utils.replaceElement(_this3.elements.original, _this3.elements.container); + ui.addStyleHook.call(this); // Setup media - // Event - utils.dispatchEvent.call(_this3, _this3.elements.original, 'destroyed', true); + media.setup.call(this); // Listen for events if debugging - // Callback - if (utils.is.function(callback)) { - callback.call(_this3.elements.original); - } + if (this.config.debug) { + on.call(this, this.elements.container, this.config.events.join(' '), function (event) { + _this.debug.log("event: ".concat(event.type)); + }); + } // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls - // Reset state - _this3.ready = false; - // Clear for garbage collection - setTimeout(function () { - _this3.elements = null; - _this3.media = null; - }, 200); - } - }; + if (this.isHTML5 || this.isEmbed && !this.supported.ui) { + ui.build.call(this); + } // Container listeners - // Stop playback - this.stop(); - // Type specific stuff - switch (this.provider + ':' + this.type) { - case 'html5:video': - case 'html5:audio': - // Clear timeout - clearTimeout(this.timers.loading); + this.listeners.container(); // Global listeners - // Restore native video controls - ui.toggleNativeControls.call(this, true); + this.listeners.global(); // Setup fullscreen - // Clean up - done(); + this.fullscreen = new Fullscreen(this); // Setup ads if provided - break; + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required - case 'youtube:video': - // Clear timers - clearInterval(this.timers.buffering); - clearInterval(this.timers.playing); - // Destroy YouTube API - if (this.embed !== null && utils.is.function(this.embed.destroy)) { - this.embed.destroy(); - } + if (this.config.autoplay) { + this.play(); + } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek - // Clean up - done(); - break; + this.lastSeekTime = 0; // Setup preview thumbnails if enabled - case 'vimeo:video': - // Destroy Vimeo API - // then clean up (wait, to prevent postmessage errors) - if (this.embed !== null) { - this.embed.unload().then(done); - } + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } + } // --------------------------------------- + // API + // --------------------------------------- - // Vimeo does not always return - setTimeout(done, 200); + /** + * Types and provider helpers + */ - break; - default: - break; - } - } + _createClass(Plyr, [{ + key: "play", + + /** + * Play the media, or play the advertisement (if they are not blocked) + */ + value: function play() { + if (!is.function(this.media.play)) { + return null; + } // Return the promise (for HTML5) - /** - * Check for support for a mime type (HTML5 only) - * @param {string} type - Mime type - */ + + return this.media.play(); + } + /** + * Pause the media + */ }, { - key: 'supports', - value: function supports(type) { - return support.mime.call(this, type); + key: "pause", + value: function pause() { + if (!this.playing || !is.function(this.media.pause)) { + return; } - /** - * Check for support - * @param {string} type - Player type (audio/video) - * @param {string} provider - Provider (html5/youtube/vimeo) - * @param {bool} inline - Where player has `playsinline` sttribute - */ + this.media.pause(); + } + /** + * Get playing state + */ }, { - key: 'isHTML5', - get: function get$$1() { - return Boolean(this.provider === providers.html5); + key: "togglePlay", + + /** + * Toggle playback based on current status + * @param {boolean} input + */ + value: function togglePlay(input) { + // Toggle based on current state if nothing passed + var toggle = is.boolean(input) ? input : !this.playing; + + if (toggle) { + this.play(); + } else { + this.pause(); } + } + /** + * Stop playback + */ + }, { - key: 'isEmbed', - get: function get$$1() { - return Boolean(this.isYouTube || this.isVimeo); + key: "stop", + value: function stop() { + if (this.isHTML5) { + this.pause(); + this.restart(); + } else if (is.function(this.media.stop)) { + this.media.stop(); } + } + /** + * Restart playback + */ + }, { - key: 'isYouTube', - get: function get$$1() { - return Boolean(this.provider === providers.youtube); - } + key: "restart", + value: function restart() { + this.currentTime = 0; + } + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ + }, { - key: 'isVimeo', - get: function get$$1() { - return Boolean(this.provider === providers.vimeo); - } + key: "rewind", + value: function rewind(seekTime) { + this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ + }, { - key: 'isVideo', - get: function get$$1() { - return Boolean(this.type === types.video); - } + key: "forward", + value: function forward(seekTime) { + this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ + }, { - key: 'isAudio', - get: function get$$1() { - return Boolean(this.type === types.audio); - } + key: "increaseVolume", + + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + value: function increaseVolume(step) { + var volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (is.number(step) ? step : 0); + } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + }, { - key: 'playing', - get: function get$$1() { - return Boolean(this.ready && !this.paused && !this.ended); - } + key: "decreaseVolume", + value: function decreaseVolume(step) { + this.increaseVolume(-step); + } + /** + * Set muted state + * @param {boolean} mute + */ - /** - * Get paused state - */ + }, { + key: "toggleCaptions", + + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + value: function toggleCaptions(input) { + captions.toggle.call(this, input, false); + } + /** + * Set the caption track by index + * @param {number} - Caption index + */ }, { - key: 'paused', - get: function get$$1() { - return Boolean(this.media.paused); - } + key: "airplay", - /** - * Get stopped state - */ + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + value: function airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); + } + } + /** + * Toggle the player controls + * @param {boolean} [toggle] - Whether to show the controls + */ }, { - key: 'stopped', - get: function get$$1() { - return Boolean(this.paused && this.currentTime === 0); + key: "toggleControls", + value: function toggleControls(toggle) { + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + var isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls + + var force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state + + var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu + + if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); + } // Trigger event on change + + + if (hiding !== isHidden) { + var eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); + } + + return !hiding; } - /** - * Get ended state - */ + return false; + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ }, { - key: 'ended', - get: function get$$1() { - return Boolean(this.media.ended); - } + key: "on", + value: function on$$1(event, callback) { + on.call(this, this.elements.container, event, callback); + } + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + }, { - key: 'currentTime', - set: function set$$1(input) { - var targetTime = 0; + key: "once", + value: function once$$1(event, callback) { + once.call(this, this.elements.container, event, callback); + } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ - if (utils.is.number(input)) { - targetTime = input; - } + }, { + key: "off", + value: function off$$1(event, callback) { + off(this.elements.container, event, callback); + } + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > this.duration) { - targetTime = this.duration; - } + }, { + key: "destroy", + value: function destroy(callback) { + var _this2 = this; - // Set - this.media.currentTime = targetTime; + var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - // Logging - this.debug.log('Seeking to ' + this.currentTime + ' seconds'); + if (!this.ready) { + return; } - /** - * Get current time - */ - , - get: function get$$1() { - return Number(this.media.currentTime); - } + var done = function done() { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; // GC for embed - /** - * Get buffered - */ + _this2.embed = null; // If it's a soft destroy, make minimal changes - }, { - key: 'buffered', - get: function get$$1() { - var buffered = this.media.buffered; + if (soft) { + if (Object.keys(_this2.elements).length) { + // Remove elements + removeElement(_this2.elements.buttons.play); + removeElement(_this2.elements.captions); + removeElement(_this2.elements.controls); + removeElement(_this2.elements.wrapper); // Clear for GC - // YouTube / Vimeo return a float between 0-1 + _this2.elements.buttons.play = null; + _this2.elements.captions = null; + _this2.elements.controls = null; + _this2.elements.wrapper = null; + } // Callback - if (utils.is.number(buffered)) { - return buffered; - } - // HTML5 - // TODO: Handle buffered chunks of the media - // (i.e. seek to another section buffers only that section) - if (buffered && buffered.length && this.duration > 0) { - return buffered.end(0) / this.duration; + if (is.function(callback)) { + callback(); } + } else { + // Unbind listeners + unbindListeners.call(_this2); // Replace the container with the original element provided - return 0; - } + replaceElement(_this2.elements.original, _this2.elements.container); // Event - /** - * Get seeking status - */ + triggerEvent.call(_this2, _this2.elements.original, 'destroyed', true); // Callback - }, { - key: 'seeking', - get: function get$$1() { - return Boolean(this.media.seeking); - } + if (is.function(callback)) { + callback.call(_this2.elements.original); + } // Reset state - /** - * Get the duration of the current media - */ - }, { - key: 'duration', - get: function get$$1() { - // Faux duration set via config - var fauxDuration = parseFloat(this.config.duration); + _this2.ready = false; // Clear for garbage collection - // True duration - var realDuration = this.media ? Number(this.media.duration) : 0; + setTimeout(function () { + _this2.elements = null; + _this2.media = null; + }, 200); + } + }; // Stop playback - // If custom duration is funky, use regular duration - return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration; - } - /** - * Set the player volume - * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage - */ + this.stop(); // Provider specific stuff - }, { - key: 'volume', - set: function set$$1(value) { - var volume = value; - var max = 1; - var min = 0; - - if (utils.is.string(volume)) { - volume = Number(volume); - } + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); // Restore native video controls - // Load volume from storage if no value specified - if (!utils.is.number(volume)) { - volume = this.storage.get('volume'); - } + ui.toggleNativeControls.call(this, true); // Clean up - // Use config if all else fails - if (!utils.is.number(volume)) { - volume = this.config.volume; - } + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); // Destroy YouTube API - // Maximum is volumeMax - if (volume > max) { - volume = max; - } - // Minimum is volumeMin - if (volume < min) { - volume = min; - } + if (this.embed !== null && is.function(this.embed.destroy)) { + this.embed.destroy(); + } // Clean up - // Update config - this.config.volume = volume; - // Set the player volume - this.media.volume = volume; + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } // Vimeo does not always return - // If muted, and we're increasing volume manually, reset muted state - if (!utils.is.empty(value) && this.muted && volume > 0) { - this.muted = false; - } - } - /** - * Get the current player volume - */ - , - get: function get$$1() { - return Number(this.media.volume); + setTimeout(done, 200); } + } + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ + }, { - key: 'muted', - set: function set$$1(mute) { - var toggle = mute; + key: "supports", + value: function supports(type) { + return support.mime.call(this, type); + } + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ - // Load muted state from storage - if (!utils.is.boolean(toggle)) { - toggle = this.storage.get('muted'); - } + }, { + key: "isHTML5", + get: function get() { + return Boolean(this.provider === providers.html5); + } + }, { + key: "isEmbed", + get: function get() { + return Boolean(this.isYouTube || this.isVimeo); + } + }, { + key: "isYouTube", + get: function get() { + return Boolean(this.provider === providers.youtube); + } + }, { + key: "isVimeo", + get: function get() { + return Boolean(this.provider === providers.vimeo); + } + }, { + key: "isVideo", + get: function get() { + return Boolean(this.type === types.video); + } + }, { + key: "isAudio", + get: function get() { + return Boolean(this.type === types.audio); + } + }, { + key: "playing", + get: function get() { + return Boolean(this.ready && !this.paused && !this.ended); + } + /** + * Get paused state + */ - // Use config if all else fails - if (!utils.is.boolean(toggle)) { - toggle = this.config.muted; - } + }, { + key: "paused", + get: function get() { + return Boolean(this.media.paused); + } + /** + * Get stopped state + */ - // Update config - this.config.muted = toggle; + }, { + key: "stopped", + get: function get() { + return Boolean(this.paused && this.currentTime === 0); + } + /** + * Get ended state + */ - // Set mute on the player - this.media.muted = toggle; - } + }, { + key: "ended", + get: function get() { + return Boolean(this.media.ended); + } + }, { + key: "currentTime", + set: function set(input) { + // Bail if media duration isn't available yet + if (!this.duration) { + return; + } // Validate input - /** - * Get current muted state - */ - , - get: function get$$1() { - return Boolean(this.media.muted); - } - /** - * Check if the media has audio - */ + var inputIsValid = is.number(input) && input > 0; // Set + + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging + + this.debug.log("Seeking to ".concat(this.currentTime, " seconds")); + } + /** + * Get current time + */ + , + get: function get() { + return Number(this.media.currentTime); + } + /** + * Get buffered + */ }, { - key: 'hasAudio', - get: function get$$1() { - // Assume yes for all non HTML5 (as we can't tell...) - if (!this.isHTML5) { - return true; - } + key: "buffered", + get: function get() { + var buffered = this.media.buffered; // YouTube / Vimeo return a float between 0-1 - if (this.isAudio) { - return true; - } + if (is.number(buffered)) { + return buffered; + } // HTML5 + // TODO: Handle buffered chunks of the media + // (i.e. seek to another section buffers only that section) - // Get audio tracks - return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + + if (buffered && buffered.length && this.duration > 0) { + return buffered.end(0) / this.duration; } - /** - * Set playback speed - * @param {number} speed - the speed of playback (0.5-2.0) - */ + return 0; + } + /** + * Get seeking status + */ }, { - key: 'speed', - set: function set$$1(input) { - var speed = null; - - if (utils.is.number(input)) { - speed = input; - } + key: "seeking", + get: function get() { + return Boolean(this.media.seeking); + } + /** + * Get the duration of the current media + */ - if (!utils.is.number(speed)) { - speed = this.storage.get('speed'); - } + }, { + key: "duration", + get: function get() { + // Faux duration set via config + var fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded - if (!utils.is.number(speed)) { - speed = this.config.speed.selected; - } + var realDuration = (this.media || {}).duration; + var duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration - // Set min/max - if (speed < 0.1) { - speed = 0.1; - } - if (speed > 2.0) { - speed = 2.0; - } + return fauxDuration || duration; + } + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ - if (!this.config.speed.options.includes(speed)) { - this.debug.warn('Unsupported speed (' + speed + ')'); - return; - } + }, { + key: "volume", + set: function set(value) { + var volume = value; + var max = 1; + var min = 0; - // Update config - this.config.speed.selected = speed; + if (is.string(volume)) { + volume = Number(volume); + } // Load volume from storage if no value specified - // Set media speed - this.media.playbackRate = speed; - } - /** - * Get current playback speed - */ - , - get: function get$$1() { - return Number(this.media.playbackRate); - } + if (!is.number(volume)) { + volume = this.storage.get('volume'); + } // Use config if all else fails - /** - * Set playback quality - * Currently HTML5 & YouTube only - * @param {number} input - Quality level - */ - }, { - key: 'quality', - set: function set$$1(input) { - var quality = null; + if (!is.number(volume)) { + volume = this.config.volume; + } // Maximum is volumeMax - if (!utils.is.empty(input)) { - quality = Number(input); - } - if (!utils.is.number(quality) || quality === 0) { - quality = this.storage.get('quality'); - } + if (volume > max) { + volume = max; + } // Minimum is volumeMin - if (!utils.is.number(quality)) { - quality = this.config.quality.selected; - } - if (!utils.is.number(quality)) { - quality = this.config.quality.default; - } + if (volume < min) { + volume = min; + } // Update config - if (!this.options.quality.length) { - return; - } - if (!this.options.quality.includes(quality)) { - var closest = utils.closest(this.options.quality, quality); - this.debug.warn('Unsupported quality option: ' + quality + ', using ' + closest + ' instead'); - quality = closest; - } + this.config.volume = volume; // Set the player volume - // Update config - this.config.quality.selected = quality; + this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state - // Set quality - this.media.quality = quality; + if (!is.empty(value) && this.muted && volume > 0) { + this.muted = false; } + } + /** + * Get the current player volume + */ + , + get: function get() { + return Number(this.media.volume); + } + }, { + key: "muted", + set: function set(mute) { + var toggle = mute; // Load muted state from storage + + if (!is.boolean(toggle)) { + toggle = this.storage.get('muted'); + } // Use config if all else fails + + + if (!is.boolean(toggle)) { + toggle = this.config.muted; + } // Update config - /** - * Get current quality level - */ - , - get: function get$$1() { - return this.media.quality; - } - /** - * Toggle loop - * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config - * @param {boolean} input - Whether to loop or not - */ + this.config.muted = toggle; // Set mute on the player + + this.media.muted = toggle; + } + /** + * Get current muted state + */ + , + get: function get() { + return Boolean(this.media.muted); + } + /** + * Check if the media has audio + */ }, { - key: 'loop', - set: function set$$1(input) { - var toggle = utils.is.boolean(input) ? input : this.config.loop.active; - this.config.loop.active = toggle; - this.media.loop = toggle; - - // Set default to be a true toggle - /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; - switch (type) { - case 'start': - if (this.config.loop.end && this.config.loop.end <= this.currentTime) { - this.config.loop.end = null; - } - this.config.loop.start = this.currentTime; - // this.config.loop.indicator.start = this.elements.display.played.value; - break; - case 'end': - if (this.config.loop.start >= this.currentTime) { - return this; - } - this.config.loop.end = this.currentTime; - // this.config.loop.indicator.end = this.elements.display.played.value; - break; - case 'all': - this.config.loop.start = 0; - this.config.loop.end = this.duration - 2; - this.config.loop.indicator.start = 0; - this.config.loop.indicator.end = 100; - break; - case 'toggle': - if (this.config.loop.active) { - this.config.loop.start = 0; - this.config.loop.end = null; - } else { - this.config.loop.start = 0; - this.config.loop.end = this.duration - 2; - } - break; - default: - this.config.loop.start = 0; - this.config.loop.end = null; - break; - } */ + key: "hasAudio", + get: function get() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; } - /** - * Get current loop state - */ - , - get: function get$$1() { - return Boolean(this.media.loop); - } + if (this.isAudio) { + return true; + } // Get audio tracks - /** - * Set new media source - * @param {object} input - The new source object (see docs) - */ + + return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } + /** + * Set playback speed + * @param {number} speed - the speed of playback (0.5-2.0) + */ }, { - key: 'source', - set: function set$$1(input) { - source.change.call(this, input); + key: "speed", + set: function set(input) { + var speed = null; + + if (is.number(input)) { + speed = input; } - /** - * Get current source - */ - , - get: function get$$1() { - return this.media.currentSrc; + if (!is.number(speed)) { + speed = this.storage.get('speed'); } - /** - * Set the poster image for a video - * @param {input} - the URL for the new poster image - */ + if (!is.number(speed)) { + speed = this.config.speed.selected; + } // Set min/max - }, { - key: 'poster', - set: function set$$1(input) { - if (!this.isVideo) { - this.debug.warn('Poster can only be set for video'); - return; - } - if (utils.is.string(input)) { - this.media.setAttribute('poster', input); - ui.setPoster.call(this); - } + if (speed < 0.1) { + speed = 0.1; } - /** - * Get the current poster image - */ - , - get: function get$$1() { - if (!this.isVideo) { - return null; - } - - return this.media.getAttribute('poster'); + if (speed > 2.0) { + speed = 2.0; } - /** - * Set the autoplay state - * @param {boolean} input - Whether to autoplay or not - */ + if (!this.config.speed.options.includes(speed)) { + this.debug.warn("Unsupported speed (".concat(speed, ")")); + return; + } // Update config + + + this.config.speed.selected = speed; // Set media speed + + this.media.playbackRate = speed; + } + /** + * Get current playback speed + */ + , + get: function get() { + return Number(this.media.playbackRate); + } + /** + * Set playback quality + * Currently HTML5 & YouTube only + * @param {number} input - Quality level + */ }, { - key: 'autoplay', - set: function set$$1(input) { - var toggle = utils.is.boolean(input) ? input : this.config.autoplay; - this.config.autoplay = toggle; - } + key: "quality", + set: function set(input) { + var config = this.config.quality; + var options = this.options.quality; - /** - * Get the current autoplay state - */ - , - get: function get$$1() { - return Boolean(this.config.autoplay); + if (!options.length) { + return; } - }, { - key: 'language', - set: function set$$1(input) { - // Nothing specified - if (!utils.is.string(input)) { - return; - } - // If empty string is passed, assume disable captions - if (utils.is.empty(input)) { - this.toggleCaptions(false); - return; - } + var quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number); + var updateStorage = true; - // Normalize - var language = input.toLowerCase(); + if (!options.includes(quality)) { + var value = closest(options, quality); + this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); + quality = value; // Don't update storage if quality is not supported - // Check for support - if (!this.options.captions.includes(language)) { - this.debug.warn('Unsupported language option: ' + language); - return; - } + updateStorage = false; + } // Update config - // Ensure captions are enabled - this.toggleCaptions(true); - // Enabled only - if (language === 'enabled') { - return; - } + config.selected = quality; // Set quality - // If nothing to change, bail - if (this.language === language) { - return; - } + this.media.quality = quality; // Save to storage - // Update config - this.captions.language = language; + if (updateStorage) { + this.storage.set({ + quality: quality + }); + } + } + /** + * Get current quality level + */ + , + get: function get() { + return this.media.quality; + } + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ - // Clear caption - captions.setText.call(this, null); + }, { + key: "loop", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; // Set default to be a true toggle + + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; + } + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; + } + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; + case 'toggle': + if (this.config.loop.active) { + this.config.loop.start = 0; + this.config.loop.end = null; + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } + /** + * Get current loop state + */ + , + get: function get() { + return Boolean(this.media.loop); + } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ - // Update captions - captions.setLanguage.call(this); + }, { + key: "source", + set: function set(input) { + source.change.call(this, input); + } + /** + * Get current source + */ + , + get: function get() { + return this.media.currentSrc; + } + /** + * Get a download URL (either source or custom) + */ - // Trigger an event - utils.dispatchEvent.call(this, this.media, 'languagechange'); + }, { + key: "download", + get: function get() { + var download = this.config.urls.download; + return is.url(download) ? download : this.source; + } + /** + * Set the poster image for a video + * @param {input} - the URL for the new poster image + */ + + }, { + key: "poster", + set: function set(input) { + if (!this.isVideo) { + this.debug.warn('Poster can only be set for video'); + return; } - /** - * Get the current captions language - */ - , - get: function get$$1() { - return this.captions.language; + ui.setPoster.call(this, input, false).catch(function () {}); + } + /** + * Get the current poster image + */ + , + get: function get() { + if (!this.isVideo) { + return null; } - /** - * Toggle picture-in-picture playback on WebKit/MacOS - * TODO: update player with state, support, enabled - * TODO: detect outside changes - */ + return this.media.getAttribute('poster'); + } + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ }, { - key: 'pip', - set: function set$$1(input) { - var states = { - pip: 'picture-in-picture', - inline: 'inline' - }; + key: "autoplay", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } + /** + * Get the current autoplay state + */ + , + get: function get() { + return Boolean(this.config.autoplay); + } + }, { + key: "currentTrack", + set: function set(input) { + captions.set.call(this, input, false); + } + /** + * Get the current caption track index (-1 if disabled) + */ + , + get: function get() { + var _this$captions = this.captions, + toggled = _this$captions.toggled, + currentTrack = _this$captions.currentTrack; + return toggled ? currentTrack : -1; + } + /** + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ - // Bail if no support - if (!support.pip) { - return; - } + }, { + key: "language", + set: function set(input) { + captions.setLanguage.call(this, input, false); + } + /** + * Get the current track's language + */ + , + get: function get() { + return (captions.getCurrentTrack.call(this) || {}).language; + } + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ - // Toggle based on current state if not passed - var toggle = utils.is.boolean(input) ? input : this.pip === states.inline; + }, { + key: "pip", + set: function set(input) { + // Bail if no support + if (!support.pip) { + return; + } // Toggle based on current state if not passed - // Toggle based on current state - this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline); - } - /** - * Get the current picture-in-picture state - */ - , - get: function get$$1() { - if (!support.pip) { - return null; - } + var toggle = is.boolean(input) ? input : !this.pip; // Toggle based on current state + // Safari - return this.media.webkitPresentationMode; - } - }], [{ - key: 'supported', - value: function supported(type, provider, inline) { - return support.check(type, provider, inline); - } + if (is.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } // Chrome - /** - * Load an SVG sprite into the page - * @param {string} url - URL for the SVG sprite - * @param {string} [id] - Unique ID - */ - }, { - key: 'loadSprite', - value: function loadSprite(url, id) { - return utils.loadSprite(url, id); + if (is.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } } + } + /** + * Get the current picture-in-picture state + */ + , + get: function get() { + if (!support.pip) { + return null; + } // Safari + - /** - * Setup multiple instances - * @param {*} selector - * @param {object} options - */ + if (!is.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } // Chrome + + + return this.media === document.pictureInPictureElement; + } + }], [{ + key: "supported", + value: function supported(type, provider, inline) { + return support.check(type, provider, inline); + } + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ }, { - key: 'setup', - value: function setup(selector) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - var targets = null; - - if (utils.is.string(selector)) { - targets = Array.from(document.querySelectorAll(selector)); - } else if (utils.is.nodeList(selector)) { - targets = Array.from(selector); - } else if (utils.is.array(selector)) { - targets = selector.filter(function (i) { - return utils.is.element(i); - }); - } + key: "loadSprite", + value: function loadSprite$$1(url, id) { + return loadSprite(url, id); + } + /** + * Setup multiple instances + * @param {*} selector + * @param {object} options + */ - if (utils.is.empty(targets)) { - return null; - } + }, { + key: "setup", + value: function setup(selector) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var targets = null; - return targets.map(function (t) { - return new Plyr(t, options); - }); + if (is.string(selector)) { + targets = Array.from(document.querySelectorAll(selector)); + } else if (is.nodeList(selector)) { + targets = Array.from(selector); + } else if (is.array(selector)) { + targets = selector.filter(is.element); + } + + if (is.empty(targets)) { + return null; } + + return targets.map(function (t) { + return new Plyr(t, options); + }); + } }]); + return Plyr; -}(); + }(); -return Plyr; + Plyr.defaults = cloneDeep(defaults); -}))); + return Plyr; -//# sourceMappingURL=plyr.js.map +}))); diff --git a/dist/plyr.js.map b/dist/plyr.js.map deleted file mode 100644 index 94fe5404..00000000 --- a/dist/plyr.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../node_modules/loadjs/dist/loadjs.umd.js","types.js","utils.js","support.js","html5.js","i18n.js","ui.js","controls.js","captions.js","console.js","defaults.js","fullscreen.js","listeners.js","plugins/vimeo.js","plugins/youtube.js","media.js","plugins/ads.js","source.js","storage.js","plyr.js"],"names":["define","this","providers","types","utils","input","instanceof","window","Plyr","getConstructor","Object","Number","isNaN","String","Boolean","Function","nullOrUndefined","Array","isArray","WeakMap","NodeList","Element","Text","Event","TextTrackCue","VTTCue","TextTrack","string","kind","test","array","nodeList","length","object","keys","constructor","document","documentMode","documentElement","style","navigator","userAgent","platform","url","responseType","Promise","resolve","reject","request","XMLHttpRequest","addEventListener","JSON","parse","responseText","e","response","Error","statusText","open","send","id","is","prefix","hasId","isCached","exists","querySelectorAll","injectSprite","data","innerHTML","body","insertBefore","childNodes","container","createElement","toggleHidden","setAttribute","support","storage","cached","localStorage","getItem","call","content","fetch","then","empty","result","setItem","stringify","catch","Math","floor","random","elements","wrapper","targets","from","reverse","forEach","element","index","child","cloneNode","parent","parentNode","sibling","nextSibling","appendChild","type","attributes","text","setAttributes","textContent","target","removeElement","removeChild","lastChild","newChild","oldChild","replaceChild","entries","key","value","sel","existingAttributes","existing","split","selector","s","trim","className","replace","stripped","parts","start","charAt","class","hidden","hide","boolean","hasAttribute","removeAttribute","toggle","contains","classList","prototype","match","includes","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","querySelector","focused","activeElement","focusable","getElements","first","last","trap","event","keyCode","getFocusElement","shiftKey","focus","preventDefault","on","off","callback","passive","capture","function","Node","toggleListener","events","options","passiveListeners","bubbles","detail","CustomEvent","assign","plyr","dispatchEvent","toggleState","pressed","getAttribute","state","args","toString","i","current","max","toFixed","parseInt","time","displayHours","inverted","number","formatTime","format","slice","hours","getHours","mins","getMinutes","secs","getSeconds","find","RegExp","toUpperCase","substr","toLowerCase","replaceAll","toTitleCase","toPascalCase","sources","source","shift","extend","filter","item","indexOf","reduce","prev","curr","abs","youtube","vimeo","regex","$2","parser","href","search","startsWith","parseUrl","hashes","params","hash","val","decodeURIComponent","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","getRatio","w","h","ratio","transitionEndEvent","undefined","offsetHeight","provider","playsinline","api","ui","browser","getBrowser","canPlayInline","isIPhone","video","rangeInput","audio","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","isHTML5","canPlayType","isVideo","isAudio","supported","defineProperty","range","matchMedia","html5","getSources","sizes","dedupe","player","mime","currentTime","playing","src","load","play","config","blankVideo","debug","log","i18n","seekTime","title","toggleClass","selectors","classNames","uiSupported","listeners","warn","toggleNativeControls","controls","inject","setup","volume","muted","speed","loop","quality","updateVolume","timeUpdate","checkPlaying","pip","airplay","isIos","isTouch","touch","ready","setTitle","setPoster","label","get","buttons","isEmbed","iframe","getElement","poster","posters","backgroundImage","p","paused","stopped","toggleControls","loading","timers","setTimeout","failed","networkState","error","inputs","setRange","mute","updateRangeFill","progress","display","buffer","getElementsByTagName","nodeValue","getPercentage","duration","seek","setProgress","buffered","forceHours","invert","invertTime","updateTimeDisplay","seeking","updateProgress","hasDuration","displayDuration","updateSeekTooltip","isWebkit","setProperty","URL","iconUrl","location","cors","host","isIE","svg4everybody","pause","restart","rewind","fastForward","settings","captions","fullscreen","seekTooltip","tooltip","namespace","getIconUrl","iconPath","iconPrefix","icon","createElementNS","use","path","setAttributeNS","attr","badge","menu","buttonType","button","toCamelCase","labelPressed","iconPressed","control","createIcon","createLabel","getAttributesFromSelector","push","suffix","list","checked","radio","faux","insertAdjacentHTML","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","parseFloat","setting","tabs","panes","toggleTab","checkMenu","emptyElement","getBadge","createBadge","sort","a","b","sorting","getLabel","createMenuItem","updateSetting","pane","active","some","lang","language","default","getTracks","tracks","track","unshift","isVimeo","values","tab","form","show","isMenuItem","isButton","stopPropagation","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","isTab","transitions","reducedMotion","size","getTabSize","restore","propertyName","createButton","createRange","createProgress","createTime","inner","home","back","setQualityMenu","getQualityOptions","setSpeedMenu","loadSprite","props","update","create","findElements","repaint","labels","stored","isYouTube","textTracks","setCaptionsMenu","insertAfter","enabled","hostname","protocol","createObjectURL","blob","setLanguage","setCue","mode","currentTrack","getCurrentTrack","activeCues","embed","enableTextTrack","cue","setText","getCueAsHTML","caption","noop","Console","console","bind","defaults","userLanguage","onChange","trapFocus","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","x","y","overflow","fallback","Fullscreen","property","native","iosNative","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","cancelFullScreen","exitFullscreen","action","enter","exit","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","prefixes","pre","Listeners","lastKey","handleKey","toggleMenu","firstTouch","code","which","repeat","altKey","ctrlKey","metaKey","seekByKey","editable","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","keyboard","global","tabFocus","hideControls","durationUpdate","hasAudio","resetOnEnd","checkLoading","ads","initialized","managerPromise","clickToPlay","ended","disableContextMenu","set","concat","inputEvent","proxy","defaultHandler","customHandlerKey","customHandler","hasCustomHandler","returned","showHomeTab","showTab","toggleInvert","hover","webkitDirectionInvertedFromDevice","step","direction","deltaY","deltaX","setAspectRatio","Vimeo","loadScript","urls","sdk","padding","paddingBottom","offset","transform","autoplay","buildUrlParams","parseVimeoId","embedContainer","replaceElement","thumbnail_large","pathname","Player","autopause","disableTextTrack","stop","setCurrentTime","selected","setPlaybackRate","setVolume","setLoop","currentSrc","getVideoUrl","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","setAutopause","getVideoTitle","getCurrentTime","getDuration","getTextTracks","cues","stripHTML","frame","seconds","build","mapQualityUnit","mapQualityUnits","levels","level","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","videoId","getVideoData","google","items","snippet","currentId","parseYouTubeId","generateId","message","instance","playbackRate","getPlaybackRate","getTitle","playVideo","pauseVideo","stopVideo","seekTo","getPlaybackQuality","setPlaybackQuality","getAvailablePlaybackRates","buffering","setInterval","getVideoLoadedFraction","lastBuffered","getAvailableQualityLevels","wrap","Ads","publisherId","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","googleIMA","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","displayContainer","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","tagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","cancel","contentComplete","seekedTime","discardAdBreak","splice","resize","ViewMode","NORMAL","initialize","init","adError","zIndex","destroy","handlers","handler","apply","Date","now","base","insertElement","attribute","cancelRequests","check","crossorigin","addStyleHook","insertElements","Storage","store","json","removeItem","jQuery","original","tagName","getProviderByUrl","getUrlParams","truthy","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","showEvents","delayEvents","noTransition","toggled","soft","done","clear","unload","targetTime","end","fauxDuration","realDuration","min","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","closest","change","states","inline","webkitPresentationMode","t"],"mappings":"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","file":"plyr.js","sourcesContent":["(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText`\n result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\nexport default { providers, types };\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport loadjs from 'loadjs';\nimport support from './support';\nimport { providers } from './types';\n\nconst utils = {\n // Check variable types\n is: {\n plyr(input) {\n return this.instanceof(input, window.Plyr);\n },\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.nullOrUndefined(input) && Array.isArray(input);\n },\n weakMap(input) {\n return this.instanceof(input, window.WeakMap);\n },\n nodeList(input) {\n return this.instanceof(input, window.NodeList);\n },\n element(input) {\n return this.instanceof(input, window.Element);\n },\n textNode(input) {\n return this.getConstructor(input) === Text;\n },\n event(input) {\n return this.instanceof(input, window.Event);\n },\n cue(input) {\n return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);\n },\n track(input) {\n return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));\n },\n url(input) {\n return !this.nullOrUndefined(input) && /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-/]))?/.test(input);\n },\n nullOrUndefined(input) {\n return input === null || typeof input === 'undefined';\n },\n empty(input) {\n return (\n this.nullOrUndefined(input) ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||\n (this.object(input) && !Object.keys(input).length)\n );\n },\n instanceof(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n getConstructor(input) {\n return !this.nullOrUndefined(input) ? input.constructor : null;\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Fetch wrapper\n // Using XHR to avoid issues with older browsers\n fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.statusText);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n },\n\n // Load an external script\n loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (!utils.is.string(url)) {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = utils.is.string(id);\n let isCached = false;\n\n const exists = () => document.querySelectorAll(`#${id}`).length;\n\n function injectSprite(data) {\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n // Create container\n const container = document.createElement('div');\n utils.toggleHidden(container, true);\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n injectSprite.call(container, data.content);\n return;\n }\n }\n\n // Get the sprite\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.empty(result)) {\n return;\n }\n\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n injectSprite.call(container, result);\n })\n .catch(() => {});\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new <element>\n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove element(s)\n removeElement(element) {\n if (utils.is.nodeList(element) || utils.is.array(element)) {\n Array.from(element).forEach(utils.removeElement);\n return;\n }\n\n if (!utils.is.element(element) || !utils.is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Replace element\n replaceElement(newChild, oldChild) {\n if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n if (!utils.is.element(element) || utils.is.empty(attributes)) {\n return;\n }\n\n Object.entries(attributes).forEach(([\n key,\n value,\n ]) => {\n element.setAttribute(key, value);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle hidden\n toggleHidden(element, hidden) {\n if (!utils.is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!utils.is.boolean(hide)) {\n hide = !element.hasAttribute('hidden');\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.element(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.element(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus(element = null, toggle = false) {\n if (!utils.is.element(element)) {\n return;\n }\n\n const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n if (toggle) {\n utils.on(this.elements.container, 'keydown', trap, false);\n } else {\n utils.off(this.elements.container, 'keydown', trap, false);\n }\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no elemetns, event, or callback\n if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements) || utils.is.array(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!utils.is.element(element) || utils.is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: utils.is.plyr(this) ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // If multiple elements passed\n if (utils.is.array(element) || utils.is.nodeList(element)) {\n Array.from(element).forEach(target => utils.toggleState(target, input));\n return;\n }\n\n // Bail if no target\n if (!utils.is.element(element)) {\n return;\n }\n\n // Get state\n const pressed = element.getAttribute('aria-pressed') === 'true';\n const state = utils.is.boolean(input) ? input : !pressed;\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Format string\n format(input, ...args) {\n if (utils.is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : '');\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return (current / max * 100).toFixed(2);\n },\n\n // Time helpers\n getHours(value) {\n return parseInt((value / 60 / 60) % 60, 10);\n },\n getMinutes(value) {\n return parseInt((value / 60) % 60, 10);\n },\n getSeconds(value) {\n return parseInt(value % 60, 10);\n },\n\n // Format time to UI friendly string\n formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!utils.is.number(time)) {\n return this.formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = this.getHours(time);\n const mins = this.getMinutes(time);\n const secs = this.getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n },\n\n // Replace all occurances of a string in a string\n replaceAll(input = '', find = '', replace = '') {\n return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n },\n\n // Convert to title case\n toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n },\n\n // Convert string to pascalCase\n toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = utils.replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = utils.replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = utils.toTitleCase(string);\n\n // Convert to pascal case\n return utils.replaceAll(string, ' ', '');\n },\n\n // Convert string to pascalCase\n toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = utils.toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n },\n\n // Deep extend destination object with N more objects\n extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!utils.is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (utils.is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n utils.extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return utils.extend(target, ...sources);\n },\n\n // Remove duplicates in an array\n dedupe(array) {\n if (!utils.is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n },\n\n // Get the closest value in an array\n closest(array, value) {\n if (!utils.is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n },\n\n // Get the provider for a given URL\n getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert a URL to a location object\n parseUrl(url) {\n const parser = document.createElement('a');\n parser.href = url;\n return parser;\n },\n\n // Get URL query parameters\n getUrlParams(input) {\n let search = input;\n\n // Parse URL if needed\n if (input.startsWith('http://') || input.startsWith('https://')) {\n ({ search } = this.parseUrl(input));\n }\n\n if (this.is.empty(search)) {\n return null;\n }\n\n const hashes = search.slice(search.indexOf('?') + 1).split('&');\n\n return hashes.reduce((params, hash) => {\n const [\n key,\n val,\n ] = hash.split('=');\n\n return Object.assign(params, { [key]: decodeURIComponent(val) });\n }, {});\n },\n\n // Convert object to URL parameters\n buildUrlParams(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n get transitionEndEvent() {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return utils.is.string(type) ? events[type] : false;\n },\n\n // Force repaint of element\n repaint(element) {\n setTimeout(() => {\n utils.toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n utils.toggleHidden(element, false);\n }, 0);\n },\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n\n switch (`${provider}:${type}`) {\n case 'html5:video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n case 'html5:audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!this.isHTML5 || !utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Check directly if codecs specified\n if (type.includes('codecs=')) {\n return media.canPlayType(type).replace(/no/, '');\n }\n\n // Type specific checks\n if (this.isVideo) {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.isAudio) {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return null;\n }\n\n return this.media.querySelectorAll('source');\n },\n\n // Get quality levels\n getQualityOptions() {\n if (!this.isHTML5) {\n return null;\n }\n\n // Get sources\n const sources = html5.getSources.call(this);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n // Get <source> with size attribute\n const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size')));\n\n // If none, bail\n if (utils.is.empty(sizes)) {\n return null;\n }\n\n // Reduce to unique list\n return utils.dedupe(sizes.map(source => Number(source.getAttribute('size'))));\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source);\n\n if (utils.is.empty(matches)) {\n return null;\n }\n\n return Number(matches[0].getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return;\n }\n\n // Get matches for requested size\n const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input);\n\n // No matches for requested size\n if (utils.is.empty(matches)) {\n return;\n }\n\n // Get supported sources\n const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type')));\n\n // No supported sources\n if (utils.is.empty(supported)) {\n return;\n }\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality: input,\n });\n\n // Get current state\n const { currentTime, playing } = player;\n\n // Set new source\n player.media.src = supported[0].getAttribute('src');\n\n // Load new source\n player.media.load();\n\n // Resume playing\n if (playing) {\n player.play();\n }\n\n // Restore time\n player.currentTime = currentTime;\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n utils.removeElement(html5.getSources());\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport utils from './utils';\n\nconst i18n = {\n get(key = '', config = {}) {\n if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {\n return '';\n }\n\n let string = config.i18n[key];\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([\n key,\n value,\n ]) => {\n string = utils.replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n ui.updateVolume.call(this);\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n utils.dispatchEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Set the poster image\n ui.setPoster.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Set the poster image\n setPoster() {\n if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) {\n return;\n }\n\n // Set the inline style\n const posters = this.poster.split(',');\n this.elements.poster.style.backgroundImage = posters.map(p => `url('${p}')`).join(',');\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set ARIA state\n utils.toggleState(this.elements.buttons.play, this.playing);\n\n // Only update controls on non timeupdate events\n if (utils.is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n this.toggleControls(!this.playing);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = [\n 'stalled',\n 'waiting',\n ].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Check if media failed to load\n checkFailed() {\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState\n this.failed = this.media.networkState === 3;\n\n if (this.failed) {\n utils.toggleClass(this.elements.container, this.config.classNames.loading, false);\n utils.toggleClass(this.elements.container, this.config.classNames.error, true);\n }\n\n // Clear timer\n clearTimeout(this.timers.failed);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.element(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (utils.is.element(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!utils.is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set <progress> value\n setProgress(target, input) {\n const value = utils.is.number(input) ? input : 0;\n const progress = utils.is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !utils.is.event(event)) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!utils.is.element(target) || !utils.is.number(time)) {\n return;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = utils.getHours(this.duration) > 0;\n\n // eslint-disable-next-line no-param-reassign\n target.textContent = utils.formatTime(time, forceHours, inverted);\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded\n durationUpdate() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's a spot to display duration\n const hasDuration = utils.is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport i18n from './i18n';\nimport support from './support';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria value for https://github.com/sampotts/plyr/issues/905\n range.setAttribute('aria-valuenow', range.value);\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n },\n\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (utils.is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type, attr) {\n let text = i18n.get(type, this.config);\n const attributes = Object.assign({}, attr);\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n if ('class' in attributes) {\n attributes.class += ` ${this.config.classNames.hidden}`;\n } else {\n attributes.class = this.config.classNames.hidden;\n }\n\n return utils.createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (utils.is.empty(text)) {\n return null;\n }\n\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const button = utils.createElement('button');\n const attributes = Object.assign({}, attr);\n let type = utils.toCamelCase(buttonType);\n\n let toggle = false;\n let label;\n let icon;\n let labelPressed;\n let iconPressed;\n\n if (!('type' in attributes)) {\n attributes.type = 'button';\n }\n\n if ('class' in attributes) {\n if (attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n toggle = true;\n label = 'play';\n labelPressed = 'pause';\n icon = 'play';\n iconPressed = 'pause';\n break;\n\n case 'mute':\n toggle = true;\n label = 'mute';\n labelPressed = 'unmute';\n icon = 'volume';\n iconPressed = 'muted';\n break;\n\n case 'captions':\n toggle = true;\n label = 'enableCaptions';\n labelPressed = 'disableCaptions';\n icon = 'captions-off';\n iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n toggle = true;\n label = 'enterFullscreen';\n labelPressed = 'exitFullscreen';\n icon = 'enter-fullscreen';\n iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n label = 'play';\n icon = 'play';\n break;\n\n default:\n label = type;\n icon = buttonType;\n }\n\n // Setup toggle icon and labels\n if (toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));\n button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));\n button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));\n\n // Add aria attributes\n attributes['aria-pressed'] = false;\n } else {\n button.appendChild(controls.createIcon.call(this, icon));\n button.appendChild(controls.createLabel.call(this, label));\n }\n\n // Merge attributes\n utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n\n utils.setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!utils.is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek label\n const label = utils.createElement(\n 'label',\n {\n for: attributes.id,\n id: `${attributes.id}-label`,\n class: this.config.classNames.hidden,\n },\n i18n.get(type, this.config),\n );\n\n // Seek input\n const input = utils.createElement(\n 'input',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-labelledby': `${attributes.id}-label`,\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return {\n label,\n input,\n };\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = utils.createElement(\n 'progress',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(utils.createElement('span', null, '0'));\n\n let suffix = '';\n switch (type) {\n case 'played':\n suffix = i18n.get('played', this.config);\n break;\n\n case 'buffer':\n suffix = i18n.get('buffered', this.config);\n break;\n\n default:\n break;\n }\n\n progress.textContent = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = utils.createElement('div', utils.extend(attributes, {\n class: `plyr__time ${attributes.class}`,\n 'aria-label': i18n.get(type, this.config),\n }), '00:00');\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Create a settings menu item\n createMenuItem(value, list, type, title, badge = null, checked = false) {\n const item = utils.createElement('li');\n\n const label = utils.createElement('label', {\n class: this.config.classNames.control,\n });\n\n const radio = utils.createElement(\n 'input',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'radio',\n name: `plyr-${type}`,\n value,\n checked,\n class: 'plyr__sr-only',\n }),\n );\n\n const faux = utils.createElement('span', { hidden: '' });\n\n label.appendChild(radio);\n label.appendChild(faux);\n label.insertAdjacentHTML('beforeend', title);\n\n if (utils.is.element(badge)) {\n label.appendChild(badge);\n }\n\n item.appendChild(label);\n list.appendChild(item);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !utils.is.element(this.elements.inputs.seek) ||\n !utils.is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.inputs.seek.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (utils.is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (utils.is.event(event) && [\n 'mouseenter',\n 'mouseleave',\n ].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Hide/show a tab\n toggleTab(setting, toggle) {\n utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);\n },\n\n // Set the quality menu\n // TODO: Vimeo support\n setQualityMenu(options) {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panes.quality.querySelector('ul');\n\n // Set options if passed and filter based on config\n if (utils.is.array(options)) {\n this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n let label = '';\n\n switch (quality) {\n case 2160:\n label = '4K';\n break;\n\n case 1440:\n case 1080:\n case 720:\n label = 'HD';\n break;\n\n case 576:\n case 480:\n label = 'SD';\n break;\n\n default:\n break;\n }\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n const label = controls.getLabel.call(this, 'quality', quality);\n controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Translate a value into a nice label\n // TODO: Localisation\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (utils.is.number(value)) {\n return `${value}p`;\n }\n\n return utils.toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panes[setting];\n let value = null;\n let list = container;\n\n switch (setting) {\n case 'captions':\n if (this.captions.active) {\n if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) {\n value = this.captions.language;\n } else {\n value = 'enabled';\n }\n } else {\n value = '';\n }\n\n break;\n\n default:\n value = !utils.is.empty(input) ? input : this[setting];\n\n // Get default\n if (utils.is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n\n break;\n }\n\n // Get the list if we need to\n if (!utils.is.element(list)) {\n list = pane && pane.querySelector('ul');\n }\n\n // If there's no list it means it's not been rendered...\n if (!utils.is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`input[value=\"${value}\"]`);\n\n if (utils.is.element(target)) {\n target.checked = true;\n }\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panes.loop.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.loop, false);\n utils.toggleHidden(this.elements.settings.panes.loop, false);\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.loop.options);\n controls.toggleTab.call(this, 'loop', toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n options.forEach(option => {\n const item = utils.createElement('li');\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panes.captions.querySelector('ul');\n\n // Toggle the pane and tab\n const toggle = captions.getTracks.call(this).length;\n controls.toggleTab.call(this, type, toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Re-map the tracks into just the data we need\n const tracks = captions.getTracks.call(this).map(track => ({\n language: !utils.is.empty(track.language) ? track.language : 'enabled',\n label: captions.getLabel.call(this, track),\n }));\n\n // Add the \"Disabled\" option to turn off captions\n tracks.unshift({\n language: '',\n label: i18n.get('disabled', this.config),\n });\n\n // Generate options\n tracks.forEach(track => {\n controls.createMenuItem.call(\n this,\n track.language,\n list,\n 'language',\n track.label,\n track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null,\n track.language.toLowerCase() === this.captions.language.toLowerCase(),\n );\n });\n\n // Store reference\n this.options.captions = tracks.map(track => track.language);\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Do nothing if not selected\n if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) {\n return;\n }\n\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.speed)) {\n return;\n }\n\n const type = 'speed';\n\n // Set the speed options\n if (utils.is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the list to populate\n const list = this.elements.settings.panes.speed.querySelector('ul');\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Create items\n this.options.speed.forEach(speed => {\n const label = controls.getLabel.call(this, 'speed', speed);\n controls.createMenuItem.call(this, speed, list, type, label);\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { tabs } = this.elements.settings;\n const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);\n\n utils.toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Show/hide menu\n toggleMenu(event) {\n const { form } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!utils.is.element(form) || !utils.is.element(button)) {\n return;\n }\n\n const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');\n\n if (utils.is.event(event)) {\n const isMenuItem = utils.is.element(form) && form.contains(event.target);\n const isButton = event.target === this.elements.buttons.settings;\n\n // If the click was inside the form or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && !isButton && show)) {\n return;\n }\n\n // Prevent the toggle being caught by the doc listener\n if (isButton) {\n event.stopPropagation();\n }\n }\n\n // Set form and button attributes\n if (utils.is.element(button)) {\n button.setAttribute('aria-expanded', show);\n }\n\n if (utils.is.element(form)) {\n utils.toggleHidden(form, !show);\n utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n if (show) {\n form.removeAttribute('tabindex');\n } else {\n form.setAttribute('tabindex', -1);\n }\n }\n },\n\n // Get the natural size of a tab\n getTabSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Prevent input's being unchecked due to the name being identical\n Array.from(clone.querySelectorAll('input[name]')).forEach(input => {\n const name = input.getAttribute('name');\n input.setAttribute('name', `${name}-clone`);\n });\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n utils.removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Toggle Menu\n showTab(target = '') {\n const { menu } = this.elements.settings;\n const pane = document.getElementById(target);\n\n // Nothing to show, bail\n if (!utils.is.element(pane)) {\n return;\n }\n\n // Are we targetting a tab? If not, bail\n const isTab = pane.getAttribute('role') === 'tabpanel';\n if (!isTab) {\n return;\n }\n\n // Hide all other tabs\n // Get other tabs\n const current = menu.querySelector('[role=\"tabpanel\"]:not([hidden])');\n const container = current.parentNode;\n\n // Set other toggles to be expanded false\n Array.from(menu.querySelectorAll(`[aria-controls=\"${current.getAttribute('id')}\"]`)).forEach(toggle => {\n toggle.setAttribute('aria-expanded', false);\n });\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getTabSize.call(this, pane);\n\n // Restore auto height/width\n const restore = e => {\n // We're only bothered about height and width on the container\n if (e.target !== container || ![\n 'width',\n 'height',\n ].includes(e.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n utils.off(container, utils.transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n utils.on(container, utils.transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n utils.toggleHidden(current, true);\n current.setAttribute('tabindex', -1);\n\n // Set attributes on target\n utils.toggleHidden(pane, false);\n\n const tabs = utils.getElements.call(this, `[aria-controls=\"${target}\"]`);\n Array.from(tabs).forEach(tab => {\n tab.setAttribute('aria-expanded', true);\n });\n pane.removeAttribute('tabindex');\n\n // Focus the first item\n pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Do nothing if we want no controls\n if (utils.is.empty(this.config.controls)) {\n return null;\n }\n\n // Create the container\n const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n const seek = controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n });\n progress.appendChild(seek.label);\n progress.appendChild(seek.input);\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = utils.createElement(\n 'span',\n {\n role: 'tooltip',\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n container.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n const volume = utils.createElement('div', {\n class: 'plyr__volume',\n });\n\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n const range = controls.createRange.call(\n this,\n 'volume',\n utils.extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n );\n volume.appendChild(range.label);\n volume.appendChild(range.input);\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n const menu = utils.createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n menu.appendChild(\n controls.createButton.call(this, 'settings', {\n id: `plyr-settings-toggle-${data.id}`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const form = utils.createElement('form', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tablist',\n tabindex: -1,\n });\n\n const inner = utils.createElement('div');\n\n const home = utils.createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tabpanel',\n });\n\n // Create the tab list\n const tabs = utils.createElement('ul', {\n role: 'tablist',\n });\n\n // Build the tabs\n this.config.settings.forEach(type => {\n const tab = utils.createElement('li', {\n role: 'tab',\n hidden: '',\n });\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n id: `plyr-settings-${data.id}-${type}-tab`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-${type}`,\n 'aria-expanded': false,\n }),\n i18n.get(type, this.config),\n );\n\n const value = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n button.appendChild(value);\n tab.appendChild(button);\n tabs.appendChild(tab);\n\n this.elements.settings.tabs[type] = tab;\n });\n\n home.appendChild(tabs);\n inner.appendChild(home);\n\n // Build the panes\n this.config.settings.forEach(type => {\n const pane = utils.createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,\n role: 'tabpanel',\n tabindex: -1,\n });\n\n const back = utils.createElement(\n 'button',\n {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-home`,\n 'aria-expanded': false,\n },\n i18n.get(type, this.config),\n );\n\n pane.appendChild(back);\n\n const options = utils.createElement('ul');\n\n pane.appendChild(options);\n inner.appendChild(pane);\n\n this.elements.settings.panes[type] = pane;\n });\n\n form.appendChild(inner);\n menu.appendChild(form);\n container.appendChild(menu);\n\n this.elements.settings.form = form;\n this.elements.settings.menu = menu;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n utils.loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {\n // String or HTMLElement passed as the option\n container = this.config.controls;\n } else if (utils.is.function(this.config.controls)) {\n // A custom function to build controls\n // The function can return a HTMLElement or String\n container = this.config.controls.call(this, props);\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([\n key,\n value,\n ]) => {\n result = utils.replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (utils.is.string(this.config.controls)) {\n container = replace(container);\n } else if (utils.is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (utils.is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!utils.is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML\n if (utils.is.element(container)) {\n target.appendChild(container);\n } else if (container) {\n target.insertAdjacentHTML('beforeend', container);\n }\n\n // Find the elements if need be\n if (!utils.is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Edge sometimes doesn't finish the paint so force a redraw\n if (window.navigator.userAgent.includes('Edge')) {\n utils.repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const labels = utils.getElements.call(\n this,\n [\n this.config.selectors.controls.wrapper,\n ' ',\n this.config.selectors.labels,\n ' .',\n this.config.classNames.hidden,\n ].join(''),\n );\n\n Array.from(labels).forEach(label => {\n utils.toggleClass(label, this.config.classNames.hidden, false);\n utils.toggleClass(label, this.config.classNames.tooltip, true);\n label.setAttribute('role', 'tooltip');\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Set default language if not set\n const stored = this.storage.get('language');\n\n if (!utils.is.empty(stored)) {\n this.captions.language = stored;\n }\n\n if (utils.is.empty(this.captions.language)) {\n this.captions.language = this.config.captions.language.toLowerCase();\n }\n\n // Set captions enabled state if not set\n if (!utils.is.boolean(this.captions.active)) {\n const active = this.storage.get('captions');\n\n if (utils.is.boolean(active)) {\n this.captions.active = active;\n } else {\n this.captions.active = this.config.captions.active;\n }\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!utils.is.element(this.elements.captions)) {\n this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));\n\n utils.insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Set the class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));\n\n // Get tracks\n const tracks = captions.getTracks.call(this);\n\n // If no caption file exists, hide container for caption text\n if (utils.is.empty(tracks)) {\n return;\n }\n\n // Get browser info\n const browser = utils.getBrowser();\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const href = utils.parseUrl(src);\n\n if (href.hostname !== window.location.href.hostname && [\n 'http:',\n 'https:',\n ].includes(href.protocol)) {\n utils\n .fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n utils.removeElement(track);\n });\n }\n });\n }\n\n // Set language\n captions.setLanguage.call(this);\n\n // Enable UI\n captions.show.call(this);\n\n // Set available languages in list\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Set the captions language\n setLanguage() {\n // Setup HTML5 track rendering\n if (this.isHTML5 && this.isVideo) {\n captions.getTracks.call(this).forEach(track => {\n // Show track\n utils.on(track, 'cuechange', event => captions.setCue.call(this, event));\n\n // Turn off native caption rendering to avoid double captions\n // eslint-disable-next-line\n track.mode = 'hidden';\n });\n\n // Get current track\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Check if suported kind\n if (utils.is.track(currentTrack)) {\n // If we change the active track while a cue is already displayed we need to update it\n if (Array.from(currentTrack.activeCues || []).length) {\n captions.setCue.call(this, currentTrack);\n }\n }\n } else if (this.isVimeo && this.captions.active) {\n this.embed.enableTextTrack(this.language);\n }\n },\n\n // Get the tracks\n getTracks() {\n // Return empty array at least\n if (utils.is.nullOrUndefined(this.media)) {\n return [];\n }\n\n // Only get accepted kinds\n return Array.from(this.media.textTracks || []).filter(track => [\n 'captions',\n 'subtitles',\n ].includes(track.kind));\n },\n\n // Get the current track for the current language\n getCurrentTrack() {\n const tracks = captions.getTracks.call(this);\n\n if (!tracks.length) {\n return null;\n }\n\n // Get track based on current language\n let track = tracks.find(track => track.language.toLowerCase() === this.language);\n\n // Get the <track> with default attribute\n if (!track) {\n track = utils.getElement.call(this, 'track[default]');\n }\n\n // Get the first track\n if (!track) {\n [track] = tracks;\n }\n\n return track;\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (utils.is.track(currentTrack)) {\n if (!utils.is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!utils.is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Display active caption if it contains text\n setCue(input) {\n // Get the track from the event if needed\n const track = utils.is.event(input) ? input.target : input;\n const { activeCues } = track;\n const active = activeCues.length && activeCues[0];\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Only display current track\n if (track !== currentTrack) {\n return;\n }\n\n // Display a cue, if there is one\n if (utils.is.cue(active)) {\n captions.setText.call(this, active.getCueAsHTML());\n } else {\n captions.setText.call(this, null);\n }\n\n utils.dispatchEvent.call(this, this.media, 'cuechange');\n },\n\n // Set the current caption\n setText(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (utils.is.element(this.elements.captions)) {\n const content = utils.createElement('span');\n\n // Empty the container\n utils.emptyElement(this.elements.captions);\n\n // Default to empty\n const caption = !utils.is.nullOrUndefined(input) ? input : '';\n\n // Set the span content\n if (utils.is.string(caption)) {\n content.textContent = caption.trim();\n } else {\n content.appendChild(caption);\n }\n\n // Set new caption text\n this.elements.captions.appendChild(content);\n } else {\n this.debug.warn('No captions element to render to');\n }\n },\n\n // Display captions container and button (for initialization)\n show() {\n // Try to load the value from storage\n let active = this.storage.get('captions');\n\n // Otherwise fall back to the default config\n if (!utils.is.boolean(active)) {\n ({ active } = this.config.captions);\n } else {\n this.captions.active = active;\n }\n\n if (active) {\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true);\n utils.toggleState(this.elements.buttons.captions, true);\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [\n 4320,\n 2880,\n 2160,\n 1440,\n 1080,\n 720,\n 576,\n 480,\n 360,\n 240,\n 'default', // YouTube's \"auto\"\n ],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: (navigator.language || navigator.userLanguage).split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: [\n 'captions',\n 'quality',\n 'speed',\n ],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n },\n\n // URLs\n urls: {\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n ads: 'plyr__ads',\n control: 'plyr__control',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n error: 'plyr--has-error',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// ==========================================================================\n\nimport utils from './utils';\n\nconst browser = utils.getBrowser();\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (utils.is.element(button)) {\n utils.toggleState(button, this.active);\n }\n\n // Trigger an event\n utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n utils.trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n // TODO: Filter for target??\n onChange.call(this);\n });\n\n // Fullscreen toggle on double click\n utils.on(this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (utils.is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n\n prefixes.some(pre => {\n if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native) {\n return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.playing) {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!utils.is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!utils.is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.player.currentTime = this.player.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n this.player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n this.player.muted = !this.player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.player.forward();\n break;\n\n case 37:\n // Arrow back\n this.player.rewind();\n break;\n\n case 70:\n // F key\n this.player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n this.player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.player.loop = !this.player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) {\n this.player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n this.player.touch = true;\n\n // Add touch class\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);\n\n // Clean up\n utils.off(document.body, 'touchstart', this.firstTouch);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n // Keyboard shortcuts\n if (this.player.config.keyboard.global) {\n utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n utils.on(document.body, 'touchstart', this.firstTouch);\n }\n\n // Container listeners\n container() {\n // Keyboard shortcuts\n if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {\n utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.player.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.player.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.player.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => {\n this.player.toggleControls(event);\n });\n }\n }\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));\n\n // Display duration\n utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event));\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n utils.on(this.player.media, 'loadeddata', () => {\n utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);\n utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);\n });\n\n // Handle the media finishing\n utils.on(this.player.media, 'ended', () => {\n // Show poster on end\n if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {\n // Restart\n this.player.restart();\n }\n });\n\n // Check for buffer progress\n utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event));\n\n // Handle volume changes\n utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event));\n\n // Handle play/pause\n utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));\n\n // Loading state\n utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));\n\n // Check if media failed to load\n // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n utils.on(this.player.media, 'playing', () => {\n if (!this.player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (this.player.ads.enabled && !this.player.ads.initialized) {\n // Wait for manager response\n this.player.ads.managerPromise.then(() => this.player.ads.play()).catch(() => this.player.play());\n }\n });\n\n // Click video\n if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this.player, `.${this.player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!utils.is.element(wrapper)) {\n return;\n }\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.player.config.hideControls && this.player.touch && !this.player.paused) {\n return;\n }\n\n if (this.player.paused) {\n this.player.play();\n } else if (this.player.ended) {\n this.player.restart();\n this.player.play();\n } else {\n this.player.pause();\n }\n });\n }\n\n // Disable right click\n if (this.player.supported.ui && this.player.config.disableContextMenu) {\n utils.on(\n this.player.elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n utils.on(this.player.media, 'volumechange', () => {\n // Save to storage\n this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });\n });\n\n // Speed change\n utils.on(this.player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'speed');\n\n // Save to storage\n this.player.storage.set({ speed: this.player.speed });\n });\n\n // Quality request\n utils.on(this.player.media, 'qualityrequested', event => {\n // Save to storage\n this.player.storage.set({ quality: event.detail.quality });\n });\n\n // Quality change\n utils.on(this.player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);\n });\n\n // Caption language change\n utils.on(this.player.media, 'languagechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ language: this.player.language });\n });\n\n // Captions toggle\n utils.on(this.player.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ captions: this.player.captions.active });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.player.media, this.player.config.events.concat([\n 'keyup',\n 'keydown',\n ]).join(' '), event => {\n let detail = {};\n\n // Get error details from media\n if (event.type === 'error') {\n detail = this.player.media.error;\n }\n\n utils.dispatchEvent.call(this.player, this.player.elements.container, event.type, true, detail);\n });\n }\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Run default and custom handlers\n const proxy = (event, defaultHandler, customHandlerKey) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(this.player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && utils.is.function(defaultHandler)) {\n defaultHandler.call(this.player, event);\n }\n };\n\n // Trigger custom and default handlers\n const on = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n\n utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n };\n\n // Play/pause toggle\n on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play');\n\n // Pause\n on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');\n\n // Rewind\n on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');\n\n // Rewind\n on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');\n\n // Mute toggle\n on(\n this.player.elements.buttons.mute,\n 'click',\n () => {\n this.player.muted = !this.player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions);\n\n // Fullscreen toggle\n on(\n this.player.elements.buttons.fullscreen,\n 'click',\n () => {\n this.player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n on(\n this.player.elements.buttons.pip,\n 'click',\n () => {\n this.player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');\n\n // Settings menu\n on(this.player.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this.player, event);\n });\n\n // Settings menu\n on(this.player.elements.settings.form, 'click', event => {\n event.stopPropagation();\n\n // Go back to home tab on click\n const showHomeTab = () => {\n const id = `plyr-settings-${this.player.id}-home`;\n controls.showTab.call(this.player, id);\n };\n\n // Settings menu items - use event delegation as items are added/removed\n if (utils.matches(event.target, this.player.config.selectors.inputs.language)) {\n proxy(\n event,\n () => {\n this.player.language = event.target.value;\n showHomeTab();\n },\n 'language',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.quality)) {\n proxy(\n event,\n () => {\n this.player.quality = event.target.value;\n showHomeTab();\n },\n 'quality',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.speed)) {\n proxy(\n event,\n () => {\n this.player.speed = parseFloat(event.target.value);\n showHomeTab();\n },\n 'speed',\n );\n } else {\n const tab = event.target;\n controls.showTab.call(this.player, tab.getAttribute('aria-controls'));\n }\n });\n\n // Seek\n on(\n this.player.elements.inputs.seek,\n inputEvent,\n event => {\n this.player.currentTime = event.target.value / event.target.max * this.player.duration;\n },\n 'seek',\n );\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) {\n on(this.player.elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (this.player.currentTime === 0) {\n return;\n }\n\n this.player.config.invertTime = !this.player.config.invertTime;\n ui.timeUpdate.call(this.player);\n });\n }\n\n // Volume\n on(\n this.player.elements.inputs.volume,\n inputEvent,\n event => {\n this.player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n on(utils.getElements.call(this.player, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this.player, event.target);\n });\n }\n\n // Seek tooltip\n on(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event));\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mouseenter mouseleave', event => {\n this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.player.elements.controls.pressed = [\n 'mousedown',\n 'touchstart',\n ].includes(event.type);\n });\n\n // Focus in/out on controls\n on(this.player.elements.controls, 'focusin focusout', event => {\n this.player.toggleControls(event);\n });\n }\n\n // Mouse wheel for volume\n on(\n this.player.elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.player.decreaseVolume(step);\n direction = -1;\n } else {\n this.player.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.player.increaseVolume(step);\n direction = 1;\n } else {\n this.player.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n\n // Reset on destroy\n clear() {\n this.global(false);\n }\n}\n\nexport default Listeners;\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from './../captions';\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n vimeo.setAspectRatio.call(this);\n\n // Load the API if not already\n if (!utils.is.object(window.Vimeo)) {\n utils\n .loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // Set aspect ratio\n // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n if (this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n // muted: player.muted,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n };\n const params = utils.buildUrlParams(options);\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = utils.parseVimeoId(source);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = utils.format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Inject the package\n const wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = utils.replaceElement(wrapper, player.media);\n\n // Get poster image\n utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (utils.is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set attribute\n player.media.setAttribute('poster', url.href);\n\n // Update\n ui.setPoster.call(player);\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play().then(() => {\n player.media.paused = false;\n });\n };\n\n player.media.pause = () => {\n player.embed.pause().then(() => {\n player.media.paused = true;\n });\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time).catch(() => {\n // Do nothing\n });\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([\n player.embed.getVideoWidth(),\n player.embed.getVideoHeight(),\n ]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.setText.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n utils.dispatchEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\n// Standardise YouTube quality unit\nfunction mapQualityUnit(input) {\n switch (input) {\n case 'hd2160':\n return 2160;\n\n case 2160:\n return 'hd2160';\n\n case 'hd1440':\n return 1440;\n\n case 1440:\n return 'hd1440';\n\n case 'hd1080':\n return 1080;\n\n case 1080:\n return 'hd1080';\n\n case 'hd720':\n return 720;\n\n case 720:\n return 'hd720';\n\n case 'large':\n return 480;\n\n case 480:\n return 'large';\n\n case 'medium':\n return 360;\n\n case 360:\n return 'medium';\n\n case 'small':\n return 240;\n\n case 240:\n return 'small';\n\n default:\n return 'default';\n }\n}\n\nfunction mapQualityUnits(levels) {\n if (utils.is.empty(levels)) {\n return levels;\n }\n\n return utils.dedupe(levels.map(level => mapQualityUnit(level)));\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n youtube.setAspectRatio.call(this);\n\n // Setup API\n if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n utils.loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (utils.is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (utils.is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (utils.is.string(key) && !utils.is.empty(key)) {\n const url = utils.format(this.config.urls.youtube.api, videoId, key);\n\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // Set aspect ratio\n setAspectRatio() {\n const ratio = this.config.ratio.split(':');\n this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`;\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = utils.parseYouTubeId(source);\n const id = utils.generateId(player.provider);\n const container = utils.createElement('div', { id });\n player.media = utils.replaceElement(container, player.media);\n\n // Set poster image\n player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId));\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n playerVars: {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: 1, // Allow iOS inline playback\n\n // Tracking for stats\n // origin: window ? `${window.location.protocol}//${window.location.host}` : null,\n widget_referrer: window ? window.location.href : null,\n\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n },\n events: {\n onError(event) {\n // If we've already fired an error, don't do it again\n // YouTube fires onError twice\n if (utils.is.object(player.media.error)) {\n return;\n }\n\n const detail = {\n code: event.data,\n };\n\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n switch (event.data) {\n case 2:\n detail.message =\n 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.';\n break;\n\n case 5:\n detail.message =\n 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';\n break;\n\n case 100:\n detail.message =\n 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';\n break;\n\n case 101:\n case 150:\n detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';\n break;\n\n default:\n detail.message = 'An unknown error occured';\n break;\n }\n\n player.media.error = detail;\n\n utils.dispatchEvent.call(player, player.media, 'error');\n },\n onPlaybackQualityChange() {\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: player.media.quality,\n });\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n instance.playVideo();\n };\n\n player.media.pause = () => {\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n return mapQualityUnit(instance.getPlaybackQuality());\n },\n set(input) {\n const quality = input;\n\n // Set via API\n instance.setPlaybackQuality(mapQualityUnit(quality));\n\n // Trigger request event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality,\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n utils.dispatchEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n player.media.paused = true;\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n utils.dispatchEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // If we were seeking, fire seeked event\n if (player.media.seeking) {\n utils.dispatchEvent.call(player, player.media, 'seeked');\n }\n player.media.seeking = false;\n\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n\n utils.dispatchEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n\n // Get quality\n controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));\n\n break;\n\n case 2:\n player.media.paused = true;\n\n utils.dispatchEvent.call(player, player.media, 'pause');\n\n break;\n\n default:\n break;\n }\n\n utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport utils from './utils';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = utils.createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isEmbed) {\n switch (this.provider) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n } else if (this.isHTML5) {\n html5.extend.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport i18n from '../i18n';\nimport utils from '../utils';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.publisherId = player.config.ads.publisherId;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId);\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) {\n utils\n .loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the default tag URL\n get tagUrl() {\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${utils.buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = utils.createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = utils.formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!utils.is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (utils.is.element(seekElement)) {\n const cuePercentage = 100 / this.player.duration * cuePoint;\n const cue = utils.createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Get skippable state\n // TODO: Skip button\n // this.player.debug.warn(this.manager.getAdSkippableState());\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n utils.dispatchEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('seeking', () => {\n time = this.player.currentTime;\n return time;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (utils.is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (utils.is.array(handlers)) {\n handlers.forEach(handler => {\n if (utils.is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!utils.is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!utils.is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport { providers } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n this.type = input.type;\n this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;\n\n // Check for support\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // Create new markup\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n this.media = utils.createElement('video');\n break;\n\n case 'html5:audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n this.media = utils.createElement('div', {\n src: input.sources[0].src,\n });\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!utils.is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport utils from './utils';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (utils.is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return utils.is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (utils.is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.3.6\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport Console from './console';\nimport controls from './controls';\nimport defaults from './defaults';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport { providers, types } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n captions: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n let params = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (utils.is.element(iframe)) {\n // Detect provider\n url = iframe.getAttribute('src');\n this.provider = utils.getProviderByUrl(url);\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n params = utils.getUrlParams(url);\n if (!utils.is.empty(params)) {\n const truthy = [\n '1',\n 'true',\n ];\n\n if (truthy.includes(params.autoplay)) {\n this.config.autoplay = true;\n }\n if (truthy.includes(params.loop)) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(params.playsinline);\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!utils.is.element(this.elements.container)) {\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n }\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n this.ads = new Ads(this);\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!utils.is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !utils.is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = utils.is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (utils.is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (utils.is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // True duration\n const realDuration = this.media ? Number(this.media.duration) : 0;\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!utils.is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n }\n\n if (!utils.is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!utils.is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n let quality = null;\n\n if (!utils.is.empty(input)) {\n quality = Number(input);\n }\n\n if (!utils.is.number(quality) || quality === 0) {\n quality = this.storage.get('quality');\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.selected;\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.default;\n }\n\n if (!this.options.quality.length) {\n return;\n }\n\n if (!this.options.quality.includes(quality)) {\n const closest = utils.closest(this.options.quality, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);\n quality = closest;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n ui.setPoster.call(this);\n }\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);\n\n // Nothing to change...\n if (this.captions.active === show) {\n return;\n }\n\n // Set global\n this.captions.active = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.active);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n /**\n * Set the captions language\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // If empty string is passed, assume disable captions\n if (utils.is.empty(input)) {\n this.toggleCaptions(false);\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // Check for support\n if (!this.options.captions.includes(language)) {\n this.debug.warn(`Unsupported language option: ${language}`);\n return;\n }\n\n // Ensure captions are enabled\n this.toggleCaptions(true);\n\n // Enabled only\n if (language === 'enabled') {\n return;\n }\n\n // If nothing to change, bail\n if (this.language === language) {\n return;\n }\n\n // Update config\n this.captions.language = language;\n\n // Clear caption\n captions.setText.call(this, null);\n\n // Update captions\n captions.setLanguage.call(this);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n }\n\n /**\n * Get the current captions language\n */\n get language() {\n return this.captions.language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} toggle - Whether to show the controls\n */\n toggleControls(toggle) {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Don't hide if no UI support or it's audio\n if (!this.supported.ui || this.isAudio) {\n return;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n\n // Get toggle state if not set\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Events that show the controls\n const showEvents = [\n 'touchstart',\n 'touchmove',\n 'mouseenter',\n 'mousemove',\n 'focusin',\n ];\n\n // Events that delay hiding\n const delayEvents = [\n 'touchmove',\n 'touchend',\n 'mousemove',\n ];\n\n // Whether to show controls\n show = showEvents.includes(toggle.type);\n\n // Delay hiding on move events\n if (delayEvents.includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (!this.touch && toggle.type === 'focusin') {\n delay = 3000;\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer on every call\n clearTimeout(this.timers.controls);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.paused || this.loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.paused || this.loading) {\n return;\n }\n\n // Delay for hiding on touch\n if (this.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || this.playing) {\n this.timers.controls = setTimeout(() => {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Restore transition behaviour\n if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) {\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false);\n }\n\n // Set hideControls class\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, this.config.hideControls);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n utils.removeElement(this.elements.buttons.play);\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n this.listeners.clear();\n\n // Replace the container with the original element provided\n utils.replaceElement(this.elements.original, this.elements.container);\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Type specific stuff\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n case 'html5:audio':\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n case 'youtube:video':\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && utils.is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo:video':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return utils.loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (utils.is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (utils.is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (utils.is.array(selector)) {\n targets = selector.filter(i => utils.is.element(i));\n }\n\n if (utils.is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.min.js b/dist/plyr.min.js index 5087641e..0fc2eeb8 100644 --- a/dist/plyr.min.js +++ b/dist/plyr.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var e,t,i=(function(e,t){var i;i=function(){var e=function(){},t={},i={},n={};function s(e,t){if(e){var s=n[e];if(i[e]=t,s)for(;s.length;)s[0](e,t),s.splice(0,1)}}function a(t,i){t.call&&(t={success:t}),i.length?(t.error||e)(i):(t.success||e)(t)}function l(t,i,n,s){var a,r,o=document,c=n.async,u=(n.numRetries||0)+1,d=n.before||e,p=t.replace(/^(css|img)!/,"");s=s||0,/(^css!|\.css$)/.test(t)?(a=!0,(r=o.createElement("link")).rel="stylesheet",r.href=p):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(r=o.createElement("img")).src=p:((r=o.createElement("script")).src=t,r.async=void 0===c||c),r.onload=r.onerror=r.onbeforeload=function(e){var o=e.type[0];if(a&&"hideFocus"in r)try{r.sheet.cssText.length||(o="e")}catch(e){o="e"}if("e"==o&&(s+=1)<u)return l(t,i,n,s);i(t,o,e.defaultPrevented)},!1!==d(t,r)&&o.head.appendChild(r)}function r(e,i,n){var r,o;if(i&&i.trim&&(r=i),o=(r?n:i)||{},r){if(r in t)throw"LoadJS";t[r]=!0}!function(e,t,i){var n,s,a=(e=e.push?e:[e]).length,r=a,o=[];for(n=function(e,i,n){if("e"==i&&o.push(e),"b"==i){if(!n)return;o.push(e)}--a||t(o)},s=0;s<r;s++)l(e[s],n,i)}(e,function(e){a(o,e),s(r,e)},o)}return r.ready=function(e,t){return function(e,t){var s,a,l,r=[],o=(e=e.push?e:[e]).length,c=o;for(s=function(e,i){i.length&&r.push(e),--c||t(r)};o--;)a=e[o],(l=i[a])?s(a,l):(n[a]=n[a]||[]).push(s)}(e,function(e){a(t,e)}),r},r.done=function(e){s(e,[])},r.reset=function(){t={},i={},n={}},r.isDefined=function(e){return e in t},r},e.exports=i()}(e={exports:{}},e.exports),e.exports),n={html5:"html5",youtube:"youtube",vimeo:"vimeo"},s={audio:"audio",video:"video"},a=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},l=function(){function e(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,i,n){return i&&e(t.prototype,i),n&&e(t,n),t}}(),r=function(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e},o=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var i=[],n=!0,s=!1,a=void 0;try{for(var l,r=e[Symbol.iterator]();!(n=(l=r.next()).done)&&(i.push(l.value),!t||i.length!==t);n=!0);}catch(e){s=!0,a=e}finally{try{!n&&r.return&&r.return()}finally{if(s)throw a}}return i}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),c={is:{plyr:function(e){return this.instanceof(e,window.Plyr)},object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.nullOrUndefined(e)&&Array.isArray(e)},weakMap:function(e){return this.instanceof(e,window.WeakMap)},nodeList:function(e){return this.instanceof(e,window.NodeList)},element:function(e){return this.instanceof(e,window.Element)},textNode:function(e){return this.getConstructor(e)===Text},event:function(e){return this.instanceof(e,window.Event)},cue:function(e){return this.instanceof(e,window.TextTrackCue)||this.instanceof(e,window.VTTCue)},track:function(e){return this.instanceof(e,TextTrack)||!this.nullOrUndefined(e)&&this.string(e.kind)},url:function(e){return!this.nullOrUndefined(e)&&/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(e)},nullOrUndefined:function(e){return null===e||void 0===e},empty:function(e){return this.nullOrUndefined(e)||(this.string(e)||this.array(e)||this.nodeList(e))&&!e.length||this.object(e)&&!Object.keys(e).length},instanceof:function(e,t){return Boolean(e&&t&&e instanceof t)},getConstructor:function(e){return this.nullOrUndefined(e)?null:e.constructor}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},fetch:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(i,n){try{var s=new XMLHttpRequest;if(!("withCredentials"in s))return;s.addEventListener("load",function(){if("text"===t)try{i(JSON.parse(s.responseText))}catch(e){i(s.responseText)}else i(s.response)}),s.addEventListener("error",function(){throw new Error(s.statusText)}),s.open("GET",e,!0),s.responseType=t,s.send()}catch(e){n(e)}})},loadScript:function(e){return new Promise(function(t,n){i(e,{success:t,error:n})})},loadSprite:function(e,t){if(c.is.string(e)){var i=c.is.string(t),n=function(){return document.querySelectorAll("#"+t).length};if(!i||!n()){var s=document.createElement("div");if(c.toggleHidden(s,!0),i&&s.setAttribute("id",t),u.storage){var a=window.localStorage.getItem("cache-"+t);if(null!==a){var l=JSON.parse(a);return void r.call(s,l.content)}}c.fetch(e).then(function(e){c.is.empty(e)||(u.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:e})),r.call(s,e))}).catch(function(){})}}function r(e){i&&n()||(this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0]))}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},createElement:function(e,t,i){var n=document.createElement(e);return c.is.object(t)&&c.setAttributes(n,t),c.is.string(i)&&(n.textContent=i),n},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},insertElement:function(e,t,i,n){t.appendChild(c.createElement(e,i,n))},removeElement:function(e){c.is.nodeList(e)||c.is.array(e)?Array.from(e).forEach(c.removeElement):c.is.element(e)&&c.is.element(e.parentNode)&&e.parentNode.removeChild(e)},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},replaceElement:function(e,t){return c.is.element(t)&&c.is.element(t.parentNode)&&c.is.element(e)?(t.parentNode.replaceChild(e,t),e):null},setAttributes:function(e,t){c.is.element(e)&&!c.is.empty(t)&&Object.entries(t).forEach(function(t){var i=o(t,2),n=i[0],s=i[1];e.setAttribute(n,s)})},getAttributesFromSelector:function(e,t){if(!c.is.string(e)||c.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),s=t.replace(".",""),a=t.replace(/[[\]]/g,"").split("="),l=a[0],r=a.length>1?a[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":c.is.object(n)&&c.is.string(n.class)&&(n.class+=" "+s),i.class=s;break;case"#":i.id=t.replace("#","");break;case"[":i[l]=r}}),i},toggleHidden:function(e,t){if(c.is.element(e)){var i=t;c.is.boolean(i)||(i=!e.hasAttribute("hidden")),i?e.setAttribute("hidden",""):e.removeAttribute("hidden")}},toggleClass:function(e,t,i){if(c.is.element(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return c.is.element(e)&&e.classList.contains(t)},matches:function(e,t){var i={Element:Element};var n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(c.is.element(e)){var i=c.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),n=i[0],s=i[i.length-1],a=function(e){if("Tab"===e.key&&9===e.keyCode){var t=c.getFocusElement();t!==s||e.shiftKey?t===n&&e.shiftKey&&(s.focus(),e.preventDefault()):(n.focus(),e.preventDefault())}};t?c.on(this.elements.container,"keydown",a,!1):c.off(this.elements.container,"keydown",a,!1)}},toggleListener:function(e,t,i){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],a=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(!c.is.empty(e)&&!c.is.empty(t)&&c.is.function(i))if(c.is.nodeList(e)||c.is.array(e))Array.from(e).forEach(function(e){e instanceof Node&&c.toggleListener.call(null,e,t,i,n,s,a)});else{var l=t.split(" "),r=a;u.passiveListeners&&(r={passive:s,capture:a}),l.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,r)})}},on:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments[2],n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];c.toggleListener(e,t,i,!0,n,s)},off:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments[2],n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];c.toggleListener(e,t,i,!1,n,s)},dispatchEvent:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(c.is.element(e)&&!c.is.empty(t)){var s=new CustomEvent(t,{bubbles:i,detail:Object.assign({},n,{plyr:c.is.plyr(this)?this:null})});e.dispatchEvent(s)}},toggleState:function(e,t){if(c.is.array(e)||c.is.nodeList(e))Array.from(e).forEach(function(e){return c.toggleState(e,t)});else if(c.is.element(e)){var i="true"===e.getAttribute("aria-pressed"),n=c.is.boolean(t)?t:!i;e.setAttribute("aria-pressed",n)}},format:function(e){for(var t=arguments.length,i=Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];return c.is.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return c.is.string(i[t])?i[t]:""})},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},getHours:function(e){return parseInt(e/60/60%60,10)},getMinutes:function(e){return parseInt(e/60%60,10)},getSeconds:function(e){return parseInt(e%60,10)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!c.is.number(e))return this.formatTime(null,t,i);var n=function(e){return("0"+e).slice(-2)},s=this.getHours(e),a=this.getMinutes(e),l=this.getSeconds(e);return t||s>0?s+=":":s="",(i?"-":"")+s+n(a)+":"+n(l)},replaceAll:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g,"\\$1"),"g"),i.toString())},toTitleCase:function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})},toPascalCase:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=c.replaceAll(e,"-"," "),e=c.replaceAll(e,"_"," "),e=c.toTitleCase(e),c.replaceAll(e," ","")},toCamelCase:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=c.toPascalCase(e)).charAt(0).toLowerCase()+e.slice(1)},extend:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,i=Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];if(!i.length)return e;var s=i.shift();return c.is.object(s)?(Object.keys(s).forEach(function(t){c.is.object(s[t])?(Object.keys(e).includes(t)||Object.assign(e,r({},t,{})),c.extend(e[t],s[t])):Object.assign(e,r({},t,s[t]))}),c.extend.apply(c,[e].concat(function(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}(i)))):e},dedupe:function(e){return c.is.array(e)?e.filter(function(t,i){return e.indexOf(t)===i}):e},closest:function(e,t){return c.is.array(e)&&e.length?e.reduce(function(e,i){return Math.abs(i-t)<Math.abs(e-t)?i:e}):null},getProviderByUrl:function(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/.test(e)?n.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?n.vimeo:null},parseYouTubeId:function(e){if(c.is.empty(e))return null;return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:e},parseVimeoId:function(e){if(c.is.empty(e))return null;if(c.is.number(Number(e)))return e;return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e},parseUrl:function(e){var t=document.createElement("a");return t.href=e,t},getUrlParams:function(e){var t=e;(e.startsWith("http://")||e.startsWith("https://"))&&(t=this.parseUrl(e).search);return this.is.empty(t)?null:t.slice(t.indexOf("?")+1).split("&").reduce(function(e,t){var i=t.split("="),n=o(i,2),s=n[0],a=n[1];return Object.assign(e,r({},s,decodeURIComponent(a)))},{})},buildUrlParams:function(e){return c.is.object(e)?Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&"):""},stripHTML:function(e){var t=document.createDocumentFragment(),i=document.createElement("div");return t.appendChild(i),i.innerHTML=e,t.firstChild.innerText},getAspectRatio:function(e,t){var i=function e(t,i){return 0===i?t:e(i,t%i)}(e,t);return e/i+":"+t/i},get transitionEndEvent(){var e=document.createElement("span"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},i=Object.keys(t).find(function(t){return void 0!==e.style[t]});return!!c.is.string(i)&&t[i]},repaint:function(e){setTimeout(function(){c.toggleHidden(e,!0),e.offsetHeight,c.toggleHidden(e,!1)},0)}},u={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,i){var n=!1,s=!1,a=c.getBrowser(),l=a.isIPhone&&i&&u.playsinline;switch(t+":"+e){case"html5:video":s=(n=u.video)&&u.rangeInput&&(!a.isIPhone||l);break;case"html5:audio":s=(n=u.audio)&&u.rangeInput;break;case"youtube:video":case"vimeo:video":n=!0,s=u.rangeInput&&(!a.isIPhone||l);break;default:s=(n=u.audio&&u.video)&&u.rangeInput}return{api:n,ui:s}},pip:!c.getBrowser().isIPhone&&c.is.function(c.createElement("video").webkitSetPresentationMode),airplay:c.is.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){var t=this.media;try{if(!this.isHTML5||!c.is.function(t.canPlayType))return!1;if(e.includes("codecs="))return t.canPlayType(e).replace(/no/,"");if(this.isVideo)switch(e){case"video/webm":return t.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,"");case"video/mp4":return t.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,"");case"video/ogg":return t.canPlayType('video/ogg; codecs="theora"').replace(/no/,"");default:return!1}else if(this.isAudio)switch(e){case"audio/mpeg":return t.canPlayType("audio/mpeg;").replace(/no/,"");case"audio/ogg":return t.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,"");case"audio/wav":return t.canPlayType('audio/wav; codecs="1"').replace(/no/,"");default:return!1}}catch(e){return!1}return!1},textTracks:"textTracks"in document.createElement("video"),passiveListeners:function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t)}catch(e){}return e}(),rangeInput:(t=document.createElement("input"),t.type="range","range"===t.type),touch:"ontouchstart"in document.documentElement,transitions:!1!==c.transitionEndEvent,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},d={getSources:function(){return this.isHTML5?this.media.querySelectorAll("source"):null},getQualityOptions:function(){if(!this.isHTML5)return null;var e=d.getSources.call(this);if(c.is.empty(e))return null;var t=Array.from(e).filter(function(e){return!c.is.empty(e.getAttribute("size"))});return c.is.empty(t)?null:c.dedupe(t.map(function(e){return Number(e.getAttribute("size"))}))},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=d.getSources.call(e);if(c.is.empty(t))return null;var i=Array.from(t).filter(function(t){return t.getAttribute("src")===e.source});return c.is.empty(i)?null:Number(i[0].getAttribute("size"))},set:function(t){var i=d.getSources.call(e);if(!c.is.empty(i)){var n=Array.from(i).filter(function(e){return Number(e.getAttribute("size"))===t});if(!c.is.empty(n)){var s=n.filter(function(t){return u.mime.call(e,t.getAttribute("type"))});if(!c.is.empty(s)){c.dispatchEvent.call(e,e.media,"qualityrequested",!1,{quality:t});var a=e.currentTime,l=e.playing;e.media.src=s[0].getAttribute("src"),e.media.load(),l&&e.play(),e.currentTime=a,c.dispatchEvent.call(e,e.media,"qualitychange",!1,{quality:t})}}}}})}},cancelRequests:function(){this.isHTML5&&(c.removeElement(d.getSources()),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}},p=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(c.is.empty(e)||c.is.empty(t)||!Object.keys(t.i18n).includes(e))return"";var i=t.i18n[e],n={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(n).forEach(function(e){var t=o(e,2),n=t[0],s=t[1];i=c.replaceAll(i,n,s)}),i},h=c.getBrowser(),m={addStyleHook:function(){c.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),c.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for "+this.provider+" "+this.type),void m.toggleNativeControls.call(this,!0);c.is.element(this.elements.controls)||(f.inject.call(this),this.listeners.controls()),m.toggleNativeControls.call(this),y.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,m.updateVolume.call(this),m.timeUpdate.call(this),m.checkPlaying.call(this),c.toggleClass(this.elements.container,this.config.classNames.pip.supported,u.pip&&this.isHTML5&&this.isVideo),c.toggleClass(this.elements.container,this.config.classNames.airplay.supported,u.airplay&&this.isHTML5),c.toggleClass(this.elements.container,this.config.classNames.isIos,h.isIos),c.toggleClass(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){c.dispatchEvent.call(e,e.media,"ready")},0),m.setTitle.call(this),m.setPoster.call(this)},setTitle:function(){var e=p("play",this.config);if(c.is.string(this.config.title)&&!c.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),c.is.nodeList(this.elements.buttons.play)&&Array.from(this.elements.buttons.play).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=c.getElement.call(this,"iframe");if(!c.is.element(t))return;var i=c.is.empty(this.config.title)?"video":this.config.title,n=p("frameTitle",this.config);t.setAttribute("title",n.replace("{title}",i))}},setPoster:function(){if(c.is.element(this.elements.poster)&&!c.is.empty(this.poster)){var e=this.poster.split(",");this.elements.poster.style.backgroundImage=e.map(function(e){return"url('"+e+"')"}).join(",")}},checkPlaying:function(e){c.toggleClass(this.elements.container,this.config.classNames.playing,this.playing),c.toggleClass(this.elements.container,this.config.classNames.paused,this.paused),c.toggleClass(this.elements.container,this.config.classNames.stopped,this.stopped),c.toggleState(this.elements.buttons.play,this.playing),c.is.event(e)&&"timeupdate"===e.type||this.toggleControls(!this.playing)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){c.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},checkFailed:function(){var e=this;this.failed=3===this.media.networkState,this.failed&&(c.toggleClass(this.elements.container,this.config.classNames.loading,!1),c.toggleClass(this.elements.container,this.config.classNames.error,!0)),clearTimeout(this.timers.failed),this.timers.loading=setTimeout(function(){c.toggleClass(e.elements.container,e.config.classNames.loading,e.loading),e.toggleControls(e.loading)},this.loading?250:0)},updateVolume:function(){this.supported.ui&&(c.is.element(this.elements.inputs.volume)&&m.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),c.is.element(this.elements.buttons.mute)&&c.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;c.is.element(e)&&(e.value=t,f.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=c.is.number(t)?t:0,n=c.is.element(e)?e:this.elements.display.buffer;if(c.is.element(n)){n.value=i;var s=n.getElementsByTagName("span")[0];c.is.element(s)&&(s.childNodes[0].nodeValue=i)}},updateProgress:function(e){if(this.supported.ui&&c.is.event(e)){var t=0;if(e)switch(e.type){case"timeupdate":case"seeking":t=c.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&m.setRange.call(this,this.elements.inputs.seek,t);break;case"playing":case"progress":m.setProgress.call(this,this.elements.display.buffer,100*this.buffered)}}},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(c.is.element(e)&&c.is.number(t)){var n=c.getHours(this.duration)>0;e.textContent=c.formatTime(t,n,i)}},timeUpdate:function(e){var t=!c.is.element(this.elements.display.duration)&&this.config.invertTime;m.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||m.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui){var e=c.is.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&m.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&m.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),f.updateSeekTooltip.call(this)}}},g=c.getBrowser(),f={updateRangeFill:function(e){var t=c.is.event(e)?e.target:e;c.is.element(t)&&"range"===t.getAttribute("type")&&(t.setAttribute("aria-valuenow",t.value),g.isWebkit&&t.style.setProperty("--value",t.value/t.max*100+"%"))},getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||g.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=c.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:c.getElements.call(this,this.config.selectors.buttons.play),pause:c.getElement.call(this,this.config.selectors.buttons.pause),restart:c.getElement.call(this,this.config.selectors.buttons.restart),rewind:c.getElement.call(this,this.config.selectors.buttons.rewind),fastForward:c.getElement.call(this,this.config.selectors.buttons.fastForward),mute:c.getElement.call(this,this.config.selectors.buttons.mute),pip:c.getElement.call(this,this.config.selectors.buttons.pip),airplay:c.getElement.call(this,this.config.selectors.buttons.airplay),settings:c.getElement.call(this,this.config.selectors.buttons.settings),captions:c.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:c.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=c.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:c.getElement.call(this,this.config.selectors.inputs.seek),volume:c.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:c.getElement.call(this,this.config.selectors.display.buffer),currentTime:c.getElement.call(this,this.config.selectors.display.currentTime),duration:c.getElement.call(this,this.config.selectors.display.duration)},c.is.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var i=f.getIconUrl.call(this),n=(i.cors?"":i.url)+"#"+this.config.iconPrefix,s=document.createElementNS("http://www.w3.org/2000/svg","svg");c.setAttributes(s,c.extend(t,{role:"presentation",focusable:"false"}));var a=document.createElementNS("http://www.w3.org/2000/svg","use"),l=n+"-"+e;return"href"in a?a.setAttributeNS("http://www.w3.org/1999/xlink","href",l):a.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",l),s.appendChild(a),s},createLabel:function(e,t){var i=p(e,this.config),n=Object.assign({},t);switch(e){case"pip":i="PIP";break;case"airplay":i="AirPlay"}return"class"in n?n.class+=" "+this.config.classNames.hidden:n.class=this.config.classNames.hidden,c.createElement("span",n,i)},createBadge:function(e){if(c.is.empty(e))return null;var t=c.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(c.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=c.createElement("button"),n=Object.assign({},t),s=c.toCamelCase(e),a=!1,l=void 0,r=void 0,o=void 0,u=void 0;switch("type"in n||(n.type="button"),"class"in n?n.class.includes(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,e){case"play":a=!0,l="play",o="pause",r="play",u="pause";break;case"mute":a=!0,l="mute",o="unmute",r="volume",u="muted";break;case"captions":a=!0,l="enableCaptions",o="disableCaptions",r="captions-off",u="captions-on";break;case"fullscreen":a=!0,l="enterFullscreen",o="exitFullscreen",r="enter-fullscreen",u="exit-fullscreen";break;case"play-large":n.class+=" "+this.config.classNames.control+"--overlaid",s="play",l="play",r="play";break;default:l=s,r=e}return a?(i.appendChild(f.createIcon.call(this,u,{class:"icon--pressed"})),i.appendChild(f.createIcon.call(this,r,{class:"icon--not-pressed"})),i.appendChild(f.createLabel.call(this,o,{class:"label--pressed"})),i.appendChild(f.createLabel.call(this,l,{class:"label--not-pressed"})),n["aria-pressed"]=!1):(i.appendChild(f.createIcon.call(this,r)),i.appendChild(f.createLabel.call(this,l))),c.extend(n,c.getAttributesFromSelector(this.config.selectors.buttons[s],n)),c.setAttributes(i,n),"play"===s?(c.is.array(this.elements.buttons[s])||(this.elements.buttons[s]=[]),this.elements.buttons[s].push(i)):this.elements.buttons[s]=i,i},createRange:function(e,t){var i=c.createElement("label",{for:t.id,id:t.id+"-label",class:this.config.classNames.hidden},p(e,this.config)),n=c.createElement("input",c.extend(c.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-labelledby":t.id+"-label","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=n,f.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=c.createElement("progress",c.extend(c.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){i.appendChild(c.createElement("span",null,"0"));var n="";switch(e){case"played":n=p("played",this.config);break;case"buffer":n=p("buffered",this.config)}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=c.getAttributesFromSelector(this.config.selectors.display[e]),i=c.createElement("div",c.extend(t,{class:"plyr__time "+t.class,"aria-label":p(e,this.config)}),"00:00");return this.elements.display[e]=i,i},createMenuItem:function(e,t,i,n){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,a=arguments.length>5&&void 0!==arguments[5]&&arguments[5],l=c.createElement("li"),r=c.createElement("label",{class:this.config.classNames.control}),o=c.createElement("input",c.extend(c.getAttributesFromSelector(this.config.selectors.inputs[i]),{type:"radio",name:"plyr-"+i,value:e,checked:a,class:"plyr__sr-only"})),u=c.createElement("span",{hidden:""});r.appendChild(o),r.appendChild(u),r.insertAdjacentHTML("beforeend",n),c.is.element(s)&&r.appendChild(s),l.appendChild(r),t.appendChild(l)},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&c.is.element(this.elements.inputs.seek)&&c.is.element(this.elements.display.seekTooltip)&&0!==this.duration){var i=0,n=this.elements.inputs.seek.getBoundingClientRect(),s=this.config.classNames.tooltip+"--visible",a=function(e){c.toggleClass(t.elements.display.seekTooltip,s,e)};if(this.touch)a(!1);else{if(c.is.event(e))i=100/n.width*(e.pageX-n.left);else{if(!c.hasClass(this.elements.display.seekTooltip,s))return;i=parseFloat(this.elements.display.seekTooltip.style.left,10)}i<0?i=0:i>100&&(i=100),m.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*i),this.elements.display.seekTooltip.style.left=i+"%",c.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&a("mouseenter"===e.type)}}},toggleTab:function(e,t){c.toggleHidden(this.elements.settings.tabs[e],!t)},setQualityMenu:function(e){var t=this;if(c.is.element(this.elements.settings.panes.quality)){var i=this.elements.settings.panes.quality.querySelector("ul");c.is.array(e)&&(this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}));var n=!c.is.empty(this.options.quality)&&this.options.quality.length>1;if(f.toggleTab.call(this,"quality",n),f.checkMenu.call(this),n){c.emptyElement(i);this.options.quality.sort(function(e,i){var n=t.config.quality.options;return n.indexOf(e)>n.indexOf(i)?1:-1}).forEach(function(e){var n=f.getLabel.call(t,"quality",e);f.createMenuItem.call(t,e,i,"quality",n,function(e){var i="";switch(e){case 2160:i="4K";break;case 1440:case 1080:case 720:i="HD";break;case 576:case 480:i="SD"}return i.length?f.createBadge.call(t,i):null}(e))}),f.updateSetting.call(this,"quality",i)}}},getLabel:function(e,t){switch(e){case"speed":return 1===t?p("normal",this.config):t+"×";case"quality":return c.is.number(t)?t+"p":c.toTitleCase(t);case"captions":return y.getLabel.call(this);default:return null}},updateSetting:function(e,t,i){var n=this.elements.settings.panes[e],s=null,a=t;switch(e){case"captions":s=this.captions.active?this.options.captions.length>2||!this.options.captions.some(function(e){return"enabled"===e})?this.captions.language:"enabled":"";break;default:if(s=c.is.empty(i)?this[e]:i,c.is.empty(s)&&(s=this.config[e].default),!c.is.empty(this.options[e])&&!this.options[e].includes(s))return void this.debug.warn("Unsupported value of '"+s+"' for "+e);if(!this.config[e].options.includes(s))return void this.debug.warn("Disabled value of '"+s+"' for "+e)}if(c.is.element(a)||(a=n&&n.querySelector("ul")),c.is.element(a)){this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=f.getLabel.call(this,e,s);var l=a&&a.querySelector('input[value="'+s+'"]');c.is.element(l)&&(l.checked=!0)}},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=y.getTracks.call(this).length;if(f.toggleTab.call(this,"captions",i),c.emptyElement(t),f.checkMenu.call(this),i){var n=y.getTracks.call(this).map(function(t){return{language:c.is.empty(t.language)?"enabled":t.language,label:y.getLabel.call(e,t)}});n.unshift({language:"",label:p("disabled",this.config)}),n.forEach(function(i){f.createMenuItem.call(e,i.language,t,"language",i.label,"enabled"!==i.language?f.createBadge.call(e,i.language.toUpperCase()):null,i.language.toLowerCase()===e.captions.language.toLowerCase())}),this.options.captions=n.map(function(e){return e.language}),f.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;if(this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&c.is.element(this.elements.settings.panes.speed)){c.is.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var i=!c.is.empty(this.options.speed)&&this.options.speed.length>1;if(f.toggleTab.call(this,"speed",i),f.checkMenu.call(this),i){var n=this.elements.settings.panes.speed.querySelector("ul");c.emptyElement(n),this.options.speed.forEach(function(e){var i=f.getLabel.call(t,"speed",e);f.createMenuItem.call(t,e,n,"speed",i)}),f.updateSetting.call(this,"speed",n)}}},checkMenu:function(){var e=this.elements.settings.tabs,t=!c.is.empty(e)&&Object.values(e).some(function(e){return!e.hidden});c.toggleHidden(this.elements.settings.menu,!t)},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings;if(c.is.element(t)&&c.is.element(i)){var n=c.is.boolean(e)?e:c.is.element(t)&&t.hasAttribute("hidden");if(c.is.event(e)){var s=c.is.element(t)&&t.contains(e.target),a=e.target===this.elements.buttons.settings;if(s||!s&&!a&&n)return;a&&e.stopPropagation()}c.is.element(i)&&i.setAttribute("aria-expanded",n),c.is.element(t)&&(c.toggleHidden(t,!n),c.toggleClass(this.elements.container,this.config.classNames.menu.open,n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))}},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return c.removeElement(t),{width:i,height:n}},showTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=this.elements.settings.menu,i=document.getElementById(e);if(c.is.element(i)&&"tabpanel"===i.getAttribute("role")){var n=t.querySelector('[role="tabpanel"]:not([hidden])'),s=n.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+n.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),u.transitions&&!u.reducedMotion){s.style.width=n.scrollWidth+"px",s.style.height=n.scrollHeight+"px";var a=f.getTabSize.call(this,i);c.on(s,c.transitionEndEvent,function e(t){t.target===s&&["width","height"].includes(t.propertyName)&&(s.style.width="",s.style.height="",c.off(s,c.transitionEndEvent,e))}),s.style.width=a.width+"px",s.style.height=a.height+"px"}c.toggleHidden(n,!0),n.setAttribute("tabindex",-1),c.toggleHidden(i,!1);var l=c.getElements.call(this,'[aria-controls="'+e+'"]');Array.from(l).forEach(function(e){e.setAttribute("aria-expanded",!0)}),i.removeAttribute("tabindex"),i.querySelectorAll("button:not(:disabled), input:not(:disabled), [tabindex]")[0].focus()}},create:function(e){var t=this;if(c.is.empty(this.config.controls))return null;var i=c.createElement("div",c.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(f.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(f.createButton.call(this,"rewind")),this.config.controls.includes("play")&&i.appendChild(f.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&i.appendChild(f.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=c.createElement("div",c.getAttributesFromSelector(this.config.selectors.progress)),s=f.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(s.label),n.appendChild(s.input),n.appendChild(f.createProgress.call(this,"buffer")),this.config.tooltips.seek){var a=c.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(a),this.elements.display.seekTooltip=a}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(f.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(f.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(f.createButton.call(this,"mute")),this.config.controls.includes("volume")){var l=c.createElement("div",{class:"plyr__volume"}),r={max:1,step:.05,value:this.config.volume},o=f.createRange.call(this,"volume",c.extend(r,{id:"plyr-volume-"+e.id}));l.appendChild(o.label),l.appendChild(o.input),this.elements.volume=l,i.appendChild(l)}if(this.config.controls.includes("captions")&&i.appendChild(f.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!c.is.empty(this.config.settings)){var h=c.createElement("div",{class:"plyr__menu",hidden:""});h.appendChild(f.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var m=c.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,hidden:"","aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),g=c.createElement("div"),y=c.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),v=c.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=c.createElement("li",{role:"tab",hidden:""}),s=c.createElement("button",c.extend(c.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),p(i,t.config)),a=c.createElement("span",{class:t.config.classNames.menu.value});a.innerHTML=e[i],s.appendChild(a),n.appendChild(s),v.appendChild(n),t.elements.settings.tabs[i]=n}),y.appendChild(v),g.appendChild(y),this.config.settings.forEach(function(i){var n=c.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,hidden:"","aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1}),s=c.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},p(i,t.config));n.appendChild(s);var a=c.createElement("ul");n.appendChild(a),g.appendChild(n),t.elements.settings.panes[i]=n}),m.appendChild(g),h.appendChild(m),i.appendChild(h),this.elements.settings.form=m,this.elements.settings.menu=h}return this.config.controls.includes("pip")&&u.pip&&i.appendChild(f.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&u.airplay&&i.appendChild(f.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(f.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(f.createButton.call(this,"play-large")),this.elements.controls=i,this.isHTML5&&f.setQualityMenu.call(this,d.getQualityOptions.call(this)),f.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=f.getIconUrl.call(this);t.cors&&c.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;this.elements.controls=null;var n={id:this.id,seektime:this.config.seekTime,title:this.config.title},s=!0;c.is.string(this.config.controls)||c.is.element(this.config.controls)?i=this.config.controls:c.is.function(this.config.controls)?i=this.config.controls.call(this,n):(i=f.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:y.getLabel.call(this)}),s=!1);var a=function(e){var t=e;return Object.entries(n).forEach(function(e){var i=o(e,2),n=i[0],s=i[1];t=c.replaceAll(t,"{"+n+"}",s)}),t};s&&(c.is.string(this.config.controls)?i=a(i):c.is.element(i)&&(i.innerHTML=a(i.innerHTML)));var l=void 0;if(c.is.string(this.config.selectors.controls.container)&&(l=document.querySelector(this.config.selectors.controls.container)),c.is.element(l)||(l=this.elements.container),c.is.element(i)?l.appendChild(i):i&&l.insertAdjacentHTML("beforeend",i),c.is.element(this.elements.controls)||f.findElements.call(this),window.navigator.userAgent.includes("Edge")&&c.repaint(l),this.config.tooltips.controls){var r=c.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(r).forEach(function(t){c.toggleClass(t,e.config.classNames.hidden,!1),c.toggleClass(t,e.config.classNames.tooltip,!0),t.setAttribute("role","tooltip")})}}},y={setup:function(){if(this.supported.ui){var e=this.storage.get("language");if(c.is.empty(e)||(this.captions.language=e),c.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()),!c.is.boolean(this.captions.active)){var t=this.storage.get("captions");c.is.boolean(t)?this.captions.active=t:this.captions.active=this.config.captions.active}if(!this.isVideo||this.isYouTube||this.isHTML5&&!u.textTracks)c.is.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&f.setCaptionsMenu.call(this);else{c.is.element(this.elements.captions)||(this.elements.captions=c.createElement("div",c.getAttributesFromSelector(this.config.selectors.captions)),c.insertAfter(this.elements.captions,this.elements.wrapper)),c.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!c.is.empty(y.getTracks.call(this)));var i=y.getTracks.call(this);if(!c.is.empty(i)){if(c.getBrowser().isIE&&window.URL){var n=this.media.querySelectorAll("track");Array.from(n).forEach(function(e){var t=e.getAttribute("src"),i=c.parseUrl(t);i.hostname!==window.location.href.hostname&&["http:","https:"].includes(i.protocol)&&c.fetch(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){c.removeElement(e)})})}y.setLanguage.call(this),y.show.call(this),c.is.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&f.setCaptionsMenu.call(this)}}}},setLanguage:function(){var e=this;if(this.isHTML5&&this.isVideo){y.getTracks.call(this).forEach(function(t){c.on(t,"cuechange",function(t){return y.setCue.call(e,t)}),t.mode="hidden"});var t=y.getCurrentTrack.call(this);c.is.track(t)&&Array.from(t.activeCues||[]).length&&y.setCue.call(this,t)}else this.isVimeo&&this.captions.active&&this.embed.enableTextTrack(this.language)},getTracks:function(){return c.is.nullOrUndefined(this.media)?[]:Array.from(this.media.textTracks||[]).filter(function(e){return["captions","subtitles"].includes(e.kind)})},getCurrentTrack:function(){var e=this,t=y.getTracks.call(this);if(!t.length)return null;var i=t.find(function(t){return t.language.toLowerCase()===e.language});(i||(i=c.getElement.call(this,"track[default]")),i)||(i=o(t,1)[0]);return i},getLabel:function(e){var t=e;return!c.is.track(t)&&u.textTracks&&this.captions.active&&(t=y.getCurrentTrack.call(this)),c.is.track(t)?c.is.empty(t.label)?c.is.empty(t.language)?p("enabled",this.config):e.language.toUpperCase():t.label:p("disabled",this.config)},setCue:function(e){var t=c.is.event(e)?e.target:e,i=t.activeCues,n=i.length&&i[0];t===y.getCurrentTrack.call(this)&&(c.is.cue(n)?y.setText.call(this,n.getCueAsHTML()):y.setText.call(this,null),c.dispatchEvent.call(this,this.media,"cuechange"))},setText:function(e){if(this.supported.ui)if(c.is.element(this.elements.captions)){var t=c.createElement("span");c.emptyElement(this.elements.captions);var i=c.is.nullOrUndefined(e)?"":e;c.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.debug.warn("No captions element to render to")},show:function(){var e=this.storage.get("captions");c.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(c.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),c.toggleState(this.elements.buttons.captions,!0))}},v=function(){},b=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];a(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return l(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):v}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):v}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):v}}]),e}(),k={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.3.6/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240,"default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:(navigator.language||navigator.userLanguage).split("-")[0]},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad"},urls:{vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet",poster:"https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",ads:"plyr__ads",control:"plyr__control",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",error:"plyr--has-error",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:""}},w=c.getBrowser();function E(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;c.is.element(e)&&c.toggleState(e,this.active),c.dispatchEvent(this.target,this.active?"enterfullscreen":"exitfullscreen",!0),w.isIos||c.trapFocus.call(this.player,this.target,this.active)}}function T(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];e?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=e?"hidden":"",c.toggleClass(this.target,this.player.config.classNames.fullscreen.fallback,e),E.call(this)}var A=function(){function e(t){var i=this;a(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},c.on(document,"ms"===this.prefix?"MSFullscreenChange":this.prefix+"fullscreenchange",function(){E.call(i)}),c.on(this.player.elements.container,"dblclick",function(e){c.is.element(i.player.elements.controls)&&i.player.elements.controls.contains(e.target)||i.toggle()}),this.update()}return l(e,[{key:"update",value:function(){this.enabled?this.player.debug.log((e.native?"Native":"Fallback")+" fullscreen enabled"):this.player.debug.log("Fullscreen not supported and fallback disabled"),c.toggleClass(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(w.isIos&&this.player.config.fullscreen.iosNative?this.player.playing&&this.target.webkitEnterFullscreen():e.native?this.prefix?c.is.empty(this.prefix)||this.target[this.prefix+"Request"+this.property]():this.target.requestFullscreen():T.call(this,!0))}},{key:"exit",value:function(){if(this.enabled)if(w.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(e.native)if(this.prefix){if(!c.is.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document[""+this.prefix+t+this.property]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document);else T.call(this,!1)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(e.native?(this.prefix?document[""+this.prefix+this.property+"Element"]:document.fullscreenElement)===this.target:c.hasClass(this.target,this.player.config.classNames.fullscreen.fallback))}},{key:"target",get:function(){return w.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(c.is.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!c.is.function(document[t+"ExitFullscreen"])&&!c.is.function(document[t+"CancelFullScreen"]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}(),C=c.getBrowser(),S=function(){function e(t){a(this,e),this.player=t,this.lastKey=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.firstTouch=this.firstTouch.bind(this)}return l(e,[{key:"handleKey",value:function(e){var t=this,i=e.keyCode?e.keyCode:e.which,n="keydown"===e.type,s=n&&i===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&c.is.number(i)){if(n){var a=c.getFocusElement();if(c.is.element(a)&&c.matches(a,this.player.config.selectors.editable))return;switch([48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67,73,76,79].includes(i)&&(e.preventDefault(),e.stopPropagation()),i){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:s||(t.player.currentTime=t.player.duration/10*(i-48));break;case 32:case 75:s||this.player.togglePlay();break;case 38:this.player.increaseVolume(.1);break;case 40:this.player.decreaseVolume(.1);break;case 77:s||(this.player.muted=!this.player.muted);break;case 39:this.player.forward();break;case 37:this.player.rewind();break;case 70:this.player.fullscreen.toggle();break;case 67:s||this.player.toggleCaptions();break;case 76:this.player.loop=!this.player.loop}!this.player.fullscreen.enabled&&this.player.fullscreen.active&&27===i&&this.player.fullscreen.toggle(),this.lastKey=i}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){f.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){this.player.touch=!0,c.toggleClass(this.player.elements.container,this.player.config.classNames.isTouch,!0),c.off(document.body,"touchstart",this.firstTouch)}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.player.config.keyboard.global&&c.toggleListener(window,"keydown keyup",this.handleKey,e,!1),c.toggleListener(document.body,"click",this.toggleMenu,e),c.on(document.body,"touchstart",this.firstTouch)}},{key:"container",value:function(){var e=this;!this.player.config.keyboard.global&&this.player.config.keyboard.focused&&c.on(this.player.elements.container,"keydown keyup",this.handleKey,!1),c.on(this.player.elements.container,"focusout",function(t){c.toggleClass(t.target,e.player.config.classNames.tabFocus,!1)}),c.on(this.player.elements.container,"keydown",function(t){9===t.keyCode&&setTimeout(function(){c.toggleClass(c.getFocusElement(),e.player.config.classNames.tabFocus,!0)},0)}),this.player.config.hideControls&&c.on(this.player.elements.container,"mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen",function(t){e.player.toggleControls(t)})}},{key:"media",value:function(){var e=this;if(c.on(this.player.media,"timeupdate seeking",function(t){return m.timeUpdate.call(e.player,t)}),c.on(this.player.media,"durationchange loadeddata loadedmetadata",function(t){return m.durationUpdate.call(e.player,t)}),c.on(this.player.media,"loadeddata",function(){c.toggleHidden(e.player.elements.volume,!e.player.hasAudio),c.toggleHidden(e.player.elements.buttons.mute,!e.player.hasAudio)}),c.on(this.player.media,"ended",function(){e.player.isHTML5&&e.player.isVideo&&e.player.config.resetOnEnd&&e.player.restart()}),c.on(this.player.media,"progress playing",function(t){return m.updateProgress.call(e.player,t)}),c.on(this.player.media,"volumechange",function(t){return m.updateVolume.call(e.player,t)}),c.on(this.player.media,"playing play pause ended emptied timeupdate",function(t){return m.checkPlaying.call(e.player,t)}),c.on(this.player.media,"waiting canplay seeked playing",function(t){return m.checkLoading.call(e.player,t)}),c.on(this.player.media,"playing",function(){e.player.ads&&e.player.ads.enabled&&!e.player.ads.initialized&&e.player.ads.managerPromise.then(function(){return e.player.ads.play()}).catch(function(){return e.player.play()})}),this.player.supported.ui&&this.player.config.clickToPlay&&!this.player.isAudio){var t=c.getElement.call(this.player,"."+this.player.config.classNames.video);if(!c.is.element(t))return;c.on(t,"click",function(){e.player.config.hideControls&&e.player.touch&&!e.player.paused||(e.player.paused?e.player.play():e.player.ended?(e.player.restart(),e.player.play()):e.player.pause())})}this.player.supported.ui&&this.player.config.disableContextMenu&&c.on(this.player.elements.wrapper,"contextmenu",function(e){e.preventDefault()},!1),c.on(this.player.media,"volumechange",function(){e.player.storage.set({volume:e.player.volume,muted:e.player.muted})}),c.on(this.player.media,"ratechange",function(){f.updateSetting.call(e.player,"speed"),e.player.storage.set({speed:e.player.speed})}),c.on(this.player.media,"qualityrequested",function(t){e.player.storage.set({quality:t.detail.quality})}),c.on(this.player.media,"qualitychange",function(t){f.updateSetting.call(e.player,"quality",null,t.detail.quality)}),c.on(this.player.media,"languagechange",function(){f.updateSetting.call(e.player,"captions"),e.player.storage.set({language:e.player.language})}),c.on(this.player.media,"captionsenabled captionsdisabled",function(){f.updateSetting.call(e.player,"captions"),e.player.storage.set({captions:e.player.captions.active})}),c.on(this.player.media,this.player.config.events.concat(["keyup","keydown"]).join(" "),function(t){var i={};"error"===t.type&&(i=e.player.media.error),c.dispatchEvent.call(e.player,e.player.elements.container,t.type,!0,i)})}},{key:"controls",value:function(){var e=this,t=C.isIE?"change":"input",i=function(t,i,n){var s=e.player.config.listeners[n],a=!0;c.is.function(s)&&(a=s.call(e.player,t)),a&&c.is.function(i)&&i.call(e.player,t)},n=function(t,n,s,a){var l=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],r=e.player.config.listeners[a],o=c.is.function(r);c.on(t,n,function(e){return i(e,s,a)},l&&!o)};n(this.player.elements.buttons.play,"click",this.player.togglePlay,"play"),n(this.player.elements.buttons.restart,"click",this.player.restart,"restart"),n(this.player.elements.buttons.rewind,"click",this.player.rewind,"rewind"),n(this.player.elements.buttons.fastForward,"click",this.player.forward,"fastForward"),n(this.player.elements.buttons.mute,"click",function(){e.player.muted=!e.player.muted},"mute"),n(this.player.elements.buttons.captions,"click",this.player.toggleCaptions),n(this.player.elements.buttons.fullscreen,"click",function(){e.player.fullscreen.toggle()},"fullscreen"),n(this.player.elements.buttons.pip,"click",function(){e.player.pip="toggle"},"pip"),n(this.player.elements.buttons.airplay,"click",this.player.airplay,"airplay"),n(this.player.elements.buttons.settings,"click",function(t){f.toggleMenu.call(e.player,t)}),n(this.player.elements.settings.form,"click",function(t){t.stopPropagation();var n=function(){var t="plyr-settings-"+e.player.id+"-home";f.showTab.call(e.player,t)};if(c.matches(t.target,e.player.config.selectors.inputs.language))i(t,function(){e.player.language=t.target.value,n()},"language");else if(c.matches(t.target,e.player.config.selectors.inputs.quality))i(t,function(){e.player.quality=t.target.value,n()},"quality");else if(c.matches(t.target,e.player.config.selectors.inputs.speed))i(t,function(){e.player.speed=parseFloat(t.target.value),n()},"speed");else{var s=t.target;f.showTab.call(e.player,s.getAttribute("aria-controls"))}}),n(this.player.elements.inputs.seek,t,function(t){e.player.currentTime=t.target.value/t.target.max*e.player.duration},"seek"),this.player.config.toggleInvert&&!c.is.element(this.player.elements.display.duration)&&n(this.player.elements.display.currentTime,"click",function(){0!==e.player.currentTime&&(e.player.config.invertTime=!e.player.config.invertTime,m.timeUpdate.call(e.player))}),n(this.player.elements.inputs.volume,t,function(t){e.player.volume=t.target.value},"volume"),C.isWebkit&&n(c.getElements.call(this.player,'input[type="range"]'),"input",function(t){f.updateRangeFill.call(e.player,t.target)}),n(this.player.elements.progress,"mouseenter mouseleave mousemove",function(t){return f.updateSeekTooltip.call(e.player,t)}),this.player.config.hideControls&&(n(this.player.elements.controls,"mouseenter mouseleave",function(t){e.player.elements.controls.hover=!e.player.touch&&"mouseenter"===t.type}),n(this.player.elements.controls,"mousedown mouseup touchstart touchend touchcancel",function(t){e.player.elements.controls.pressed=["mousedown","touchstart"].includes(t.type)}),n(this.player.elements.controls,"focusin focusout",function(t){e.player.toggleControls(t)})),n(this.player.elements.inputs.volume,"wheel",function(t){var i=t.webkitDirectionInvertedFromDevice,n=0;(t.deltaY<0||t.deltaX>0)&&(i?(e.player.decreaseVolume(.02),n=-1):(e.player.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.player.increaseVolume(.02),n=1):(e.player.decreaseVolume(.02),n=-1)),(1===n&&e.player.media.volume<1||-1===n&&e.player.media.volume>0)&&t.preventDefault()},"volume",!1)}},{key:"clear",value:function(){this.global(!1)}}]),e}(),N={setup:function(){var e=this;c.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),N.setAspectRatio.call(this),c.is.object(window.Vimeo)?N.ready.call(this):c.loadScript(this.config.urls.vimeo.sdk).then(function(){N.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},setAspectRatio:function(e){var t=c.is.string(e)?e.split(":"):this.config.ratio.split(":"),i=100/t[0]*t[1];if(this.elements.wrapper.style.paddingBottom=i+"%",this.supported.ui){var n=(240-i)/4.8;this.media.style.transform="translateY(-"+n+"%)"}},ready:function(){var e=this,t=this,i={loop:t.config.loop.active,autoplay:t.autoplay,byline:!1,portrait:!1,title:!1,speed:!0,transparent:0,gesture:"media",playsinline:!this.config.fullscreen.iosNative},n=c.buildUrlParams(i),s=t.media.getAttribute("src");c.is.empty(s)&&(s=t.media.getAttribute(t.config.attributes.embed.id));var a=c.parseVimeoId(s),l=c.createElement("iframe"),r=c.format(t.config.urls.vimeo.iframe,a,n);l.setAttribute("src",r),l.setAttribute("allowfullscreen",""),l.setAttribute("allowtransparency",""),l.setAttribute("allow","autoplay");var o=c.createElement("div",{class:t.config.classNames.embedContainer});o.appendChild(l),t.media=c.replaceElement(o,t.media),c.fetch(c.format(t.config.urls.vimeo.api,a),"json").then(function(e){if(!c.is.empty(e)){var i=new URL(e[0].thumbnail_large);i.pathname=i.pathname.split("_")[0]+".jpg",t.media.setAttribute("poster",i.href),m.setPoster.call(t)}}),t.embed=new window.Vimeo.Player(l,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){t.embed.play().then(function(){t.media.paused=!1})},t.media.pause=function(){t.embed.pause().then(function(){t.media.paused=!0})},t.media.stop=function(){t.pause(),t.currentTime=0};var u=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return u},set:function(e){var i=t.media.paused;t.media.seeking=!0,c.dispatchEvent.call(t,t.media,"seeking"),t.embed.setCurrentTime(e).catch(function(){}),i&&t.pause()}});var d=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return d},set:function(e){t.embed.setPlaybackRate(e).then(function(){d=e,c.dispatchEvent.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&f.setSpeedMenu.call(t,[])})}});var p=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return p},set:function(e){t.embed.setVolume(e).then(function(){p=e,c.dispatchEvent.call(t,t.media,"volumechange")})}});var h=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return h},set:function(e){var i=!!c.is.boolean(e)&&e;t.embed.setVolume(i?0:t.config.volume).then(function(){h=i,c.dispatchEvent.call(t,t.media,"volumechange")})}});var g=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return g},set:function(e){var i=c.is.boolean(e)?e:t.config.loop.active;t.embed.setLoop(i).then(function(){g=i})}});var v=void 0;t.embed.getVideoUrl().then(function(e){v=e}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return v}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(t){var i=c.getAspectRatio(t[0],t[1]);N.setAspectRatio.call(e,i)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(i){t.config.title=i,m.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){u=e,c.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,c.dispatchEvent.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,y.setup.call(t)}),t.embed.on("cuechange",function(e){var i=null;e.cues.length&&(i=c.stripHTML(e.cues[0].text)),y.setText.call(t,i)}),t.embed.on("loaded",function(){c.is.element(t.embed.element)&&t.supported.ui&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){t.media.paused&&c.dispatchEvent.call(t,t.media,"play"),t.media.paused=!1,c.dispatchEvent.call(t,t.media,"playing")}),t.embed.on("pause",function(){t.media.paused=!0,c.dispatchEvent.call(t,t.media,"pause")}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,u=e.seconds,c.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,c.dispatchEvent.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&c.dispatchEvent.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,c.dispatchEvent.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,c.dispatchEvent.call(t,t.media,"seeked"),c.dispatchEvent.call(t,t.media,"play")}),t.embed.on("ended",function(){t.media.paused=!0,c.dispatchEvent.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,c.dispatchEvent.call(t,t.media,"error")}),setTimeout(function(){return m.build.call(t)},0)}};function P(e){switch(e){case"hd2160":return 2160;case 2160:return"hd2160";case"hd1440":return 1440;case 1440:return"hd1440";case"hd1080":return 1080;case 1080:return"hd1080";case"hd720":return 720;case 720:return"hd720";case"large":return 480;case 480:return"large";case"medium":return 360;case 360:return"medium";case"small":return 240;case 240:return"small";default:return"default"}}var x={setup:function(){var e=this;c.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),x.setAspectRatio.call(this),c.is.object(window.YT)&&c.is.function(window.YT.Player)?x.ready.call(this):(c.loadScript(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){x.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(c.is.function(this.embed.getVideoData)){var i=this.embed.getVideoData().title;if(c.is.empty(i))return this.config.title=i,void m.setTitle.call(this)}var n=this.config.keys.google;if(c.is.string(n)&&!c.is.empty(n)){var s=c.format(this.config.urls.youtube.api,e,n);c.fetch(s).then(function(e){c.is.object(e)&&(t.config.title=e.items[0].snippet.title,m.setTitle.call(t))}).catch(function(){})}},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(){var e=this,t=e.media.getAttribute("id");if(c.is.empty(t)||!t.startsWith("youtube-")){var i=e.media.getAttribute("src");c.is.empty(i)&&(i=e.media.getAttribute(this.config.attributes.embed.id));var n=c.parseYouTubeId(i),s=c.generateId(e.provider),a=c.createElement("div",{id:s});e.media=c.replaceElement(a,e.media),e.media.setAttribute("poster",c.format(e.config.urls.youtube.poster,n)),e.embed=new window.YT.Player(s,{videoId:n,playerVars:{autoplay:e.config.autoplay?1:0,controls:e.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,widget_referrer:window?window.location.href:null,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language},events:{onError:function(t){if(!c.is.object(e.media.error)){var i={code:t.data};switch(t.data){case 2:i.message="The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.";break;case 5:i.message="The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.";break;case 100:i.message="The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.";break;case 101:case 150:i.message="The owner of the requested video does not allow it to be played in embedded players.";break;default:i.message="An unknown error occured"}e.media.error=i,c.dispatchEvent.call(e,e.media,"error")}},onPlaybackQualityChange:function(){c.dispatchEvent.call(e,e.media,"qualitychange",!1,{quality:e.media.quality})},onPlaybackRateChange:function(t){var i=t.target;e.media.playbackRate=i.getPlaybackRate(),c.dispatchEvent.call(e,e.media,"ratechange")},onReady:function(t){var i=t.target;x.getTitle.call(e,n),e.media.play=function(){i.playVideo()},e.media.pause=function(){i.pauseVideo()},e.media.stop=function(){i.stopVideo()},e.media.duration=i.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(t){var n=e.media.paused;e.media.seeking=!0,c.dispatchEvent.call(e,e.media,"seeking"),i.seekTo(t),n&&e.pause()}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(e.media,"quality",{get:function(){return P(i.getPlaybackQuality())},set:function(t){var n=t;i.setPlaybackQuality(P(n)),c.dispatchEvent.call(e,e.media,"qualityrequested",!1,{quality:n})}});var s=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return s},set:function(t){s=t,i.setVolume(100*s),c.dispatchEvent.call(e,e.media,"volumechange")}});var a=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return a},set:function(t){var n=c.is.boolean(t)?t:a;a=n,i[n?"mute":"unMute"](),c.dispatchEvent.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=i.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),c.dispatchEvent.call(e,e.media,"timeupdate"),c.dispatchEvent.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=i.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&c.dispatchEvent.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),c.dispatchEvent.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return m.build.call(e)},50)},onStateChange:function(t){var i,n=t.target;switch(clearInterval(e.timers.playing),t.data){case-1:c.dispatchEvent.call(e,e.media,"timeupdate"),e.media.buffered=n.getVideoLoadedFraction(),c.dispatchEvent.call(e,e.media,"progress");break;case 0:e.media.paused=!0,e.media.loop?(n.stopVideo(),n.playVideo()):c.dispatchEvent.call(e,e.media,"ended");break;case 1:e.media.seeking&&c.dispatchEvent.call(e,e.media,"seeked"),e.media.seeking=!1,e.media.paused&&c.dispatchEvent.call(e,e.media,"play"),e.media.paused=!1,c.dispatchEvent.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){c.dispatchEvent.call(e,e.media,"timeupdate")},50),e.media.duration!==n.getDuration()&&(e.media.duration=n.getDuration(),c.dispatchEvent.call(e,e.media,"durationchange")),f.setQualityMenu.call(e,(i=n.getAvailableQualityLevels(),c.is.empty(i)?i:c.dedupe(i.map(function(e){return P(e)}))));break;case 2:e.media.paused=!0,c.dispatchEvent.call(e,e.media,"pause")}c.dispatchEvent.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},L={setup:function(){if(this.media)if(c.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),c.toggleClass(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&c.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=c.createElement("div",{class:this.config.classNames.video}),c.wrap(this.media,this.elements.wrapper),this.elements.poster=c.createElement("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isEmbed)switch(this.provider){case"youtube":x.setup.call(this);break;case"vimeo":N.setup.call(this)}else this.isHTML5&&d.extend.call(this);else this.debug.warn("No media element found!")}},M=function(){function e(t){var i=this;a(this,e),this.player=t,this.publisherId=t.config.ads.publisherId,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){i.on("loaded",e),i.on("error",t)}),this.load()}return l(e,[{key:"load",value:function(){var e=this;this.enabled&&(c.is.object(window.google)&&c.is.object(window.google.ima)?this.ready():c.loadScript(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=c.createElement("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var i=new google.ima.AdsRequest;i.adTagUrl=this.tagUrl,i.linearAdSlotWidth=t.offsetWidth,i.linearAdSlotHeight=t.offsetHeight,i.nonLinearAdSlotWidth=t.offsetWidth,i.nonLinearAdSlotHeight=t.offsetHeight,i.forceNonLinearFullSlot=!1,i.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(i)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=c.formatTime(Math.max(e.manager.getRemainingTime(),0)),i=p("advertisement",e.player.config)+" - "+t;e.elements.container.setAttribute("data-badge-text",i)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this,i=new google.ima.AdsRenderingSettings;i.restoreCustomPlaybackStateOnAdBreakComplete=!0,i.enablePreloading=!0,this.manager=e.getAdsManager(this.player,i),this.cuePoints=this.manager.getCuePoints(),c.is.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var i=t.player.elements.progress;if(c.is.element(i)){var n=100/t.player.duration*e,s=c.createElement("span",{class:t.player.config.classNames.cues});s.style.left=n.toString()+"%",i.appendChild(s)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}},{key:"onAdEvent",value:function(e){var t=this,i=this.player.elements.container,n=e.getAd(),s=function(e){var i="ads"+e.replace(/_/g,"").toLowerCase();c.dispatchEvent.call(t.player,t.player.media,i)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),s(e.type),this.pollCountdown(!0),n.isLinear()||(n.width=i.offsetWidth,n.height=i.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:s(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:s(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:s(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:s(e.type)}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e=this,t=this.player.elements.container,i=void 0;this.player.on("ended",function(){e.loader.contentComplete()}),this.player.on("seeking",function(){return i=e.player.currentTime}),this.player.on("seeked",function(){var t=e.player.currentTime;c.is.empty(e.cuePoints)||e.cuePoints.forEach(function(n,s){i<n&&n<t&&(e.manager.discardAdBreak(),e.cuePoints.splice(s,1))})}),window.addEventListener("resize",function(){e.manager&&e.manager.resize(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,i=arguments.length,n=Array(i>1?i-1:0),s=1;s<i;s++)n[s-1]=arguments[s];var a=this.events[e];c.is.array(a)&&a.forEach(function(e){c.is.function(e)&&e.apply(t,n)})}},{key:"on",value:function(e,t){return c.is.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var i=this;this.player.debug.log("Safety timer invoked from: "+t),this.safetyTimer=setTimeout(function(){i.cancel(),i.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){c.is.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: "+e),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){return this.player.isVideo&&this.player.config.ads.enabled&&!c.is.empty(this.publisherId)}},{key:"tagUrl",get:function(){var e={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"https://go.aniview.com/api/adserver6/vast/?"+c.buildUrlParams(e)}}]),e}(),I={insertElements:function(e,t){var i=this;c.is.string(t)?c.insertElement(e,this.media,{src:t}):c.is.array(t)&&t.forEach(function(t){c.insertElement(e,i.media,t)})},change:function(e){var t=this;c.is.object(e)&&"sources"in e&&e.sources.length?(d.cancelRequests.call(this),this.destroy.call(this,function(){switch(t.options.quality=[],c.removeElement(t.media),t.media=null,c.is.element(t.elements.container)&&t.elements.container.removeAttribute("class"),t.type=e.type,t.provider=c.is.empty(e.sources[0].provider)?n.html5:e.sources[0].provider,t.supported=u.check(t.type,t.provider,t.config.playsinline),t.provider+":"+t.type){case"html5:video":t.media=c.createElement("video");break;case"html5:audio":t.media=c.createElement("audio");break;case"youtube:video":case"vimeo:video":t.media=c.createElement("div",{src:e.sources[0].src})}t.elements.container.appendChild(t.media),c.is.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),c.is.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),m.addStyleHook.call(t),t.isHTML5&&I.insertElements.call(t,"source",e.sources),t.config.title=e.title,L.setup.call(t),t.isHTML5&&("tracks"in e&&I.insertElements.call(t,"track",e.tracks),t.media.load()),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&m.build.call(t),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},q=function(){function e(t){a(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return l(e,[{key:"get",value:function(t){if(!e.supported)return null;var i=window.localStorage.getItem(this.key);if(c.is.empty(i))return null;var n=JSON.parse(i);return c.is.string(t)&&t.length?n[t]:n}},{key:"set",value:function(t){if(e.supported&&this.enabled&&c.is.object(t)){var i=this.get();c.is.empty(i)&&(i={}),c.extend(i,t),window.localStorage.setItem(this.key,JSON.stringify(i))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();return function(){function e(t,i){var l=this;if(a(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=u.touch,this.media=t,c.is.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||c.is.nodeList(this.media)||c.is.array(this.media))&&(this.media=this.media[0]),this.config=c.extend({},k,i||{},function(){try{return JSON.parse(l.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,buttons:{},display:{},progress:{},inputs:{},settings:{menu:null,panes:{},tabs:{}},captions:null},this.captions={active:null,currentTrack:null},this.fullscreen={active:!1},this.options={speed:[],quality:[],captions:[]},this.debug=new b(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",u),!c.is.nullOrUndefined(this.media)&&c.is.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(u.check().api){var r=this.media.cloneNode(!0);r.autoplay=!1,this.elements.original=r;var o=this.media.tagName.toLowerCase(),d=null,p=null,h=null;switch(o){case"div":if(d=this.media.querySelector("iframe"),c.is.element(d)){if(p=d.getAttribute("src"),this.provider=c.getProviderByUrl(p),this.elements.container=this.media,this.media=d,this.elements.container.className="",h=c.getUrlParams(p),!c.is.empty(h)){var g=["1","true"];g.includes(h.autoplay)&&(this.config.autoplay=!0),g.includes(h.loop)&&(this.config.loop.active=!0),this.isYouTube?this.config.playsinline=g.includes(h.playsinline):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(c.is.empty(this.provider)||!Object.keys(n).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=s.video;break;case"video":case"audio":this.type=o,this.provider=n.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),this.media.hasAttribute("playsinline")&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=u.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.listeners=new S(this),this.storage=new q(this),this.media.plyr=this,c.is.element(this.elements.container)||(this.elements.container=c.createElement("div"),c.wrap(this.media,this.elements.container)),this.elements.container.setAttribute("tabindex",0),m.addStyleHook.call(this),L.setup.call(this),this.config.debug&&c.on(this.elements.container,this.config.events.join(" "),function(e){l.debug.log("event: "+e.type)}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&m.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new A(this),this.ads=new M(this),this.config.autoplay&&this.play()):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return l(e,[{key:"play",value:function(){return c.is.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&c.is.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(c.is.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):c.is.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(c.is.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(c.is.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(c.is.number(e)?e:1)}},{key:"decreaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t-(c.is.number(e)?e:1)}},{key:"toggleCaptions",value:function(e){if(this.supported.ui){var t=c.is.boolean(e)?e:!this.elements.container.classList.contains(this.config.classNames.captions.active);this.captions.active!==t&&(this.captions.active=t,c.toggleState(this.elements.buttons.captions,this.captions.active),c.toggleClass(this.elements.container,this.config.classNames.captions.active,this.captions.active),c.dispatchEvent.call(this,this.media,this.captions.active?"captionsenabled":"captionsdisabled"))}}},{key:"airplay",value:function(){u.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){var t=this;if(c.is.element(this.elements.controls)&&this.supported.ui&&!this.isAudio){var i=0,n=e,s=!1;if(!c.is.boolean(e))if(c.is.event(e)){s="enterfullscreen"===e.type;n=["touchstart","touchmove","mouseenter","mousemove","focusin"].includes(e.type),["touchmove","touchend","mousemove"].includes(e.type)&&(i=2e3),this.touch||"focusin"!==e.type||(i=3e3,c.toggleClass(this.elements.controls,this.config.classNames.noTransition,!0))}else n=c.hasClass(this.elements.container,this.config.classNames.hideControls);if(clearTimeout(this.timers.controls),n||this.paused||this.loading){if(c.toggleClass(this.elements.container,this.config.classNames.hideControls,!1)&&c.dispatchEvent.call(this,this.media,"controlsshown"),this.paused||this.loading)return;this.touch&&(i=3e3)}n&&!this.playing||(this.timers.controls=setTimeout(function(){c.is.element(t.elements.controls)&&((!t.elements.controls.pressed&&!t.elements.controls.hover||s)&&(c.hasClass(t.elements.container,t.config.classNames.hideControls)||c.toggleClass(t.elements.controls,t.config.classNames.noTransition,!1),c.toggleClass(t.elements.container,t.config.classNames.hideControls,t.config.hideControls)&&(c.dispatchEvent.call(t,t.media,"controlshidden"),t.config.controls.includes("settings")&&!c.is.empty(t.config.settings)&&f.toggleMenu.call(t,!1))))},i))}}},{key:"on",value:function(e,t){c.on(this.elements.container,e,t)}},{key:"off",value:function(e,t){c.off(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var n=function(){document.body.style.overflow="",t.embed=null,i?(Object.keys(t.elements).length&&(c.removeElement(t.elements.buttons.play),c.removeElement(t.elements.captions),c.removeElement(t.elements.controls),c.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),c.is.function(e)&&e()):(t.listeners.clear(),c.replaceElement(t.elements.original,t.elements.container),c.dispatchEvent.call(t,t.elements.original,"destroyed",!0),c.is.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};switch(this.stop(),this.provider+":"+this.type){case"html5:video":case"html5:audio":clearTimeout(this.timers.loading),m.toggleNativeControls.call(this,!0),n();break;case"youtube:video":clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&c.is.function(this.embed.destroy)&&this.embed.destroy(),n();break;case"vimeo:video":null!==this.embed&&this.embed.unload().then(n),setTimeout(n,200)}}}},{key:"supports",value:function(e){return u.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===n.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===n.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===n.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===s.video)}},{key:"isAudio",get:function(){return Boolean(this.type===s.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){var t=0;c.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t,this.debug.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return c.is.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=this.media?Number(this.media.duration):0;return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;c.is.string(t)&&(t=Number(t)),c.is.number(t)||(t=this.storage.get("volume")),c.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!c.is.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;c.is.boolean(t)||(t=this.storage.get("muted")),c.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;c.is.number(e)&&(t=e),c.is.number(t)||(t=this.storage.get("speed")),c.is.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed ("+t+")")},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=null;if(c.is.empty(e)||(t=Number(e)),c.is.number(t)&&0!==t||(t=this.storage.get("quality")),c.is.number(t)||(t=this.config.quality.selected),c.is.number(t)||(t=this.config.quality.default),this.options.quality.length){if(!this.options.quality.includes(t)){var i=c.closest(this.options.quality,t);this.debug.warn("Unsupported quality option: "+t+", using "+i+" instead"),t=i}this.config.quality.selected=t,this.media.quality=t}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=c.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){I.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){this.isVideo?c.is.string(e)&&(this.media.setAttribute("poster",e),m.setPoster.call(this)):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=c.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"language",set:function(e){if(c.is.string(e))if(c.is.empty(e))this.toggleCaptions(!1);else{var t=e.toLowerCase();this.options.captions.includes(t)?(this.toggleCaptions(!0),"enabled"!==t&&this.language!==t&&(this.captions.language=t,y.setText.call(this,null),y.setLanguage.call(this),c.dispatchEvent.call(this,this.media,"languagechange"))):this.debug.warn("Unsupported language option: "+t)}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t="picture-in-picture",i="inline";if(u.pip){var n=c.is.boolean(e)?e:this.pip===i;this.media.webkitSetPresentationMode(n?t:i)}},get:function(){return u.pip?this.media.webkitPresentationMode:null}}],[{key:"supported",value:function(e,t,i){return u.check(e,t,i)}},{key:"loadSprite",value:function(e,t){return c.loadSprite(e,t)}},{key:"setup",value:function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null;return c.is.string(t)?n=Array.from(document.querySelectorAll(t)):c.is.nodeList(t)?n=Array.from(t):c.is.array(t)&&(n=t.filter(function(e){return c.is.element(e)})),c.is.empty(n)?null:n.map(function(t){return new e(t,i)})}}]),e}()}); +"object"==typeof navigator&&function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function i(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}function n(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function a(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var i=[],n=!0,a=!1,s=void 0;try{for(var o,r=e[Symbol.iterator]();!(n=(o=r.next()).done)&&(i.push(o.value),!t||i.length!==t);n=!0);}catch(e){a=!0,s=e}finally{try{n||null==r.return||r.return()}finally{if(a)throw s}}return i}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function s(e){return function(e){if(Array.isArray(e)){for(var t=0,i=new Array(e.length);t<e.length;t++)i[t]=e[t];return i}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}var o=function(e){return null!=e?e.constructor:null},r=function(e,t){return Boolean(e&&t&&e instanceof t)},l=function(e){return null==e},c=function(e){return o(e)===Object},u=function(e){return o(e)===String},d=function(e){return Array.isArray(e)},h=function(e){return r(e,NodeList)},m=function(e){return l(e)||(u(e)||d(e)||h(e))&&!e.length||c(e)&&!Object.keys(e).length},p={nullOrUndefined:l,object:c,number:function(e){return o(e)===Number&&!Number.isNaN(e)},string:u,boolean:function(e){return o(e)===Boolean},function:function(e){return o(e)===Function},array:d,weakMap:function(e){return r(e,WeakMap)},nodeList:h,element:function(e){return r(e,Element)},textNode:function(e){return o(e)===Text},event:function(e){return r(e,Event)},keyboardEvent:function(e){return r(e,KeyboardEvent)},cue:function(e){return r(e,window.TextTrackCue)||r(e,window.VTTCue)},track:function(e){return r(e,TextTrack)||!l(e)&&u(e.kind)},url:function(e){if(r(e,window.URL))return!0;if(!u(e))return!1;var t=e;e.startsWith("http://")&&e.startsWith("https://")||(t="http://".concat(e));try{return!m(new URL(t).hostname)}catch(e){return!1}},empty:m},f=function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(e){}return e}();function g(e,t,i){var n=this,a=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(e&&"addEventListener"in e&&!p.empty(t)&&p.function(i)){var r=t.split(" "),l=o;f&&(l={passive:s,capture:o}),r.forEach(function(t){n&&n.eventListeners&&a&&n.eventListeners.push({element:e,type:t,callback:i,options:l}),e[a?"addEventListener":"removeEventListener"](t,i,l)})}}function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];g.call(this,e,t,i,!0,n,a)}function v(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];g.call(this,e,t,i,!1,n,a)}function b(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,a=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];g.call(this,e,i,function o(){v(e,i,o,a,s);for(var r=arguments.length,l=new Array(r),c=0;c<r;c++)l[c]=arguments[c];n.apply(t,l)},!0,a,s)}function k(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(p.element(e)&&!p.empty(t)){var a=new CustomEvent(t,{bubbles:i,detail:Object.assign({},n,{plyr:this})});e.dispatchEvent(a)}}function w(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,a=e.parentNode,s=e.nextSibling;n.appendChild(e),s?a.insertBefore(n,s):a.appendChild(n)})}function T(e,t){p.element(e)&&!p.empty(t)&&Object.entries(t).filter(function(e){var t=a(e,2)[1];return!p.nullOrUndefined(t)}).forEach(function(t){var i=a(t,2),n=i[0],s=i[1];return e.setAttribute(n,s)})}function C(e,t,i){var n=document.createElement(e);return p.object(t)&&T(n,t),p.string(i)&&(n.innerText=i),n}function A(e,t,i,n){p.element(t)&&t.appendChild(C(e,i,n))}function E(e){p.nodeList(e)||p.array(e)?Array.from(e).forEach(E):p.element(e)&&p.element(e.parentNode)&&e.parentNode.removeChild(e)}function P(e){if(p.element(e))for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1}function S(e,t){return p.element(t)&&p.element(t.parentNode)&&p.element(e)?(t.parentNode.replaceChild(e,t),e):null}function N(e,t){if(!p.string(e)||p.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),a=t.replace(".",""),s=t.replace(/[[\]]/g,"").split("="),o=s[0],r=s.length>1?s[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":p.object(n)&&p.string(n.class)&&(n.class+=" ".concat(a)),i.class=a;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i}function M(e,t){if(p.element(e)){var i=t;p.boolean(i)||(i=!e.hidden),i?e.setAttribute("hidden",""):e.removeAttribute("hidden")}}function x(e,t,i){if(p.nodeList(e))return Array.from(e).map(function(e){return x(e,t,i)});if(p.element(e)){var n="toggle";return void 0!==i&&(n=i?"add":"remove"),e.classList[n](t),e.classList.contains(t)}return!1}function I(e,t){return p.element(e)&&e.classList.contains(t)}function L(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function _(e){return this.elements.container.querySelectorAll(e)}function O(e){return this.elements.container.querySelector(e)}function j(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];p.element(e)&&(e.focus({preventScroll:!0}),t&&x(e,this.config.classNames.tabFocus))}var q,D,H,R=(q=document.createElement("span"),D={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},H=Object.keys(D).find(function(e){return void 0!==q.style[e]}),!!p.string(H)&&D[H]);function B(e){setTimeout(function(){try{M(e,!0),e.offsetHeight,M(e,!1)}catch(e){}},0)}var F,V={isIE:!!document.documentMode,isEdge:window.navigator.userAgent.includes("Edge"),isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)},U={"audio/ogg":"vorbis","audio/wav":"1","video/webm":"vp8, vorbis","video/mp4":"avc1.42E01E, mp4a.40.2","video/ogg":"theora"},z={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,i){var n=V.isIPhone&&i&&z.playsinline,a=z[e]||"html5"!==t;return{api:a,ui:a&&z.rangeInput&&("video"!==e||!V.isIPhone||n)}},pip:!(V.isIPhone||!p.function(C("video").webkitSetPresentationMode)&&(!document.pictureInPictureEnabled||C("video").disablePictureInPicture)),airplay:p.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){if(p.empty(e))return!1;var t=a(e.split("/"),1)[0],i=e;if(!this.isHTML5||t!==this.type)return!1;Object.keys(U).includes(i)&&(i+='; codecs="'.concat(U[e],'"'));try{return Boolean(i&&this.media.canPlayType(i).replace(/no/,""))}catch(e){return!1}},textTracks:"textTracks"in document.createElement("video"),rangeInput:(F=document.createElement("input"),F.type="range","range"===F.type),touch:"ontouchstart"in document.documentElement,transitions:!1!==R,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},W={getSources:function(){var e=this;return this.isHTML5?Array.from(this.media.querySelectorAll("source")).filter(function(t){var i=t.getAttribute("type");return!!p.empty(i)||z.mime.call(e,i)}):[]},getQualityOptions:function(){return W.getSources.call(this).map(function(e){return Number(e.getAttribute("size"))}).filter(Boolean)},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=W.getSources.call(e).find(function(t){return t.getAttribute("src")===e.source});return t&&Number(t.getAttribute("size"))},set:function(t){var i=W.getSources.call(e).find(function(e){return Number(e.getAttribute("size"))===t});if(i){var n=e.media,a=n.currentTime,s=n.paused,o=n.preload,r=n.readyState;e.media.src=i.getAttribute("src"),("none"!==o||r)&&(e.once("loadedmetadata",function(){e.currentTime=a,s||e.play()}),e.media.load()),k.call(e,e.media,"qualitychange",!1,{quality:t})}}})}},cancelRequests:function(){this.isHTML5&&(E(W.getSources.call(this)),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}};function K(e){return p.array(e)?e.filter(function(t,i){return e.indexOf(t)===i}):e}function Y(e,t){return t.split(".").reduce(function(e,t){return e&&e[t]},e)}function Q(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,i=new Array(t>1?t-1:0),a=1;a<t;a++)i[a-1]=arguments[a];if(!i.length)return e;var s=i.shift();return p.object(s)?(Object.keys(s).forEach(function(t){p.object(s[t])?(Object.keys(e).includes(t)||Object.assign(e,n({},t,{})),Q(e[t],s[t])):Object.assign(e,n({},t,s[t]))}),Q.apply(void 0,[e].concat(i))):e}function J(e){for(var t=arguments.length,i=new Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];return p.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return i[t].toString()})}function X(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"),i.toString())}function $(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}function G(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=X(e,"-"," "),e=X(e,"_"," "),X(e=$(e)," ","")}(e)).charAt(0).toLowerCase()+e.slice(1)}function Z(e){var t=document.createElement("div");return t.appendChild(e),t.innerHTML}var ee={pip:"PIP",airplay:"AirPlay",html5:"HTML5",vimeo:"Vimeo",youtube:"YouTube"},te=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(p.empty(e)||p.empty(t))return"";var i=Y(t.i18n,e);if(p.empty(i))return Object.keys(ee).includes(e)?ee[e]:"";var n={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(n).forEach(function(e){var t=a(e,2),n=t[0],s=t[1];i=X(i,n,s)}),i},ie=function(){function t(i){e(this,t),this.enabled=i.config.storage.enabled,this.key=i.config.storage.key}return i(t,[{key:"get",value:function(e){if(!t.supported||!this.enabled)return null;var i=window.localStorage.getItem(this.key);if(p.empty(i))return null;var n=JSON.parse(i);return p.string(e)&&e.length?n[e]:n}},{key:"set",value:function(e){if(t.supported&&this.enabled&&p.object(e)){var i=this.get();p.empty(i)&&(i={}),Q(i,e),window.localStorage.setItem(this.key,JSON.stringify(i))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),t}();function ne(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(i,n){try{var a=new XMLHttpRequest;if(!("withCredentials"in a))return;a.addEventListener("load",function(){if("text"===t)try{i(JSON.parse(a.responseText))}catch(e){i(a.responseText)}else i(a.response)}),a.addEventListener("error",function(){throw new Error(a.status)}),a.open("GET",e,!0),a.responseType=t,a.send()}catch(e){n(e)}})}function ae(e,t){if(p.string(e)){var i=p.string(t),n=function(){return null!==document.getElementById(t)},a=function(e,t){e.innerHTML=t,i&&n()||document.body.insertAdjacentElement("afterbegin",e)};if(!i||!n()){var s=ie.supported,o=document.createElement("div");if(o.setAttribute("hidden",""),i&&o.setAttribute("id",t),s){var r=window.localStorage.getItem("".concat("cache","-").concat(t));if(null!==r){var l=JSON.parse(r);a(o,l.content)}}ne(e).then(function(e){p.empty(e)||(s&&window.localStorage.setItem("".concat("cache","-").concat(t),JSON.stringify({content:e})),a(o,e))}).catch(function(){})}}}var se=function(e){return Math.trunc(e/60/60%60,10)},oe=function(e){return Math.trunc(e/60%60,10)},re=function(e){return Math.trunc(e%60,10)};function le(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!p.number(e))return le(null,t,i);var n=function(e){return"0".concat(e).slice(-2)},a=se(e),s=oe(e),o=re(e);return a=t||a>0?"".concat(a,":"):"","".concat(i&&e>0?"-":"").concat(a).concat(n(s),":").concat(n(o))}var ce={getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||V.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=O.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:_.call(this,this.config.selectors.buttons.play),pause:O.call(this,this.config.selectors.buttons.pause),restart:O.call(this,this.config.selectors.buttons.restart),rewind:O.call(this,this.config.selectors.buttons.rewind),fastForward:O.call(this,this.config.selectors.buttons.fastForward),mute:O.call(this,this.config.selectors.buttons.mute),pip:O.call(this,this.config.selectors.buttons.pip),airplay:O.call(this,this.config.selectors.buttons.airplay),settings:O.call(this,this.config.selectors.buttons.settings),captions:O.call(this,this.config.selectors.buttons.captions),fullscreen:O.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=O.call(this,this.config.selectors.progress),this.elements.inputs={seek:O.call(this,this.config.selectors.inputs.seek),volume:O.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:O.call(this,this.config.selectors.display.buffer),currentTime:O.call(this,this.config.selectors.display.currentTime),duration:O.call(this,this.config.selectors.display.duration)},p.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip))),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var i=ce.getIconUrl.call(this),n="".concat(i.cors?"":i.url,"#").concat(this.config.iconPrefix),a=document.createElementNS("http://www.w3.org/2000/svg","svg");T(a,Q(t,{role:"presentation",focusable:"false"}));var s=document.createElementNS("http://www.w3.org/2000/svg","use"),o="".concat(n,"-").concat(e);return"href"in s&&s.setAttributeNS("http://www.w3.org/1999/xlink","href",o),s.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),a.appendChild(s),a},createLabel:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=te(e,this.config);return C("span",Object.assign({},t,{class:[t.class,this.config.classNames.hidden].filter(Boolean).join(" ")}),i)},createBadge:function(e){if(p.empty(e))return null;var t=C("span",{class:this.config.classNames.menu.value});return t.appendChild(C("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=Object.assign({},t),n=G(e),a={element:"button",toggle:!1,label:null,icon:null,labelPressed:null,iconPressed:null};switch(["element","icon","label"].forEach(function(e){Object.keys(i).includes(e)&&(a[e]=i[e],delete i[e])}),"button"!==a.element||Object.keys(i).includes("type")||(i.type="button"),Object.keys(i).includes("class")?i.class.includes(this.config.classNames.control)||(i.class+=" ".concat(this.config.classNames.control)):i.class=this.config.classNames.control,e){case"play":a.toggle=!0,a.label="play",a.labelPressed="pause",a.icon="play",a.iconPressed="pause";break;case"mute":a.toggle=!0,a.label="mute",a.labelPressed="unmute",a.icon="volume",a.iconPressed="muted";break;case"captions":a.toggle=!0,a.label="enableCaptions",a.labelPressed="disableCaptions",a.icon="captions-off",a.iconPressed="captions-on";break;case"fullscreen":a.toggle=!0,a.label="enterFullscreen",a.labelPressed="exitFullscreen",a.icon="enter-fullscreen",a.iconPressed="exit-fullscreen";break;case"play-large":i.class+=" ".concat(this.config.classNames.control,"--overlaid"),n="play",a.label="play",a.icon="play";break;default:p.empty(a.label)&&(a.label=n),p.empty(a.icon)&&(a.icon=e)}var s=C(a.element);return a.toggle?(s.appendChild(ce.createIcon.call(this,a.iconPressed,{class:"icon--pressed"})),s.appendChild(ce.createIcon.call(this,a.icon,{class:"icon--not-pressed"})),s.appendChild(ce.createLabel.call(this,a.labelPressed,{class:"label--pressed"})),s.appendChild(ce.createLabel.call(this,a.label,{class:"label--not-pressed"}))):(s.appendChild(ce.createIcon.call(this,a.icon)),s.appendChild(ce.createLabel.call(this,a.label))),Q(i,N(this.config.selectors.buttons[n],i)),T(s,i),"play"===n?(p.array(this.elements.buttons[n])||(this.elements.buttons[n]=[]),this.elements.buttons[n].push(s)):this.elements.buttons[n]=s,s},createRange:function(e,t){var i=C("input",Q(N(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-label":te(e,this.config),"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=i,ce.updateRangeFill.call(this,i),i},createProgress:function(e,t){var i=C("progress",Q(N(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){i.appendChild(C("span",null,"0"));var n={played:"played",buffer:"buffered"}[e],a=n?te(n,this.config):"";i.innerText="% ".concat(a.toLowerCase())}return this.elements.display[e]=i,i},createTime:function(e){var t=N(this.config.selectors.display[e]),i=C("div",Q(t,{class:"".concat(this.config.classNames.display.time," ").concat(t.class?t.class:"").trim(),"aria-label":te(e,this.config)}),"00:00");return this.elements.display[e]=i,i},bindMenuItemShortcuts:function(e,t){var i=this;y(e,"keydown keyup",function(n){if([32,38,39,40].includes(n.which)&&(n.preventDefault(),n.stopPropagation(),"keydown"!==n.type)){var a,s=L(e,'[role="menuitemradio"]');if(!s&&[32,39].includes(n.which))ce.showMenuPanel.call(i,t,!0);else 32!==n.which&&(40===n.which||s&&39===n.which?(a=e.nextElementSibling,p.element(a)||(a=e.parentNode.firstElementChild)):(a=e.previousElementSibling,p.element(a)||(a=e.parentNode.lastElementChild)),j.call(i,a,!0))}},!1),y(e,"keyup",function(e){13===e.which&&ce.focusFirstMenuItem.call(i,null,!0)})},createMenuItem:function(e){var t=this,i=e.value,n=e.list,a=e.type,s=e.title,o=e.badge,r=void 0===o?null:o,l=e.checked,c=void 0!==l&&l,u=N(this.config.selectors.inputs[a]),d=C("button",Q(u,{type:"button",role:"menuitemradio",class:"".concat(this.config.classNames.control," ").concat(u.class?u.class:"").trim(),"aria-checked":c,value:i})),h=C("span");h.innerHTML=s,p.element(r)&&h.appendChild(r),d.appendChild(h),Object.defineProperty(d,"checked",{enumerable:!0,get:function(){return"true"===d.getAttribute("aria-checked")},set:function(e){e&&Array.from(d.parentNode.children).filter(function(e){return L(e,'[role="menuitemradio"]')}).forEach(function(e){return e.setAttribute("aria-checked","false")}),d.setAttribute("aria-checked",e?"true":"false")}}),this.listeners.bind(d,"click keyup",function(e){if(!p.keyboardEvent(e)||32===e.which){switch(e.preventDefault(),e.stopPropagation(),d.checked=!0,a){case"language":t.currentTrack=Number(i);break;case"quality":t.quality=i;break;case"speed":t.speed=parseFloat(i)}ce.showMenuPanel.call(t,"home",p.keyboardEvent(e))}},a,!1),ce.bindMenuItemShortcuts.call(this,d,a),n.appendChild(d)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return p.number(e)?le(e,se(this.duration)>0,t):e},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];p.element(e)&&p.number(t)&&(e.innerText=ce.formatTime(t,i))},updateVolume:function(){this.supported.ui&&(p.element(this.elements.inputs.volume)&&ce.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),p.element(this.elements.buttons.mute)&&(this.elements.buttons.mute.pressed=this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;p.element(e)&&(e.value=t,ce.updateRangeFill.call(this,e))},updateProgress:function(e){var t=this;if(this.supported.ui&&p.event(e)){var i,n,a=0;if(e)switch(e.type){case"timeupdate":case"seeking":case"seeked":i=this.currentTime,n=this.duration,a=0===i||0===n||Number.isNaN(i)||Number.isNaN(n)?0:(i/n*100).toFixed(2),"timeupdate"===e.type&&ce.setRange.call(this,this.elements.inputs.seek,a);break;case"playing":case"progress":!function(e,i){var n=p.number(i)?i:0,a=p.element(e)?e:t.elements.display.buffer;if(p.element(a)){a.value=n;var s=a.getElementsByTagName("span")[0];p.element(s)&&(s.childNodes[0].nodeValue=n)}}(this.elements.display.buffer,100*this.buffered)}}},updateRangeFill:function(e){var t=p.event(e)?e.target:e;if(p.element(t)&&"range"===t.getAttribute("type")){if(L(t,this.config.selectors.inputs.seek)){t.setAttribute("aria-valuenow",this.currentTime);var i=ce.formatTime(this.currentTime),n=ce.formatTime(this.duration),a=te("seekLabel",this.config);t.setAttribute("aria-valuetext",a.replace("{currentTime}",i).replace("{duration}",n))}else if(L(t,this.config.selectors.inputs.volume)){var s=100*t.value;t.setAttribute("aria-valuenow",s),t.setAttribute("aria-valuetext","".concat(s.toFixed(1),"%"))}else t.setAttribute("aria-valuenow",t.value);V.isWebkit&&t.style.setProperty("--value","".concat(t.value/t.max*100,"%"))}},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&p.element(this.elements.inputs.seek)&&p.element(this.elements.display.seekTooltip)&&0!==this.duration){var i=0,n=this.elements.progress.getBoundingClientRect(),a="".concat(this.config.classNames.tooltip,"--visible"),s=function(e){x(t.elements.display.seekTooltip,a,e)};if(this.touch)s(!1);else{if(p.event(e))i=100/n.width*(e.pageX-n.left);else{if(!I(this.elements.display.seekTooltip,a))return;i=parseFloat(this.elements.display.seekTooltip.style.left,10)}i<0?i=0:i>100&&(i=100),ce.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*i),this.elements.display.seekTooltip.style.left="".concat(i,"%"),p.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s("mouseenter"===e.type)}}},timeUpdate:function(e){var t=!p.element(this.elements.display.duration)&&this.config.invertTime;ce.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||ce.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui&&(this.config.invertTime||!this.currentTime)){if(this.duration>=Math.pow(2,32))return M(this.elements.display.currentTime,!0),void M(this.elements.progress,!0);p.element(this.elements.inputs.seek)&&this.elements.inputs.seek.setAttribute("aria-valuemax",this.duration);var e=p.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&ce.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&ce.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),ce.updateSeekTooltip.call(this)}},toggleMenuButton:function(e,t){M(this.elements.settings.buttons[e],!t)},updateSetting:function(e,t,i){var n=this.elements.settings.panels[e],a=null,s=t;if("captions"===e)a=this.currentTrack;else{if(a=p.empty(i)?this[e]:i,p.empty(a)&&(a=this.config[e].default),!p.empty(this.options[e])&&!this.options[e].includes(a))return void this.debug.warn("Unsupported value of '".concat(a,"' for ").concat(e));if(!this.config[e].options.includes(a))return void this.debug.warn("Disabled value of '".concat(a,"' for ").concat(e))}if(p.element(s)||(s=n&&n.querySelector('[role="menu"]')),p.element(s)){this.elements.settings.buttons[e].querySelector(".".concat(this.config.classNames.menu.value)).innerHTML=ce.getLabel.call(this,e,a);var o=s&&s.querySelector('[value="'.concat(a,'"]'));p.element(o)&&(o.checked=!0)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?te("normal",this.config):"".concat(t,"×");case"quality":if(p.number(t)){var i=te("qualityLabel.".concat(t),this.config);return i.length?i:"".concat(t,"p")}return $(t);case"captions":return he.getLabel.call(this);default:return null}},setQualityMenu:function(e){var t=this;if(p.element(this.elements.settings.panels.quality)){var i=this.elements.settings.panels.quality.querySelector('[role="menu"]');p.array(e)&&(this.options.quality=K(e).filter(function(e){return t.config.quality.options.includes(e)}));var n=!p.empty(this.options.quality)&&this.options.quality.length>1;if(ce.toggleMenuButton.call(this,"quality",n),P(i),ce.checkMenu.call(this),n){var a=function(e){var i=te("qualityBadge.".concat(e),t.config);return i.length?ce.createBadge.call(t,i):null};this.options.quality.sort(function(e,i){var n=t.config.quality.options;return n.indexOf(e)>n.indexOf(i)?1:-1}).forEach(function(e){ce.createMenuItem.call(t,{value:e,list:i,type:"quality",title:ce.getLabel.call(t,"quality",e),badge:a(e)})}),ce.updateSetting.call(this,"quality",i)}}},setCaptionsMenu:function(){var e=this;if(p.element(this.elements.settings.panels.captions)){var t=this.elements.settings.panels.captions.querySelector('[role="menu"]'),i=he.getTracks.call(this),n=Boolean(i.length);if(ce.toggleMenuButton.call(this,"captions",n),P(t),ce.checkMenu.call(this),n){var a=i.map(function(i,n){return{value:n,checked:e.captions.toggled&&e.currentTrack===n,title:he.getLabel.call(e,i),badge:i.language&&ce.createBadge.call(e,i.language.toUpperCase()),list:t,type:"language"}});a.unshift({value:-1,checked:!this.captions.toggled,title:te("disabled",this.config),list:t,type:"language"}),a.forEach(ce.createMenuItem.bind(this)),ce.updateSetting.call(this,"captions",t)}}},setSpeedMenu:function(e){var t=this;if(p.element(this.elements.settings.panels.speed)){var i=this.elements.settings.panels.speed.querySelector('[role="menu"]');p.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var n=!p.empty(this.options.speed)&&this.options.speed.length>1;ce.toggleMenuButton.call(this,"speed",n),P(i),ce.checkMenu.call(this),n&&(this.options.speed.forEach(function(e){ce.createMenuItem.call(t,{value:e,list:i,type:"speed",title:ce.getLabel.call(t,"speed",e)})}),ce.updateSetting.call(this,"speed",i))}},checkMenu:function(){var e=this.elements.settings.buttons,t=!p.empty(e)&&Object.values(e).some(function(e){return!e.hidden});M(this.elements.settings.menu,!t)},focusFirstMenuItem:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!this.elements.settings.popup.hidden){var i=e;p.element(i)||(i=Object.values(this.elements.settings.panels).find(function(e){return!e.hidden}));var n=i.querySelector('[role^="menuitem"]');j.call(this,n,t)}},toggleMenu:function(e){var t=this.elements.settings.popup,i=this.elements.buttons.settings;if(p.element(t)&&p.element(i)){var n=t.hidden,a=n;if(p.boolean(e))a=e;else if(p.keyboardEvent(e)&&27===e.which)a=!1;else if(p.event(e)){var s=t.contains(e.target);if(s||!s&&e.target!==i&&a)return}i.setAttribute("aria-expanded",a),M(t,!a),x(this.elements.container,this.config.classNames.menu.open,a),a&&p.keyboardEvent(e)?ce.focusFirstMenuItem.call(this,null,!0):a||n||j.call(this,i,p.keyboardEvent(e))}},getMenuSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return E(t),{width:i,height:n}},showMenuPanel:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=document.getElementById("plyr-settings-".concat(this.id,"-").concat(t));if(p.element(n)){var a=n.parentNode,s=Array.from(a.children).find(function(e){return!e.hidden});if(z.transitions&&!z.reducedMotion){a.style.width="".concat(s.scrollWidth,"px"),a.style.height="".concat(s.scrollHeight,"px");var o=ce.getMenuSize.call(this,n);y.call(this,a,R,function t(i){i.target===a&&["width","height"].includes(i.propertyName)&&(a.style.width="",a.style.height="",v.call(e,a,R,t))}),a.style.width="".concat(o.width,"px"),a.style.height="".concat(o.height,"px")}M(s,!0),M(n,!1),ce.focusFirstMenuItem.call(this,n,i)}},setDownloadLink:function(){var e=this.elements.buttons.download;p.element(e)&&e.setAttribute("href",this.download)},create:function(e){var t=this,i=C("div",N(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(ce.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(ce.createButton.call(this,"rewind")),this.config.controls.includes("play")&&i.appendChild(ce.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&i.appendChild(ce.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=C("div",N(this.config.selectors.progress));if(n.appendChild(ce.createRange.call(this,"seek",{id:"plyr-seek-".concat(e.id)})),n.appendChild(ce.createProgress.call(this,"buffer")),this.config.tooltips.seek){var a=C("span",{class:this.config.classNames.tooltip},"00:00");n.appendChild(a),this.elements.display.seekTooltip=a}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(ce.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(ce.createTime.call(this,"duration")),this.config.controls.includes("mute")||this.config.controls.includes("volume")){var s=C("div",{class:"plyr__volume"});if(this.config.controls.includes("mute")&&s.appendChild(ce.createButton.call(this,"mute")),this.config.controls.includes("volume")){var o={max:1,step:.05,value:this.config.volume};s.appendChild(ce.createRange.call(this,"volume",Q(o,{id:"plyr-volume-".concat(e.id)}))),this.elements.volume=s}i.appendChild(s)}if(this.config.controls.includes("captions")&&i.appendChild(ce.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!p.empty(this.config.settings)){var r=C("div",{class:"plyr__menu",hidden:""});r.appendChild(ce.createButton.call(this,"settings",{"aria-haspopup":!0,"aria-controls":"plyr-settings-".concat(e.id),"aria-expanded":!1}));var l=C("div",{class:"plyr__menu__container",id:"plyr-settings-".concat(e.id),hidden:""}),c=C("div"),u=C("div",{id:"plyr-settings-".concat(e.id,"-home")}),d=C("div",{role:"menu"});u.appendChild(d),c.appendChild(u),this.elements.settings.panels.home=u,this.config.settings.forEach(function(i){var n=C("button",Q(N(t.config.selectors.buttons.settings),{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--forward"),role:"menuitem","aria-haspopup":!0,hidden:""}));ce.bindMenuItemShortcuts.call(t,n,i),y(n,"click",function(){ce.showMenuPanel.call(t,i,!1)});var a=C("span",null,te(i,t.config)),s=C("span",{class:t.config.classNames.menu.value});s.innerHTML=e[i],a.appendChild(s),n.appendChild(a),d.appendChild(n);var o=C("div",{id:"plyr-settings-".concat(e.id,"-").concat(i),hidden:""}),r=C("button",{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--back")});r.appendChild(C("span",{"aria-hidden":!0},te(i,t.config))),r.appendChild(C("span",{class:t.config.classNames.hidden},te("menuBack",t.config))),y(o,"keydown",function(e){37===e.which&&(e.preventDefault(),e.stopPropagation(),ce.showMenuPanel.call(t,"home",!0))},!1),y(r,"click",function(){ce.showMenuPanel.call(t,"home",!1)}),o.appendChild(r),o.appendChild(C("div",{role:"menu"})),c.appendChild(o),t.elements.settings.buttons[i]=n,t.elements.settings.panels[i]=o}),l.appendChild(c),r.appendChild(l),i.appendChild(r),this.elements.settings.popup=l,this.elements.settings.menu=r}if(this.config.controls.includes("pip")&&z.pip&&i.appendChild(ce.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&z.airplay&&i.appendChild(ce.createButton.call(this,"airplay")),this.config.controls.includes("download")){var h={element:"a",href:this.download,target:"_blank"},m=this.config.urls.download;!p.url(m)&&this.isEmbed&&Q(h,{icon:"logo-".concat(this.provider),label:this.provider}),i.appendChild(ce.createButton.call(this,"download",h))}return this.config.controls.includes("fullscreen")&&i.appendChild(ce.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(ce.createButton.call(this,"play-large")),this.elements.controls=i,this.isHTML5&&ce.setQualityMenu.call(this,W.getQualityOptions.call(this)),ce.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=ce.getIconUrl.call(this);t.cors&&ae(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;this.elements.controls=null;var n={id:this.id,seektime:this.config.seekTime,title:this.config.title},s=!0;p.function(this.config.controls)&&(this.config.controls=this.config.controls.call(this,n)),this.config.controls||(this.config.controls=[]),p.element(this.config.controls)||p.string(this.config.controls)?i=this.config.controls:(i=ce.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:he.getLabel.call(this)}),s=!1);var o,r=function(e){var t=e;return Object.entries(n).forEach(function(e){var i=a(e,2),n=i[0],s=i[1];t=X(t,"{".concat(n,"}"),s)}),t};if(s&&(p.string(this.config.controls)?i=r(i):p.element(i)&&(i.innerHTML=r(i.innerHTML))),p.string(this.config.selectors.controls.container)&&(o=document.querySelector(this.config.selectors.controls.container)),p.element(o)||(o=this.elements.container),o[p.element(i)?"insertAdjacentElement":"insertAdjacentHTML"]("afterbegin",i),p.element(this.elements.controls)||ce.findElements.call(this),!p.empty(this.elements.buttons)){var l=function(t){var i=e.config.classNames.controlPressed;Object.defineProperty(t,"pressed",{enumerable:!0,get:function(){return I(t,i)},set:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];x(t,i,e)}})};Object.values(this.elements.buttons).filter(Boolean).forEach(function(e){p.array(e)||p.nodeList(e)?Array.from(e).filter(Boolean).forEach(l):l(e)})}if(V.isEdge&&B(o),this.config.tooltips.controls){var c=this.config,u=c.classNames,d=c.selectors,h="".concat(d.controls.wrapper," ").concat(d.labels," .").concat(u.hidden),m=_.call(this,h);Array.from(m).forEach(function(t){x(t,e.config.classNames.hidden,!1),x(t,e.config.classNames.tooltip,!0)})}}};function ue(e){var t=e;if(!(arguments.length>1&&void 0!==arguments[1])||arguments[1]){var i=document.createElement("a");i.href=t,t=i.href}try{return new URL(t)}catch(e){return null}}function de(e){var t=new URLSearchParams;return p.object(e)&&Object.entries(e).forEach(function(e){var i=a(e,2),n=i[0],s=i[1];t.set(n,s)}),t}var he={setup:function(){if(this.supported.ui)if(!this.isVideo||this.isYouTube||this.isHTML5&&!z.textTracks)p.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&ce.setCaptionsMenu.call(this);else{var e,t;if(p.element(this.elements.captions)||(this.elements.captions=C("div",N(this.config.selectors.captions)),e=this.elements.captions,t=this.elements.wrapper,p.element(e)&&p.element(t)&&t.parentNode.insertBefore(e,t.nextSibling)),V.isIE&&window.URL){var i=this.media.querySelectorAll("track");Array.from(i).forEach(function(e){var t=e.getAttribute("src"),i=ue(t);null!==i&&i.hostname!==window.location.href.hostname&&["http:","https:"].includes(i.protocol)&&ne(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){E(e)})})}var n=K((navigator.languages||[navigator.language||navigator.userLanguage||"en"]).map(function(e){return e.split("-")[0]})),s=(this.storage.get("language")||this.config.captions.language||"auto").toLowerCase();if("auto"===s)s=a(n,1)[0];var o=this.storage.get("captions");if(p.boolean(o)||(o=this.config.captions.active),Object.assign(this.captions,{toggled:!1,active:o,language:s,languages:n}),this.isHTML5){var r=this.config.captions.update?"addtrack removetrack":"removetrack";y.call(this,this.media.textTracks,r,he.update.bind(this))}setTimeout(he.update.bind(this),0)}},update:function(){var e=this,t=he.getTracks.call(this,!0),i=this.captions,n=i.active,a=i.language,s=i.meta,o=i.currentTrackNode,r=Boolean(t.find(function(e){return e.language===a}));this.isHTML5&&this.isVideo&&t.filter(function(e){return!s.get(e)}).forEach(function(t){e.debug.log("Track added",t),s.set(t,{default:"showing"===t.mode}),t.mode="hidden",y.call(e,t,"cuechange",function(){return he.updateCues.call(e)})}),(r&&this.language!==a||!t.includes(o))&&(he.setLanguage.call(this,a),he.toggle.call(this,n&&r)),x(this.elements.container,this.config.classNames.captions.enabled,!p.empty(t)),(this.config.controls||[]).includes("settings")&&this.config.settings.includes("captions")&&ce.setCaptionsMenu.call(this)},toggle:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.supported.ui){var i=this.captions.toggled,n=this.config.classNames.captions.active,a=p.nullOrUndefined(e)?!i:e;if(a!==i){if(t||(this.captions.active=a,this.storage.set({captions:a})),!this.language&&a&&!t){var o=he.getTracks.call(this),r=he.findTrack.call(this,[this.captions.language].concat(s(this.captions.languages)),!0);return this.captions.language=r.language,void he.set.call(this,o.indexOf(r))}this.elements.buttons.captions&&(this.elements.buttons.captions.pressed=a),x(this.elements.container,n,a),this.captions.toggled=a,ce.updateSetting.call(this,"captions"),k.call(this,this.media,a?"captionsenabled":"captionsdisabled")}}},set:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=he.getTracks.call(this);if(-1!==e)if(p.number(e))if(e in i){if(this.captions.currentTrack!==e){this.captions.currentTrack=e;var n=i[e],a=(n||{}).language;this.captions.currentTrackNode=n,ce.updateSetting.call(this,"captions"),t||(this.captions.language=a,this.storage.set({language:a})),this.isVimeo&&this.embed.enableTextTrack(a),k.call(this,this.media,"languagechange")}he.toggle.call(this,!0,t),this.isHTML5&&this.isVideo&&he.updateCues.call(this)}else this.debug.warn("Track not found",e);else this.debug.warn("Invalid caption argument",e);else he.toggle.call(this,!1,t)},setLanguage:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(p.string(e)){var i=e.toLowerCase();this.captions.language=i;var n=he.getTracks.call(this),a=he.findTrack.call(this,[i]);he.set.call(this,n.indexOf(a),t)}else this.debug.warn("Invalid language argument",e)},getTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Array.from((this.media||{}).textTracks||[]).filter(function(i){return!e.isHTML5||t||e.captions.meta.has(i)}).filter(function(e){return["captions","subtitles"].includes(e.kind)})},findTrack:function(e){var t,i=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=he.getTracks.call(this),s=function(e){return Number((i.captions.meta.get(e)||{}).default)},o=Array.from(a).sort(function(e,t){return s(t)-s(e)});return e.every(function(e){return!(t=o.find(function(t){return t.language===e}))}),t||(n?o[0]:void 0)},getCurrentTrack:function(){return he.getTracks.call(this)[this.currentTrack]},getLabel:function(e){var t=e;return!p.track(t)&&z.textTracks&&this.captions.toggled&&(t=he.getCurrentTrack.call(this)),p.track(t)?p.empty(t.label)?p.empty(t.language)?te("enabled",this.config):e.language.toUpperCase():t.label:te("disabled",this.config)},updateCues:function(e){if(this.supported.ui)if(p.element(this.elements.captions))if(p.nullOrUndefined(e)||Array.isArray(e)){var t=e;if(!t){var i=he.getCurrentTrack.call(this);t=Array.from((i||{}).activeCues||[]).map(function(e){return e.getCueAsHTML()}).map(Z)}var n=t.map(function(e){return e.trim()}).join("\n");if(n!==this.elements.captions.innerHTML){P(this.elements.captions);var a=C("span",N(this.config.selectors.caption));a.innerHTML=n,this.elements.captions.appendChild(a),k.call(this,this.media,"cuechange")}}else this.debug.warn("updateCues: Invalid input",e);else this.debug.warn("No captions element to render to")}},me={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,playsinline:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.4.8/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:"auto",update:!1},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",seekLabel:"{currentTime} of {duration}",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",download:"Download",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",menuBack:"Go back to previous menu",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad",qualityBadge:{2160:"4K",1440:"HD",1080:"HD",720:"HD",576:"SD",480:"SD"}},urls:{download:null,vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,download:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","download","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',download:'[data-plyr="download"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress__buffer",loop:".plyr__progress__loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",caption:".plyr__caption",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",posterEnabled:"plyr__poster-enabled",ads:"plyr__ads",control:"plyr__control",controlPressed:"plyr__control--pressed",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",display:{time:"plyr__time"},menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus",previewThumbnails:{thumbContainer:"plyr__preview-thumb",thumbContainerShown:"plyr__preview-thumb--is-shown",imageContainer:"plyr__preview-thumb__image-container",timeContainer:"plyr__preview-thumb__time-container",scrubbingContainer:"plyr__preview-scrubbing",scrubbingContainerShown:"plyr__preview-scrubbing--is-shown"}},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:"",tagUrl:""},previewThumbnails:{enabled:!1,src:""},vimeo:{byline:!1,portrait:!1,title:!1,speed:!0,transparent:!1},youtube:{noCookie:!1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1}},pe="picture-in-picture",fe="inline",ge={html5:"html5",youtube:"youtube",vimeo:"vimeo"},ye={audio:"audio",video:"video"};var ve=function(){},be=function(){function t(){var i=arguments.length>0&&void 0!==arguments[0]&&arguments[0];e(this,t),this.enabled=window.console&&i,this.enabled&&this.log("Debugging enabled")}return i(t,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):ve}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):ve}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):ve}}]),t}();function ke(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;p.element(e)&&(e.pressed=this.active),k.call(this.player,this.target,this.active?"enterfullscreen":"exitfullscreen",!0),V.isIos||function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(p.element(e)){var i=_.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),n=i[0],a=i[i.length-1];g.call(this,this.elements.container,"keydown",function(e){if("Tab"===e.key&&9===e.keyCode){var t=document.activeElement;t!==a||e.shiftKey?t===n&&e.shiftKey&&(a.focus(),e.preventDefault()):(n.focus(),e.preventDefault())}},t,!1)}}.call(this.player,this.target,this.active)}}function we(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(t?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=t?"hidden":"",x(this.target,this.player.config.classNames.fullscreen.fallback,t),V.isIos){var i=document.head.querySelector('meta[name="viewport"]'),n="viewport-fit=cover";i||(i=document.createElement("meta")).setAttribute("name","viewport");var a=p.string(i.content)&&i.content.includes(n);t?(this.cleanupViewport=!a,a||(i.content+=",".concat(n))):this.cleanupViewport&&(i.content=i.content.split(",").filter(function(e){return e.trim()!==n}).join(",")),setTimeout(function(){return B(e.target)},100)}ke.call(this)}var Te=function(){function t(i){var n=this;e(this,t),this.player=i,this.prefix=t.prefix,this.property=t.property,this.scrollPosition={x:0,y:0},this.forceFallback="force"===i.config.fullscreen.fallback,y.call(this.player,document,"ms"===this.prefix?"MSFullscreenChange":"".concat(this.prefix,"fullscreenchange"),function(){ke.call(n)}),y.call(this.player,this.player.elements.container,"dblclick",function(e){p.element(n.player.elements.controls)&&n.player.elements.controls.contains(e.target)||n.toggle()}),this.update()}return i(t,[{key:"update",value:function(){var e;this.enabled?(e=this.forceFallback?"Fallback (forced)":t.native?"Native":"Fallback",this.player.debug.log("".concat(e," fullscreen enabled"))):this.player.debug.log("Fullscreen not supported and fallback disabled");x(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(V.isIos&&this.player.config.fullscreen.iosNative?this.target.webkitEnterFullscreen():!t.native||this.forceFallback?we.call(this,!0):this.prefix?p.empty(this.prefix)||this.target["".concat(this.prefix,"Request").concat(this.property)]():this.target.requestFullscreen())}},{key:"exit",value:function(){if(this.enabled)if(V.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(!t.native||this.forceFallback)we.call(this,!1);else if(this.prefix){if(!p.empty(this.prefix)){var e="moz"===this.prefix?"Cancel":"Exit";document["".concat(this.prefix).concat(e).concat(this.property)]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"usingNative",get:function(){return t.native&&!this.forceFallback}},{key:"enabled",get:function(){return(t.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(!t.native||this.forceFallback?I(this.target,this.player.config.classNames.fullscreen.fallback):(this.prefix?document["".concat(this.prefix).concat(this.property,"Element")]:document.fullscreenElement)===this.target)}},{key:"target",get:function(){return V.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(p.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!p.function(document["".concat(t,"ExitFullscreen")])&&!p.function(document["".concat(t,"CancelFullScreen")]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),t}();function Ce(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return new Promise(function(i,n){var a=new Image,s=function(){delete a.onload,delete a.onerror,(a.naturalWidth>=t?i:n)(a)};Object.assign(a,{onload:s,onerror:s,src:e})})}var Ae={addStyleHook:function(){x(this.elements.container,this.config.selectors.container.replace(".",""),!0),x(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for ".concat(this.provider," ").concat(this.type)),void Ae.toggleNativeControls.call(this,!0);p.element(this.elements.controls)||(ce.inject.call(this),this.listeners.controls()),Ae.toggleNativeControls.call(this),this.isHTML5&&he.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,ce.updateVolume.call(this),ce.timeUpdate.call(this),Ae.checkPlaying.call(this),x(this.elements.container,this.config.classNames.pip.supported,z.pip&&this.isHTML5&&this.isVideo),x(this.elements.container,this.config.classNames.airplay.supported,z.airplay&&this.isHTML5),x(this.elements.container,this.config.classNames.isIos,V.isIos),x(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){k.call(e,e.media,"ready")},0),Ae.setTitle.call(this),this.poster&&Ae.setPoster.call(this,this.poster,!1).catch(function(){}),this.config.duration&&ce.durationUpdate.call(this)},setTitle:function(){var e=te("play",this.config);if(p.string(this.config.title)&&!p.empty(this.config.title)&&(e+=", ".concat(this.config.title)),Array.from(this.elements.buttons.play||[]).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=O.call(this,"iframe");if(!p.element(t))return;var i=p.empty(this.config.title)?"video":this.config.title,n=te("frameTitle",this.config);t.setAttribute("title",n.replace("{title}",i))}},togglePoster:function(e){x(this.elements.container,this.config.classNames.posterEnabled,e)},setPoster:function(e){var t=this;return arguments.length>1&&void 0!==arguments[1]&&!arguments[1]||!this.poster?(this.media.setAttribute("poster",e),function(){var e=this;return new Promise(function(t){return e.ready?setTimeout(t,0):y.call(e,e.elements.container,"ready",t)}).then(function(){})}.call(this).then(function(){return Ce(e)}).catch(function(i){throw e===t.poster&&Ae.togglePoster.call(t,!1),i}).then(function(){if(e!==t.poster)throw new Error("setPoster cancelled by later call to setPoster")}).then(function(){return Object.assign(t.elements.poster.style,{backgroundImage:"url('".concat(e,"')"),backgroundSize:""}),Ae.togglePoster.call(t,!0),e})):Promise.reject(new Error("Poster already set"))},checkPlaying:function(e){var t=this;x(this.elements.container,this.config.classNames.playing,this.playing),x(this.elements.container,this.config.classNames.paused,this.paused),x(this.elements.container,this.config.classNames.stopped,this.stopped),Array.from(this.elements.buttons.play||[]).forEach(function(e){e.pressed=t.playing}),p.event(e)&&"timeupdate"===e.type||Ae.toggleControls.call(this)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){x(t.elements.container,t.config.classNames.loading,t.loading),Ae.toggleControls.call(t)},this.loading?250:0)},toggleControls:function(e){var t=this.elements.controls;if(t&&this.config.hideControls){var i=this.touch&&this.lastSeekTime+2e3>Date.now();this.toggleControls(Boolean(e||this.loading||this.paused||t.pressed||t.hover||i))}}};function Ee(e){var t=e;p.string(t)||p.nullOrUndefined(this.embed)||(t=this.embed.ratio),p.string(t)||(t=this.config.ratio);var i=a(t.split(":").map(Number),2),n=100/i[0]*i[1];if(this.elements.wrapper.style.paddingBottom="".concat(n,"%"),this.isVimeo&&this.supported.ui){var s=(240-n)/4.8;this.media.style.transform="translateY(-".concat(s,"%)")}return{padding:n,ratio:t}}var Pe=function(){function t(i){e(this,t),this.player=i,this.lastKey=null,this.focusTimer=null,this.lastKeyDown=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.setTabFocus=this.setTabFocus.bind(this),this.firstTouch=this.firstTouch.bind(this)}return i(t,[{key:"handleKey",value:function(e){var t=this.player,i=t.elements,n=e.keyCode?e.keyCode:e.which,a="keydown"===e.type,s=a&&n===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&p.number(n)){if(a){var o=document.activeElement;if(p.element(o)){var r=t.config.selectors.editable;if(o!==i.inputs.seek&&L(o,r))return;if(32===e.which&&L(o,'button, [role^="menuitem"]'))return}switch([32,37,38,39,40,48,49,50,51,52,53,54,56,57,67,70,73,75,76,77,79].includes(n)&&(e.preventDefault(),e.stopPropagation()),n){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:s||(t.currentTime=t.duration/10*(n-48));break;case 32:case 75:s||t.togglePlay();break;case 38:t.increaseVolume(.1);break;case 40:t.decreaseVolume(.1);break;case 77:s||(t.muted=!t.muted);break;case 39:t.forward();break;case 37:t.rewind();break;case 70:t.fullscreen.toggle();break;case 67:s||t.toggleCaptions();break;case 76:t.loop=!t.loop}27===n&&!t.fullscreen.usingNative&&t.fullscreen.active&&t.fullscreen.toggle(),this.lastKey=n}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){ce.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){var e=this.player,t=e.elements;e.touch=!0,x(t.container,e.config.classNames.isTouch,!0)}},{key:"setTabFocus",value:function(e){var t=this.player,i=t.elements;if(clearTimeout(this.focusTimer),"keydown"!==e.type||9===e.which){"keydown"===e.type&&(this.lastKeyDown=e.timeStamp);var n,a=e.timeStamp-this.lastKeyDown<=20;if("focus"!==e.type||a)n=t.config.classNames.tabFocus,x(_.call(t,".".concat(n)),n,!1),this.focusTimer=setTimeout(function(){var e=document.activeElement;i.container.contains(e)&&x(document.activeElement,t.config.classNames.tabFocus,!0)},10)}}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.player;t.config.keyboard.global&&g.call(t,window,"keydown keyup",this.handleKey,e,!1),g.call(t,document.body,"click",this.toggleMenu,e),b.call(t,document.body,"touchstart",this.firstTouch),g.call(t,document.body,"keydown focus blur",this.setTabFocus,e,!1,!0)}},{key:"container",value:function(){var e=this.player,t=e.config,i=e.elements,n=e.timers;!t.keyboard.global&&t.keyboard.focused&&y.call(e,i.container,"keydown keyup",this.handleKey,!1),y.call(e,i.container,"mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",function(t){var a=i.controls;a&&"enterfullscreen"===t.type&&(a.pressed=!1,a.hover=!1);var s=0;["touchstart","touchmove","mousemove"].includes(t.type)&&(Ae.toggleControls.call(e,!0),s=e.touch?3e3:2e3),clearTimeout(n.controls),n.controls=setTimeout(function(){return Ae.toggleControls.call(e,!1)},s)});var s=function(t){if(!t)return Ee.call(e);var n=i.container.getBoundingClientRect(),a=n.width,s=n.height;return Ee.call(e,"".concat(a,":").concat(s))},o=function(){window.clearTimeout(n.resized),n.resized=window.setTimeout(s,50)};y.call(e,i.container,"enterfullscreen exitfullscreen",function(t){var n=e.fullscreen,r=n.target,l=n.usingNative;if(e.isEmbed&&r===i.container){var c="enterfullscreen"===t.type,u=s(c);u.padding;!function(t,i,n){if(e.isVimeo){var s=e.elements.wrapper.firstChild,o=a(t.split(":").map(Number),2)[1],r=a(e.embed.ratio.split(":").map(Number),2),l=r[0],c=r[1];s.style.maxWidth=n?"".concat(o/c*l,"px"):null,s.style.margin=n?"0 auto":null}}(u.ratio,0,c),l||(c?y.call(e,window,"resize",o):v.call(e,window,"resize",o))}})}},{key:"media",value:function(){var e=this,t=this.player,i=t.elements;if(y.call(t,t.media,"timeupdate seeking seeked",function(e){return ce.timeUpdate.call(t,e)}),y.call(t,t.media,"durationchange loadeddata loadedmetadata",function(e){return ce.durationUpdate.call(t,e)}),y.call(t,t.media,"canplay loadeddata",function(){M(i.volume,!t.hasAudio),M(i.buttons.mute,!t.hasAudio)}),y.call(t,t.media,"ended",function(){t.isHTML5&&t.isVideo&&t.config.resetOnEnd&&t.restart()}),y.call(t,t.media,"progress playing seeking seeked",function(e){return ce.updateProgress.call(t,e)}),y.call(t,t.media,"volumechange",function(e){return ce.updateVolume.call(t,e)}),y.call(t,t.media,"playing play pause ended emptied timeupdate",function(e){return Ae.checkPlaying.call(t,e)}),y.call(t,t.media,"waiting canplay seeked playing",function(e){return Ae.checkLoading.call(t,e)}),y.call(t,t.media,"playing",function(){t.ads&&t.ads.enabled&&!t.ads.initialized&&t.ads.managerPromise.then(function(){return t.ads.play()}).catch(function(){return t.play()})}),t.supported.ui&&t.config.clickToPlay&&!t.isAudio){var n=O.call(t,".".concat(t.config.classNames.video));if(!p.element(n))return;y.call(t,i.container,"click",function(a){([i.container,n].includes(a.target)||n.contains(a.target))&&(t.touch&&t.config.hideControls||(t.ended?(e.proxy(a,t.restart,"restart"),e.proxy(a,t.play,"play")):e.proxy(a,t.togglePlay,"play")))})}t.supported.ui&&t.config.disableContextMenu&&y.call(t,i.wrapper,"contextmenu",function(e){e.preventDefault()},!1),y.call(t,t.media,"volumechange",function(){t.storage.set({volume:t.volume,muted:t.muted})}),y.call(t,t.media,"ratechange",function(){ce.updateSetting.call(t,"speed"),t.storage.set({speed:t.speed})}),y.call(t,t.media,"qualitychange",function(e){ce.updateSetting.call(t,"quality",null,e.detail.quality)}),y.call(t,t.media,"ready qualitychange",function(){ce.setDownloadLink.call(t)});var a=t.config.events.concat(["keyup","keydown"]).join(" ");y.call(t,t.media,a,function(e){var n=e.detail,a=void 0===n?{}:n;"error"===e.type&&(a=t.media.error),k.call(t,i.container,e.type,!0,a)})}},{key:"proxy",value:function(e,t,i){var n=this.player,a=n.config.listeners[i],s=!0;p.function(a)&&(s=a.call(n,e)),s&&p.function(t)&&t.call(n,e)}},{key:"bind",value:function(e,t,i,n){var a=this,s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=this.player,r=o.config.listeners[n],l=p.function(r);y.call(o,e,t,function(e){return a.proxy(e,i,n)},s&&!l)}},{key:"controls",value:function(){var e=this,t=this.player,i=t.elements,n=V.isIE?"change":"input";if(i.buttons.play&&Array.from(i.buttons.play).forEach(function(i){e.bind(i,"click",t.togglePlay,"play")}),this.bind(i.buttons.restart,"click",t.restart,"restart"),this.bind(i.buttons.rewind,"click",t.rewind,"rewind"),this.bind(i.buttons.fastForward,"click",t.forward,"fastForward"),this.bind(i.buttons.mute,"click",function(){t.muted=!t.muted},"mute"),this.bind(i.buttons.captions,"click",function(){return t.toggleCaptions()}),this.bind(i.buttons.download,"click",function(){k.call(t,t.media,"download")},"download"),this.bind(i.buttons.fullscreen,"click",function(){t.fullscreen.toggle()},"fullscreen"),this.bind(i.buttons.pip,"click",function(){t.pip="toggle"},"pip"),this.bind(i.buttons.airplay,"click",t.airplay,"airplay"),this.bind(i.buttons.settings,"click",function(e){e.stopPropagation(),ce.toggleMenu.call(t,e)}),this.bind(i.buttons.settings,"keyup",function(e){var i=e.which;[13,32].includes(i)&&(13!==i?(e.preventDefault(),e.stopPropagation(),ce.toggleMenu.call(t,e)):ce.focusFirstMenuItem.call(t,null,!0))},null,!1),this.bind(i.settings.menu,"keydown",function(e){27===e.which&&ce.toggleMenu.call(t,e)}),this.bind(i.inputs.seek,"mousedown mousemove",function(e){var t=i.progress.getBoundingClientRect(),n=100/t.width*(e.pageX-t.left);e.currentTarget.setAttribute("seek-value",n)}),this.bind(i.inputs.seek,"mousedown mouseup keydown keyup touchstart touchend",function(e){var i=e.currentTarget,n=e.keyCode?e.keyCode:e.which;if(!p.keyboardEvent(e)||39===n||37===n){t.lastSeekTime=Date.now();var a=i.hasAttribute("play-on-seeked"),s=["mouseup","touchend","keyup"].includes(e.type);a&&s?(i.removeAttribute("play-on-seeked"),t.play()):!s&&t.playing&&(i.setAttribute("play-on-seeked",""),t.pause())}}),V.isIos){var s=_.call(t,'input[type="range"]');Array.from(s).forEach(function(t){return e.bind(t,n,function(e){return B(e.target)})})}this.bind(i.inputs.seek,n,function(e){var i=e.currentTarget,n=i.getAttribute("seek-value");p.empty(n)&&(n=i.value),i.removeAttribute("seek-value"),t.currentTime=n/i.max*t.duration},"seek"),this.bind(i.progress,"mouseenter mouseleave mousemove",function(e){return ce.updateSeekTooltip.call(t,e)}),this.bind(i.progress,"mousemove touchmove",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.startMove(e)}),this.bind(i.progress,"mouseleave click",function(){var e=t.previewThumbnails;e&&e.loaded&&e.endMove(!1,!0)}),this.bind(i.progress,"mousedown touchstart",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.startScrubbing(e)}),this.bind(i.progress,"mouseup touchend",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.endScrubbing(e)}),V.isWebkit&&Array.from(_.call(t,'input[type="range"]')).forEach(function(i){e.bind(i,"input",function(e){return ce.updateRangeFill.call(t,e.target)})}),t.config.toggleInvert&&!p.element(i.display.duration)&&this.bind(i.display.currentTime,"click",function(){0!==t.currentTime&&(t.config.invertTime=!t.config.invertTime,ce.timeUpdate.call(t))}),this.bind(i.inputs.volume,n,function(e){t.volume=e.target.value},"volume"),this.bind(i.controls,"mouseenter mouseleave",function(e){i.controls.hover=!t.touch&&"mouseenter"===e.type}),this.bind(i.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){i.controls.pressed=["mousedown","touchstart"].includes(e.type)}),this.bind(i.controls,"focusin",function(){var i=t.config,n=t.elements,a=t.timers;x(n.controls,i.classNames.noTransition,!0),Ae.toggleControls.call(t,!0),setTimeout(function(){x(n.controls,i.classNames.noTransition,!1)},0);var s=e.touch?3e3:4e3;clearTimeout(a.controls),a.controls=setTimeout(function(){return Ae.toggleControls.call(t,!1)},s)}),this.bind(i.inputs.volume,"wheel",function(e){var i=e.webkitDirectionInvertedFromDevice,n=a([e.deltaX,-e.deltaY].map(function(e){return i?-e:e}),2),s=n[0],o=n[1],r=Math.sign(Math.abs(s)>Math.abs(o)?s:o);t.increaseVolume(r/50);var l=t.media.volume;(1===r&&l<1||-1===r&&l>0)&&e.preventDefault()},"volume",!1)}}]),t}();"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var Se,Ne=(function(e,t){e.exports=function(){var e=function(){},t={},i={},n={};function a(e,t){if(e){var a=n[e];if(i[e]=t,a)for(;a.length;)a[0](e,t),a.splice(0,1)}}function s(t,i){t.call&&(t={success:t}),i.length?(t.error||e)(i):(t.success||e)(t)}function o(t,i,n,a){var s,r,l=document,c=n.async,u=(n.numRetries||0)+1,d=n.before||e,h=t.replace(/^(css|img)!/,"");a=a||0,/(^css!|\.css$)/.test(t)?(s=!0,(r=l.createElement("link")).rel="stylesheet",r.href=h):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(r=l.createElement("img")).src=h:((r=l.createElement("script")).src=t,r.async=void 0===c||c),r.onload=r.onerror=r.onbeforeload=function(e){var l=e.type[0];if(s&&"hideFocus"in r)try{r.sheet.cssText.length||(l="e")}catch(e){18!=e.code&&(l="e")}if("e"==l&&(a+=1)<u)return o(t,i,n,a);i(t,l,e.defaultPrevented)},!1!==d(t,r)&&l.head.appendChild(r)}function r(e,i,n){var r,l;if(i&&i.trim&&(r=i),l=(r?n:i)||{},r){if(r in t)throw"LoadJS";t[r]=!0}!function(e,t,i){var n,a,s=(e=e.push?e:[e]).length,r=s,l=[];for(n=function(e,i,n){if("e"==i&&l.push(e),"b"==i){if(!n)return;l.push(e)}--s||t(l)},a=0;a<r;a++)o(e[a],n,i)}(e,function(e){s(l,e),a(r,e)},l)}return r.ready=function(e,t){return function(e,t){e=e.push?e:[e];var a,s,o,r=[],l=e.length,c=l;for(a=function(e,i){i.length&&r.push(e),--c||t(r)};l--;)s=e[l],(o=i[s])?a(s,o):(n[s]=n[s]||[]).push(a)}(e,function(e){s(t,e)}),r},r.done=function(e){a(e,[])},r.reset=function(){t={},i={},n={}},r.isDefined=function(e){return e in t},r}()}(Se={exports:{}},Se.exports),Se.exports);function Me(e){return new Promise(function(t,i){Ne(e,{success:t,error:i})})}function xe(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,k.call(this,this.media,e?"play":"pause"))}var Ie={setup:function(){var e=this;x(this.elements.wrapper,this.config.classNames.embed,!0),Ee.call(this),p.object(window.Vimeo)?Ie.ready.call(this):Me(this.config.urls.vimeo.sdk).then(function(){Ie.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},ready:function(){var e=this,t=this,i=t.config.vimeo,n=de(Q({},{loop:t.config.loop.active,autoplay:t.autoplay,muted:t.muted,gesture:"media",playsinline:!this.config.fullscreen.iosNative},i)),s=t.media.getAttribute("src");p.empty(s)&&(s=t.media.getAttribute(t.config.attributes.embed.id));var o,r=(o=s,p.empty(o)?null:p.number(Number(o))?o:o.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:o),l=C("iframe"),c=J(t.config.urls.vimeo.iframe,r,n);l.setAttribute("src",c),l.setAttribute("allowfullscreen",""),l.setAttribute("allowtransparency",""),l.setAttribute("allow","autoplay");var u=C("div",{poster:t.poster,class:t.config.classNames.embedContainer});u.appendChild(l),t.media=S(u,t.media),ne(J(t.config.urls.vimeo.api,r),"json").then(function(e){if(!p.empty(e)){var i=new URL(e[0].thumbnail_large);i.pathname="".concat(i.pathname.split("_")[0],".jpg"),Ae.setPoster.call(t,i.href).catch(function(){})}}),t.embed=new window.Vimeo.Player(l,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){return xe.call(t,!0),t.embed.play()},t.media.pause=function(){return xe.call(t,!1),t.embed.pause()},t.media.stop=function(){t.pause(),t.currentTime=0};var d=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return d},set:function(e){var i=t.embed,n=t.media,a=t.paused,s=t.volume,o=a&&!i.hasPlayed;n.seeking=!0,k.call(t,n,"seeking"),Promise.resolve(o&&i.setVolume(0)).then(function(){return i.setCurrentTime(e)}).then(function(){return o&&i.pause()}).then(function(){return o&&i.setVolume(s)}).catch(function(){})}});var h=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return h},set:function(e){t.embed.setPlaybackRate(e).then(function(){h=e,k.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&ce.setSpeedMenu.call(t,[])})}});var m=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return m},set:function(e){t.embed.setVolume(e).then(function(){m=e,k.call(t,t.media,"volumechange")})}});var f=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return f},set:function(e){var i=!!p.boolean(e)&&e;t.embed.setVolume(i?0:t.config.volume).then(function(){f=i,k.call(t,t.media,"volumechange")})}});var g,y=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return y},set:function(e){var i=p.boolean(e)?e:t.config.loop.active;t.embed.setLoop(i).then(function(){y=i})}}),t.embed.getVideoUrl().then(function(e){g=e,ce.setDownloadLink.call(t)}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return g}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(i){var n=a(i,2),s=n[0],o=n[1];t.embed.ratio="".concat(s,":").concat(o),Ee.call(e,t.embed.ratio)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(i){t.config.title=i,Ae.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){d=e,k.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,k.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,he.setup.call(t)}),t.embed.on("cuechange",function(e){var i=e.cues,n=(void 0===i?[]:i).map(function(e){return t=e.text,i=document.createDocumentFragment(),n=document.createElement("div"),i.appendChild(n),n.innerHTML=t,i.firstChild.innerText;var t,i,n});he.updateCues.call(t,n)}),t.embed.on("loaded",function(){(t.embed.getPaused().then(function(e){xe.call(t,!e),e||k.call(t,t.media,"playing")}),p.element(t.embed.element)&&t.supported.ui)&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){xe.call(t,!0),k.call(t,t.media,"playing")}),t.embed.on("pause",function(){xe.call(t,!1)}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,d=e.seconds,k.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,k.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&k.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,k.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,k.call(t,t.media,"seeked")}),t.embed.on("ended",function(){t.media.paused=!0,k.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,k.call(t,t.media,"error")}),setTimeout(function(){return Ae.build.call(t)},0)}};function Le(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,k.call(this,this.media,e?"play":"pause"))}var _e,Oe={setup:function(){var e=this;x(this.elements.wrapper,this.config.classNames.embed,!0),Ee.call(this),p.object(window.YT)&&p.function(window.YT.Player)?Oe.ready.call(this):(Me(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){Oe.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(p.function(this.embed.getVideoData)){var i=this.embed.getVideoData().title;if(p.empty(i))return this.config.title=i,void Ae.setTitle.call(this)}var n=this.config.keys.google;p.string(n)&&!p.empty(n)&&ne(J(this.config.urls.youtube.api,e,n)).then(function(e){p.object(e)&&(t.config.title=e.items[0].snippet.title,Ae.setTitle.call(t))}).catch(function(){})},ready:function(){var e=this,t=e.media.getAttribute("id");if(p.empty(t)||!t.startsWith("youtube-")){var i=e.media.getAttribute("src");p.empty(i)&&(i=e.media.getAttribute(this.config.attributes.embed.id));var n,a,s=(n=i,p.empty(n)?null:n.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:n),o=(a=e.provider,"".concat(a,"-").concat(Math.floor(1e4*Math.random()))),r=C("div",{id:o,poster:e.poster});e.media=S(r,e.media);var l=function(e){return"https://img.youtube.com/vi/".concat(s,"/").concat(e,"default.jpg")};Ce(l("maxres"),121).catch(function(){return Ce(l("sd"),121)}).catch(function(){return Ce(l("hq"))}).then(function(t){return Ae.setPoster.call(e,t.src)}).then(function(t){t.includes("maxres")||(e.elements.poster.style.backgroundSize="cover")}).catch(function(){});var c=e.config.youtube;e.embed=new window.YT.Player(o,{videoId:s,host:c.noCookie?"https://www.youtube-nocookie.com":void 0,playerVars:Q({},{autoplay:e.config.autoplay?1:0,hl:e.config.hl,controls:e.supported.ui?0:1,disablekb:1,playsinline:e.config.fullscreen.iosNative?0:1,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language,widget_referrer:window?window.location.href:null},c),events:{onError:function(t){if(!e.media.error){var i=t.data,n={2:"The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.",5:"The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",100:"The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.",101:"The owner of the requested video does not allow it to be played in embedded players.",150:"The owner of the requested video does not allow it to be played in embedded players."}[i]||"An unknown error occured";e.media.error={code:i,message:n},k.call(e,e.media,"error")}},onPlaybackRateChange:function(t){var i=t.target;e.media.playbackRate=i.getPlaybackRate(),k.call(e,e.media,"ratechange")},onReady:function(t){if(!p.function(e.media.play)){var i=t.target;Oe.getTitle.call(e,s),e.media.play=function(){Le.call(e,!0),i.playVideo()},e.media.pause=function(){Le.call(e,!1),i.pauseVideo()},e.media.stop=function(){i.stopVideo()},e.media.duration=i.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(t){e.paused&&!e.embed.hasPlayed&&e.embed.mute(),e.media.seeking=!0,k.call(e,e.media,"seeking"),i.seekTo(t)}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}});var n=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return n},set:function(t){n=t,i.setVolume(100*n),k.call(e,e.media,"volumechange")}});var a=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return a},set:function(t){var n=p.boolean(t)?t:a;a=n,i[n?"mute":"unMute"](),k.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=i.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),k.call(e,e.media,"timeupdate"),k.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=i.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&k.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),k.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return Ae.build.call(e)},50)}},onStateChange:function(t){var i=t.target;switch(clearInterval(e.timers.playing),e.media.seeking&&[1,2].includes(t.data)&&(e.media.seeking=!1,k.call(e,e.media,"seeked")),t.data){case-1:k.call(e,e.media,"timeupdate"),e.media.buffered=i.getVideoLoadedFraction(),k.call(e,e.media,"progress");break;case 0:Le.call(e,!1),e.media.loop?(i.stopVideo(),i.playVideo()):k.call(e,e.media,"ended");break;case 1:e.media.paused&&!e.embed.hasPlayed?e.media.pause():(Le.call(e,!0),k.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){k.call(e,e.media,"timeupdate")},50),e.media.duration!==i.getDuration()&&(e.media.duration=i.getDuration(),k.call(e,e.media,"durationchange")));break;case 2:e.muted||e.embed.unMute(),Le.call(e,!1)}k.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},je={setup:function(){this.media?(x(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),x(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&x(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=C("div",{class:this.config.classNames.video}),w(this.media,this.elements.wrapper),this.elements.poster=C("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isHTML5?W.extend.call(this):this.isYouTube?Oe.setup.call(this):this.isVimeo&&Ie.setup.call(this)):this.debug.warn("No media element found!")}},qe=function(){function t(i){var n=this;e(this,t),this.player=i,this.config=i.config.ads,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){n.on("loaded",e),n.on("error",t)}),this.load()}return i(t,[{key:"load",value:function(){var e=this;this.enabled&&(p.object(window.google)&&p.object(window.google.ima)?this.ready():Me(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=C("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var i=new google.ima.AdsRequest;i.adTagUrl=this.tagUrl,i.linearAdSlotWidth=t.offsetWidth,i.linearAdSlotHeight=t.offsetHeight,i.nonLinearAdSlotWidth=t.offsetWidth,i.nonLinearAdSlotHeight=t.offsetHeight,i.forceNonLinearFullSlot=!1,i.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(i)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=le(Math.max(e.manager.getRemainingTime(),0)),i="".concat(te("advertisement",e.player.config)," - ").concat(t);e.elements.container.setAttribute("data-badge-text",i)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this;if(this.enabled){var i=new google.ima.AdsRenderingSettings;i.restoreCustomPlaybackStateOnAdBreakComplete=!0,i.enablePreloading=!0,this.manager=e.getAdsManager(this.player,i),this.cuePoints=this.manager.getCuePoints(),p.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var i=t.player.elements.progress;if(p.element(i)){var n=100/t.player.duration*e,a=C("span",{class:t.player.config.classNames.cues});a.style.left="".concat(n.toString(),"%"),i.appendChild(a)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}}},{key:"onAdEvent",value:function(e){var t=this,i=this.player.elements.container,n=e.getAd(),a=e.getAdData(),s=function(e){var i="ads".concat(e.replace(/_/g,"").toLowerCase());k.call(t.player,t.player.media,i)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),s(e.type),this.pollCountdown(!0),n.isLinear()||(n.width=i.offsetWidth,n.height=i.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:s(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:s(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:s(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:s(e.type);break;case google.ima.AdEvent.Type.LOG:a.adError&&this.player.debug.warn("Non-fatal ad error: ".concat(a.adError.getMessage()))}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e,t=this,i=this.player.elements.container;this.player.on("ended",function(){t.loader.contentComplete()}),this.player.on("timeupdate",function(){e=t.player.currentTime}),this.player.on("seeked",function(){var i=t.player.currentTime;p.empty(t.cuePoints)||t.cuePoints.forEach(function(n,a){e<n&&n<i&&(t.manager.discardAdBreak(),t.cuePoints.splice(a,1))})}),window.addEventListener("resize",function(){t.manager&&t.manager.resize(i.offsetWidth,i.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,i=arguments.length,n=new Array(i>1?i-1:0),a=1;a<i;a++)n[a-1]=arguments[a];var s=this.events[e];p.array(s)&&s.forEach(function(e){p.function(e)&&e.apply(t,n)})}},{key:"on",value:function(e,t){return p.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var i=this;this.player.debug.log("Safety timer invoked from: ".concat(t)),this.safetyTimer=setTimeout(function(){i.cancel(),i.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){p.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: ".concat(e)),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){var e=this.config;return this.player.isHTML5&&this.player.isVideo&&e.enabled&&(!p.empty(e.publisherId)||p.url(e.tagUrl))}},{key:"tagUrl",get:function(){var e=this.config;if(p.url(e.tagUrl))return e.tagUrl;var t={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:window.location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"".concat("https://go.aniview.com/api/adserver6/vast/","?").concat(de(t))}}]),t}(),De=function(){function t(i){e(this,t),this.player=i,this.thumbnails=[],this.loaded=!1,this.lastMouseMoveTime=Date.now(),this.mouseDown=!1,this.loadedImages=[],this.elements={thumb:{},scrubbing:{}},this.load()}return i(t,[{key:"load",value:function(){var e=this;this.player.elements.display.seekTooltip&&(this.player.elements.display.seekTooltip.hidden=this.enabled),this.enabled&&this.getThumbnails().then(function(){e.render(),e.determineContainerAutoSizing(),e.loaded=!0})}},{key:"getThumbnails",value:function(){var e=this;return new Promise(function(t){var i=e.player.config.previewThumbnails.src;if(p.empty(i))throw new Error("Missing previewThumbnails.src config attribute");var n=(p.string(i)?[i]:i).map(function(t){return e.getThumbnail(t)});Promise.all(n).then(function(){e.thumbnails.sort(function(e,t){return e.height-t.height}),e.player.debug.log("Preview thumbnails",e.thumbnails),t()})})}},{key:"getThumbnail",value:function(e){var t=this;return new Promise(function(i){ne(e).then(function(n){var s,o,r={frames:(s=n,o=[],s.split(/\r\n\r\n|\n\n|\r\r/).forEach(function(e){var t={};e.split(/\r\n|\n|\r/).forEach(function(e){if(p.number(t.startTime)){if(!p.empty(e.trim())&&p.empty(t.text)){var i=e.trim().split("#xywh="),n=a(i,1);if(t.text=n[0],i[1]){var s=a(i[1].split(","),4);t.x=s[0],t.y=s[1],t.w=s[2],t.h=s[3]}}}else{var o=e.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);o&&(t.startTime=60*Number(o[1])*60+60*Number(o[2])+Number(o[3])+Number("0.".concat(o[4])),t.endTime=60*Number(o[6])*60+60*Number(o[7])+Number(o[8])+Number("0.".concat(o[9])))}}),t.text&&o.push(t)}),o),height:null,urlPrefix:""};r.frames[0].text.startsWith("/")||(r.urlPrefix=e.substring(0,e.lastIndexOf("/")+1));var l=new Image;l.onload=function(){r.height=l.naturalHeight,r.width=l.naturalWidth,t.thumbnails.push(r),i()},l.src=r.urlPrefix+r.frames[0].text})})}},{key:"startMove",value:function(e){if(this.loaded&&p.event(e)&&["touchmove","mousemove"].includes(e.type)&&this.player.media.duration){if("touchmove"===e.type)this.seekTime=this.player.media.duration*(this.player.elements.inputs.seek.value/100);else{var t=this.player.elements.progress.getBoundingClientRect(),i=100/t.width*(e.pageX-t.left);this.seekTime=this.player.media.duration*(i/100),this.seekTime<0&&(this.seekTime=0),this.seekTime>this.player.media.duration-1&&(this.seekTime=this.player.media.duration-1),this.mousePosX=e.pageX,this.elements.thumb.time.innerText=le(this.seekTime)}this.showImageAtCurrentTime()}}},{key:"endMove",value:function(){this.toggleThumbContainer(!1,!0)}},{key:"startScrubbing",value:function(e){!1!==e.button&&0!==e.button||(this.mouseDown=!0,this.player.media.duration&&(this.toggleScrubbingContainer(!0),this.toggleThumbContainer(!1,!0),this.showImageAtCurrentTime()))}},{key:"finishScrubbing",value:function(){var e=this;this.mouseDown=!1,Math.ceil(this.lastTime)===Math.ceil(this.player.media.currentTime)?this.toggleScrubbingContainer(!1):b.call(this.player,this.player.media,"timeupdate",function(){e.mouseDown||e.toggleScrubbingContainer(!1)})}},{key:"listeners",value:function(){var e=this;this.player.on("play",function(){e.toggleThumbContainer(!1,!0)}),this.player.on("seeked",function(){e.toggleThumbContainer(!1)}),this.player.on("timeupdate",function(){e.lastTime=e.player.media.currentTime})}},{key:"render",value:function(){this.elements.thumb.container=C("div",{class:this.player.config.classNames.previewThumbnails.thumbContainer}),this.elements.thumb.imageContainer=C("div",{class:this.player.config.classNames.previewThumbnails.imageContainer}),this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);var e=C("div",{class:this.player.config.classNames.previewThumbnails.timeContainer});this.elements.thumb.time=C("span",{},"00:00"),e.appendChild(this.elements.thumb.time),this.elements.thumb.container.appendChild(e),this.player.elements.progress.appendChild(this.elements.thumb.container),this.elements.scrubbing.container=C("div",{class:this.player.config.classNames.previewThumbnails.scrubbingContainer}),this.player.elements.wrapper.appendChild(this.elements.scrubbing.container)}},{key:"showImageAtCurrentTime",value:function(){var e=this;this.mouseDown?this.setScrubbingContainerSize():(this.toggleThumbContainer(!0),this.setThumbContainerSizeAndPos());var t=this.thumbnails[0].frames.findIndex(function(t){return e.seekTime>=t.startTime&&e.seekTime<=t.endTime}),i=t>=0,n=0;this.toggleThumbContainer(i),i&&(this.thumbnails.forEach(function(i,a){e.loadedImages.includes(i.frames[t].text)&&(n=a)}),t!==this.showingThumb&&(this.showingThumb=t,this.loadImage(n)))}},{key:"loadImage",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,i=this.showingThumb,n=this.thumbnails[t],a=n.urlPrefix,s=n.frames[i],o=n.frames[i].text,r=a+o;if(this.currentImageElement&&this.currentImageElement.dataset.filename===o)this.showImage(this.currentImageElement,s,t,i,o,!1),this.currentImageElement.dataset.index=i,this.removeOldImages(this.currentImageElement);else{this.loadingImage&&this.usingSprites&&(this.loadingImage.onload=null);var l=new Image;l.src=r,l.dataset.index=i,l.dataset.filename=o,this.showingThumbFilename=o,this.player.debug.log("Loading image: ".concat(r)),l.onload=function(){return e.showImage(l,s,t,i,o,!0)},this.loadingImage=l,this.removeOldImages(l)}}},{key:"showImage",value:function(e,t,i,n,a){var s=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];this.player.debug.log("Showing thumb: ".concat(a,". num: ").concat(n,". qual: ").concat(i,". newimg: ").concat(s)),this.setImageSizeAndOffset(e,t),s&&(this.currentImageContainer.appendChild(e),this.currentImageElement=e,this.loadedImages.includes(a)||this.loadedImages.push(a)),this.preloadNearby(n,!0).then(this.preloadNearby(n,!1)).then(this.getHigherQuality(i,e,t,a))}},{key:"removeOldImages",value:function(e){var t=this;Array.from(this.currentImageContainer.children).forEach(function(i){if("img"===i.tagName.toLowerCase()){var n=t.usingSprites?500:1e3;if(i.dataset.index!==e.dataset.index&&!i.dataset.deleting){i.dataset.deleting=!0;var a=t.currentImageContainer;setTimeout(function(){a.removeChild(i),t.player.debug.log("Removing thumb: ".concat(i.dataset.filename))},n)}}})}},{key:"preloadNearby",value:function(e){var t=this,i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return new Promise(function(n){setTimeout(function(){var a=t.thumbnails[0].frames[e].text;if(t.showingThumbFilename===a){var s;s=i?t.thumbnails[0].frames.slice(e):t.thumbnails[0].frames.slice(0,e).reverse();var o=!1;s.forEach(function(e){var i=e.text;if(i!==a&&!t.loadedImages.includes(i)){o=!0,t.player.debug.log("Preloading thumb filename: ".concat(i));var s=t.thumbnails[0].urlPrefix+i,r=new Image;r.src=s,r.onload=function(){t.player.debug.log("Preloaded thumb filename: ".concat(i)),t.loadedImages.includes(i)||t.loadedImages.push(i),n()}}}),o||n()}},300)})}},{key:"getHigherQuality",value:function(e,t,i,n){var a=this;if(e<this.thumbnails.length-1){var s=t.naturalHeight;this.usingSprites&&(s=i.h),s<this.thumbContainerHeight&&setTimeout(function(){a.showingThumbFilename===n&&(a.player.debug.log("Showing higher quality thumb for: ".concat(n)),a.loadImage(e+1))},300)}}},{key:"toggleThumbContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.player.config.classNames.previewThumbnails.thumbContainerShown;this.elements.thumb.container.classList.toggle(i,e),!e&&t&&(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"toggleScrubbingContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.player.config.classNames.previewThumbnails.scrubbingContainerShown;this.elements.scrubbing.container.classList.toggle(t,e),e||(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"determineContainerAutoSizing",value:function(){this.elements.thumb.imageContainer.clientHeight>20&&(this.sizeSpecifiedInCSS=!0)}},{key:"setThumbContainerSizeAndPos",value:function(){if(!this.sizeSpecifiedInCSS){var e=Math.floor(this.thumbContainerHeight*this.thumbAspectRatio);this.elements.thumb.imageContainer.style.height="".concat(this.thumbContainerHeight,"px"),this.elements.thumb.imageContainer.style.width="".concat(e,"px")}this.setThumbContainerPos()}},{key:"setThumbContainerPos",value:function(){var e=this.player.elements.progress.getBoundingClientRect(),t=this.player.elements.container.getBoundingClientRect(),i=this.elements.thumb.container,n=t.left-e.left+10,a=t.right-e.left-i.clientWidth-10,s=this.mousePosX-e.left-i.clientWidth/2;s<n&&(s=n),s>a&&(s=a),i.style.left="".concat(s,"px")}},{key:"setScrubbingContainerSize",value:function(){this.elements.scrubbing.container.style.width="".concat(this.player.media.clientWidth,"px"),this.elements.scrubbing.container.style.height="".concat(this.player.media.clientWidth/this.thumbAspectRatio,"px")}},{key:"setImageSizeAndOffset",value:function(e,t){if(this.usingSprites){var i=this.thumbContainerHeight/t.h;e.style.height="".concat(Math.floor(e.naturalHeight*i),"px"),e.style.width="".concat(Math.floor(e.naturalWidth*i),"px"),e.style.left="-".concat(t.x*i,"px"),e.style.top="-".concat(t.y*i,"px")}}},{key:"enabled",get:function(){return this.player.isHTML5&&this.player.isVideo&&this.player.config.previewThumbnails.enabled}},{key:"currentImageContainer",get:function(){return this.mouseDown?this.elements.scrubbing.container:this.elements.thumb.imageContainer}},{key:"usingSprites",get:function(){return Object.keys(this.thumbnails[0].frames[0]).includes("w")}},{key:"thumbAspectRatio",get:function(){return this.usingSprites?this.thumbnails[0].frames[0].w/this.thumbnails[0].frames[0].h:this.thumbnails[0].width/this.thumbnails[0].height}},{key:"thumbContainerHeight",get:function(){return this.mouseDown?Math.floor(this.player.media.clientWidth/this.thumbAspectRatio):Math.floor(this.player.media.clientWidth/this.thumbAspectRatio/4)}},{key:"currentImageElement",get:function(){return this.mouseDown?this.currentScrubbingImageElement:this.currentThumbnailImageElement},set:function(e){this.mouseDown?this.currentScrubbingImageElement=e:this.currentThumbnailImageElement=e}}]),t}(),He={insertElements:function(e,t){var i=this;p.string(t)?A(e,this.media,{src:t}):p.array(t)&&t.forEach(function(t){A(e,i.media,t)})},change:function(e){var t=this;Y(e,"sources.length")?(W.cancelRequests.call(this),this.destroy.call(this,function(){t.options.quality=[],E(t.media),t.media=null,p.element(t.elements.container)&&t.elements.container.removeAttribute("class");var i=e.sources,n=e.type,s=a(i,1)[0],o=s.provider,r=void 0===o?ge.html5:o,l=s.src,c="html5"===r?n:"div",u="html5"===r?{}:{src:l};Object.assign(t,{provider:r,type:n,supported:z.check(n,r,t.config.playsinline),media:C(c,u)}),t.elements.container.appendChild(t.media),p.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),p.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),Ae.addStyleHook.call(t),t.isHTML5&&He.insertElements.call(t,"source",i),t.config.title=e.title,je.setup.call(t),t.isHTML5&&Object.keys(e).includes("tracks")&&He.insertElements.call(t,"track",e.tracks),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&Ae.build.call(t),t.isHTML5&&t.media.load(),t.previewThumbnails&&t.previewThumbnails.load(),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},Re=function(){function t(i,n){var a=this;if(e(this,t),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=z.touch,this.media=i,p.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||p.nodeList(this.media)||p.array(this.media))&&(this.media=this.media[0]),this.config=Q({},me,t.defaults,n||{},function(){try{return JSON.parse(a.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,captions:null,buttons:{},display:{},progress:{},inputs:{},settings:{popup:null,menu:null,panels:{},buttons:{}}},this.captions={active:null,currentTrack:-1,meta:new WeakMap},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new be(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",z),!p.nullOrUndefined(this.media)&&p.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(z.check().api){var s=this.media.cloneNode(!0);s.autoplay=!1,this.elements.original=s;var o=this.media.tagName.toLowerCase(),r=null,l=null;switch(o){case"div":if(r=this.media.querySelector("iframe"),p.element(r)){if(l=ue(r.getAttribute("src")),this.provider=function(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e)?ge.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?ge.vimeo:null}(l.toString()),this.elements.container=this.media,this.media=r,this.elements.container.className="",l.search.length){var c=["1","true"];c.includes(l.searchParams.get("autoplay"))&&(this.config.autoplay=!0),c.includes(l.searchParams.get("loop"))&&(this.config.loop.active=!0),this.isYouTube?(this.config.playsinline=c.includes(l.searchParams.get("playsinline")),this.config.youtube.hl=l.searchParams.get("hl")):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(p.empty(this.provider)||!Object.keys(ge).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=ye.video;break;case"video":case"audio":this.type=o,this.provider=ge.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),(this.media.hasAttribute("playsinline")||this.media.hasAttribute("webkit-playsinline"))&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=z.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.eventListeners=[],this.listeners=new Pe(this),this.storage=new ie(this),this.media.plyr=this,p.element(this.elements.container)||(this.elements.container=C("div",{tabindex:0}),w(this.media,this.elements.container)),Ae.addStyleHook.call(this),je.setup.call(this),this.config.debug&&y.call(this,this.elements.container,this.config.events.join(" "),function(e){a.debug.log("event: ".concat(e.type))}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&Ae.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new Te(this),this.config.ads.enabled&&(this.ads=new qe(this)),this.config.autoplay&&this.play(),this.lastSeekTime=0,this.config.previewThumbnails.enabled&&(this.previewThumbnails=new De(this))):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return i(t,[{key:"play",value:function(){return p.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&p.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(p.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):p.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(p.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(p.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(p.number(e)?e:0)}},{key:"decreaseVolume",value:function(e){this.increaseVolume(-e)}},{key:"toggleCaptions",value:function(e){he.toggle.call(this,e,!1)}},{key:"airplay",value:function(){z.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){if(this.supported.ui&&!this.isAudio){var t=I(this.elements.container,this.config.classNames.hideControls),i=void 0===e?void 0:!e,n=x(this.elements.container,this.config.classNames.hideControls,i);if(n&&this.config.controls.includes("settings")&&!p.empty(this.config.settings)&&ce.toggleMenu.call(this,!1),n!==t){var a=n?"controlshidden":"controlsshown";k.call(this,this.media,a)}return!n}return!1}},{key:"on",value:function(e,t){y.call(this,this.elements.container,e,t)}},{key:"once",value:function(e,t){b.call(this,this.elements.container,e,t)}},{key:"off",value:function(e,t){v(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var n=function(){document.body.style.overflow="",t.embed=null,i?(Object.keys(t.elements).length&&(E(t.elements.buttons.play),E(t.elements.captions),E(t.elements.controls),E(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),p.function(e)&&e()):(function(){this&&this.eventListeners&&(this.eventListeners.forEach(function(e){var t=e.element,i=e.type,n=e.callback,a=e.options;t.removeEventListener(i,n,a)}),this.eventListeners=[])}.call(t),S(t.elements.original,t.elements.container),k.call(t,t.elements.original,"destroyed",!0),p.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};this.stop(),this.isHTML5?(clearTimeout(this.timers.loading),Ae.toggleNativeControls.call(this,!0),n()):this.isYouTube?(clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&p.function(this.embed.destroy)&&this.embed.destroy(),n()):this.isVimeo&&(null!==this.embed&&this.embed.unload().then(n),setTimeout(n,200))}}},{key:"supports",value:function(e){return z.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===ge.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===ge.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===ge.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===ye.video)}},{key:"isAudio",get:function(){return Boolean(this.type===ye.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){if(this.duration){var t=p.number(e)&&e>0;this.media.currentTime=t?Math.min(e,this.duration):0,this.debug.log("Seeking to ".concat(this.currentTime," seconds"))}},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return p.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=(this.media||{}).duration,i=p.number(t)&&t!==1/0?t:0;return e||i}},{key:"volume",set:function(e){var t=e;p.string(t)&&(t=Number(t)),p.number(t)||(t=this.storage.get("volume")),p.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!p.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;p.boolean(t)||(t=this.storage.get("muted")),p.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;p.number(e)&&(t=e),p.number(t)||(t=this.storage.get("speed")),p.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed (".concat(t,")"))},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=this.config.quality,i=this.options.quality;if(i.length){var n=[!p.empty(e)&&Number(e),this.storage.get("quality"),t.selected,t.default].find(p.number),a=!0;if(!i.includes(n)){var s=function(e,t){return p.array(e)&&e.length?e.reduce(function(e,i){return Math.abs(i-t)<Math.abs(e-t)?i:e}):null}(i,n);this.debug.warn("Unsupported quality option: ".concat(n,", using ").concat(s," instead")),n=s,a=!1}t.selected=n,this.media.quality=n,a&&this.storage.set({quality:n})}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=p.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){He.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"download",get:function(){var e=this.config.urls.download;return p.url(e)?e:this.source}},{key:"poster",set:function(e){this.isVideo?Ae.setPoster.call(this,e,!1).catch(function(){}):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=p.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"currentTrack",set:function(e){he.set.call(this,e,!1)},get:function(){var e=this.captions,t=e.toggled,i=e.currentTrack;return t?i:-1}},{key:"language",set:function(e){he.setLanguage.call(this,e,!1)},get:function(){return(he.getCurrentTrack.call(this)||{}).language}},{key:"pip",set:function(e){if(z.pip){var t=p.boolean(e)?e:!this.pip;p.function(this.media.webkitSetPresentationMode)&&this.media.webkitSetPresentationMode(t?pe:fe),p.function(this.media.requestPictureInPicture)&&(!this.pip&&t?this.media.requestPictureInPicture():this.pip&&!t&&document.exitPictureInPicture())}},get:function(){return z.pip?p.empty(this.media.webkitPresentationMode)?this.media===document.pictureInPictureElement:this.media.webkitPresentationMode===pe:null}}],[{key:"supported",value:function(e,t,i){return z.check(e,t,i)}},{key:"loadSprite",value:function(e,t){return ae(e,t)}},{key:"setup",value:function(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null;return p.string(e)?n=Array.from(document.querySelectorAll(e)):p.nodeList(e)?n=Array.from(e):p.array(e)&&(n=e.filter(p.element)),p.empty(n)?null:n.map(function(e){return new t(e,i)})}}]),t}();return Re.defaults=(_e=me,JSON.parse(JSON.stringify(_e))),Re}); //# sourceMappingURL=plyr.min.js.map diff --git a/dist/plyr.min.js.map b/dist/plyr.min.js.map index 64f59076..7f904429 100644 --- a/dist/plyr.min.js.map +++ b/dist/plyr.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["support.js","../../node_modules/loadjs/dist/loadjs.umd.js","types.js","utils.js","html5.js","i18n.js","ui.js","controls.js","captions.js","console.js","defaults.js","fullscreen.js","listeners.js","plugins/vimeo.js","plugins/youtube.js","media.js","plugins/ads.js","source.js","storage.js","plyr.js"],"names":["range","factory","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","q","length","splice","executeCallbacks","args","depsNotFound","call","success","error","loadFile","path","callbackFn","numTries","isCss","e","doc","document","async","maxTries","numRetries","beforeCallbackFn","before","pathStripped","replace","test","createElement","rel","href","src","undefined","onload","onerror","onbeforeload","ev","result","type","sheet","cssText","x","defaultPrevented","head","appendChild","loadjs","paths","arg1","arg2","trim","fn","i","numWaiting","push","loadFiles","ready","deps","bundleIds","r","subscribe","done","reset","isDefined","module","exports","providers","types","utils","input","this","instanceof","window","Plyr","getConstructor","Object","Number","isNaN","String","Boolean","Function","nullOrUndefined","Array","isArray","WeakMap","NodeList","Element","Text","Event","TextTrackCue","VTTCue","TextTrack","string","kind","array","nodeList","object","keys","constructor","documentMode","documentElement","style","navigator","userAgent","platform","url","responseType","arguments","Promise","resolve","reject","request","XMLHttpRequest","addEventListener","JSON","parse","responseText","response","Error","statusText","open","send","id","is","hasId","exists","querySelectorAll","container","toggleHidden","setAttribute","support","storage","cached","localStorage","getItem","data","content","fetch","then","empty","setItem","stringify","catch","injectSprite","innerHTML","body","insertBefore","childNodes","prefix","Math","floor","random","elements","wrapper","targets","from","reverse","forEach","element","index","child","cloneNode","parent","parentNode","sibling","nextSibling","attributes","text","setAttributes","textContent","target","removeElement","removeChild","lastChild","newChild","oldChild","replaceChild","entries","_ref","key","_ref2","value","sel","existingAttributes","existing","split","s","selector","className","parts","charAt","class","hidden","hide","boolean","hasAttribute","removeAttribute","toggle","contains","classList","prototype","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","querySelector","focused","activeElement","focusable","getElements","first","last","trap","event","keyCode","getFocusElement","shiftKey","focus","preventDefault","on","off","callback","passive","capture","function","Node","toggleListener","events","options","passiveListeners","bubbles","detail","CustomEvent","assign","plyr","dispatchEvent","toggleState","pressed","getAttribute","state","_len","_key","toString","match","current","max","toFixed","parseInt","time","displayHours","inverted","number","formatTime","format","slice","hours","getHours","mins","getMinutes","secs","getSeconds","find","RegExp","toUpperCase","substr","toLowerCase","replaceAll","toTitleCase","toPascalCase","sources","_len2","_key2","source","shift","defineProperty","extend","apply","concat","toConsumableArray","filter","item","indexOf","reduce","prev","curr","abs","youtube","vimeo","$2","parser","search","startsWith","parseUrl","params","hash","_hash$split2","val","decodeURIComponent","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","offsetHeight","provider","playsinline","api","ui","browser","getBrowser","canPlayInline","isIPhone","video","rangeInput","audio","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","isHTML5","canPlayType","isVideo","isAudio","supported","transitionEndEvent","matchMedia","html5","getSources","sizes","dedupe","player","mime","currentTime","playing","load","play","config","blankVideo","debug","log","i18n","seekTime","title","toggleClass","selectors","classNames","uiSupported","listeners","warn","toggleNativeControls","controls","inject","setup","volume","muted","speed","loop","quality","updateVolume","timeUpdate","checkPlaying","pip","airplay","isIos","isTouch","touch","_this","setTitle","setPoster","label","buttons","button","isEmbed","iframe","getElement","poster","posters","backgroundImage","p","paused","stopped","toggleControls","loading","timers","setTimeout","_this2","failed","networkState","_this3","inputs","setRange","mute","updateRangeFill","progress","display","buffer","getElementsByTagName","nodeValue","getPercentage","duration","seek","setProgress","buffered","forceHours","invert","invertTime","updateTimeDisplay","seeking","updateProgress","hasDuration","displayDuration","updateSeekTooltip","isWebkit","setProperty","cors","URL","iconUrl","location","host","isIE","svg4everybody","pause","restart","rewind","fastForward","settings","captions","fullscreen","seekTooltip","tooltip","getIconUrl","iconPath","iconPrefix","icon","createElementNS","use","setAttributeNS","attr","badge","menu","buttonType","toCamelCase","labelPressed","iconPressed","control","createIcon","createLabel","getAttributesFromSelector","suffix","list","checked","radio","faux","insertAdjacentHTML","tooltips","percent","clientRect","getBoundingClientRect","visible","_toggle","pageX","left","hasClass","parseFloat","setting","tabs","panes","toggleTab","checkMenu","emptyElement","sort","a","b","sorting","getLabel","createMenuItem","createBadge","getBadge","updateSetting","pane","active","some","lang","language","default","getTracks","tracks","track","unshift","isVimeo","_this4","values","tab","form","show","isMenuItem","isButton","stopPropagation","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setQualityMenu","getQualityOptions","setSpeedMenu","loadSprite","props","update","create","findElements","repaint","labels","_this6","stored","get","isYouTube","textTracks","setCaptionsMenu","insertAfter","enabled","hostname","protocol","blob","createObjectURL","setLanguage","setCue","mode","currentTrack","getCurrentTrack","activeCues","embed","enableTextTrack","cue","setText","getCueAsHTML","caption","noop","Console","console","bind","defaults","userLanguage","onChange","trapFocus","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","y","overflow","fallback","Fullscreen","property","native","iosNative","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","exitFullscreen","exit","enter","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","Listeners","lastKey","handleKey","toggleMenu","firstTouch","code","which","repeat","altKey","ctrlKey","metaKey","editable","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","keyboard","global","tabFocus","hideControls","durationUpdate","hasAudio","resetOnEnd","checkLoading","ads","initialized","managerPromise","clickToPlay","ended","disableContextMenu","set","inputEvent","proxy","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","showHomeTab","showTab","toggleInvert","hover","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","setAspectRatio","Vimeo","loadScript","urls","sdk","padding","paddingBottom","offset","transform","autoplay","buildUrlParams","parseVimeoId","embedContainer","replaceElement","thumbnail_large","pathname","Player","autopause","disableTextTrack","stop","setCurrentTime","selected","setPlaybackRate","setVolume","setLoop","currentSrc","getVideoUrl","all","getVideoWidth","getVideoHeight","dimensions","getAspectRatio","setAutopause","getVideoTitle","getCurrentTime","getDuration","getTextTracks","cues","stripHTML","seconds","build","mapQualityUnit","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","videoId","getVideoData","google","items","snippet","currentId","parseYouTubeId","generateId","message","instance","playbackRate","getPlaybackRate","getTitle","playVideo","pauseVideo","stopVideo","seekTo","getPlaybackQuality","setPlaybackQuality","getAvailablePlaybackRates","buffering","setInterval","getVideoLoadedFraction","lastBuffered","levels","getAvailableQualityLevels","level","wrap","Ads","publisherId","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","googleIMA","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","displayContainer","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","tagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","_this7","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","cancel","contentComplete","_this8","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","_this9","init","start","adError","zIndex","_this10","destroy","handlers","handler","_this11","Date","now","base","insertElement","attribute","cancelRequests","check","crossorigin","addStyleHook","insertElements","Storage","store","json","removeItem","jQuery","original","tagName","getProviderByUrl","getUrlParams","truthy","step","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","noTransition","soft","clear","unload","targetTime","end","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","closest","change","states","webkitPresentationMode","inline","t"],"mappings":"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uEAMH,UACA,WACC,aACE,YACD,iBACK,UACP,YACE,cACE,gBACE,SACP,aACI,WACF,aACE,UACH,cACI,sBAQV,WACA,UACA,UACA,UACA,UACA,iBACA,YACA,aACA,iBACA,aACA,eACA,OACA,QACA,QACA,UACA,SACA,UACA,aACA,8BAIA,iBACA,kBACA,mBACA,iBACA,iBACA,gBACA,sBAIA,gBACA,+BAIA,kBACA,mBACA,YACA,cACA,cACA,iBACA,gBACA,gCAMU,uDACC,4BAEI,aACF,0BAEL,4BAEE,2BACC,8BACE,+BACD,mCACK,kCACP,8BACI,oCACE,+BACP,4BACI,iCACC,8BACJ,mCAGA,4BACE,6BACD,+BACG,iCACD,8CAGI,gCACH,+BACF,iCACA,+BACF,+BACE,mCAEF,2BACA,gCAEG,mDAMP,qBACI,kBACH,4BACA,mCACS,sCACR,mBACH,oBACI,wBACA,uBACD,uBACC,wBACA,sBACF,wBACA,sBACE,qBACH,oBACE,6BACM,4BACP,uBACE,6BACI,6BACC,kCAEH,0BACA,mBACD,qCAGG,gCACD,6CAGC,oCACC,4CAGC,6BACH,uCAGG,iCACH,iCAEF,+CAMI,wBACN,oCAMA,oBAMC,cACI,KChYfoI,EAAUzP,EAAM0P,aAEtB,SAASyP,OACAjf,KAAK0d,aAKJrK,EAASrT,KAAK4Q,OAAO1L,SAASkO,QAAQyD,WACxC/W,EAAMuD,GAAGmC,QAAQ6N,MACX9I,YAAY8I,EAAQrT,KAAKka,UAI7B5P,cAActK,KAAKoG,OAAQpG,KAAKka,OAAS,kBAAoB,kBAAkB,GAGhF3K,EAAQsD,SACHqM,UAAU9iB,KAAK4D,KAAK4Q,OAAQ5Q,KAAKoG,OAAQpG,KAAKka,SAI5D,SAASiF,QAAepX,EAAgB1F,UAAAtG,OAAA,QAAA4B,IAAA0E,UAAA,IAAAA,UAAA,GAEhC0F,OACKqX,kBACElf,OAAOmf,SAAW,IAClBnf,OAAOof,SAAW,UAGlBC,SAASvf,KAAKof,eAAehhB,EAAG4B,KAAKof,eAAeI,YAItD7a,KAAK5C,MAAM0d,SAAW1X,EAAS,SAAW,KAG7C0J,YAAYzR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","file":"plyr.min.js","sourcesContent":["// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n\n switch (`${provider}:${type}`) {\n case 'html5:video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n case 'html5:audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!this.isHTML5 || !utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Check directly if codecs specified\n if (type.includes('codecs=')) {\n return media.canPlayType(type).replace(/no/, '');\n }\n\n // Type specific checks\n if (this.isVideo) {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.isAudio) {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText`\n result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\nexport default { providers, types };\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport loadjs from 'loadjs';\nimport support from './support';\nimport { providers } from './types';\n\nconst utils = {\n // Check variable types\n is: {\n plyr(input) {\n return this.instanceof(input, window.Plyr);\n },\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.nullOrUndefined(input) && Array.isArray(input);\n },\n weakMap(input) {\n return this.instanceof(input, window.WeakMap);\n },\n nodeList(input) {\n return this.instanceof(input, window.NodeList);\n },\n element(input) {\n return this.instanceof(input, window.Element);\n },\n textNode(input) {\n return this.getConstructor(input) === Text;\n },\n event(input) {\n return this.instanceof(input, window.Event);\n },\n cue(input) {\n return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);\n },\n track(input) {\n return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));\n },\n url(input) {\n return !this.nullOrUndefined(input) && /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-/]))?/.test(input);\n },\n nullOrUndefined(input) {\n return input === null || typeof input === 'undefined';\n },\n empty(input) {\n return (\n this.nullOrUndefined(input) ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||\n (this.object(input) && !Object.keys(input).length)\n );\n },\n instanceof(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n getConstructor(input) {\n return !this.nullOrUndefined(input) ? input.constructor : null;\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Fetch wrapper\n // Using XHR to avoid issues with older browsers\n fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.statusText);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n },\n\n // Load an external script\n loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (!utils.is.string(url)) {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = utils.is.string(id);\n let isCached = false;\n\n const exists = () => document.querySelectorAll(`#${id}`).length;\n\n function injectSprite(data) {\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n // Create container\n const container = document.createElement('div');\n utils.toggleHidden(container, true);\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n injectSprite.call(container, data.content);\n return;\n }\n }\n\n // Get the sprite\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.empty(result)) {\n return;\n }\n\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n injectSprite.call(container, result);\n })\n .catch(() => {});\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new <element>\n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove element(s)\n removeElement(element) {\n if (utils.is.nodeList(element) || utils.is.array(element)) {\n Array.from(element).forEach(utils.removeElement);\n return;\n }\n\n if (!utils.is.element(element) || !utils.is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Replace element\n replaceElement(newChild, oldChild) {\n if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n if (!utils.is.element(element) || utils.is.empty(attributes)) {\n return;\n }\n\n Object.entries(attributes).forEach(([\n key,\n value,\n ]) => {\n element.setAttribute(key, value);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle hidden\n toggleHidden(element, hidden) {\n if (!utils.is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!utils.is.boolean(hide)) {\n hide = !element.hasAttribute('hidden');\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.element(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.element(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus(element = null, toggle = false) {\n if (!utils.is.element(element)) {\n return;\n }\n\n const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n if (toggle) {\n utils.on(this.elements.container, 'keydown', trap, false);\n } else {\n utils.off(this.elements.container, 'keydown', trap, false);\n }\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no elemetns, event, or callback\n if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements) || utils.is.array(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!utils.is.element(element) || utils.is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: utils.is.plyr(this) ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // If multiple elements passed\n if (utils.is.array(element) || utils.is.nodeList(element)) {\n Array.from(element).forEach(target => utils.toggleState(target, input));\n return;\n }\n\n // Bail if no target\n if (!utils.is.element(element)) {\n return;\n }\n\n // Get state\n const pressed = element.getAttribute('aria-pressed') === 'true';\n const state = utils.is.boolean(input) ? input : !pressed;\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Format string\n format(input, ...args) {\n if (utils.is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : '');\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return (current / max * 100).toFixed(2);\n },\n\n // Time helpers\n getHours(value) {\n return parseInt((value / 60 / 60) % 60, 10);\n },\n getMinutes(value) {\n return parseInt((value / 60) % 60, 10);\n },\n getSeconds(value) {\n return parseInt(value % 60, 10);\n },\n\n // Format time to UI friendly string\n formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!utils.is.number(time)) {\n return this.formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = this.getHours(time);\n const mins = this.getMinutes(time);\n const secs = this.getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n },\n\n // Replace all occurances of a string in a string\n replaceAll(input = '', find = '', replace = '') {\n return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n },\n\n // Convert to title case\n toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n },\n\n // Convert string to pascalCase\n toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = utils.replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = utils.replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = utils.toTitleCase(string);\n\n // Convert to pascal case\n return utils.replaceAll(string, ' ', '');\n },\n\n // Convert string to pascalCase\n toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = utils.toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n },\n\n // Deep extend destination object with N more objects\n extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!utils.is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (utils.is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n utils.extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return utils.extend(target, ...sources);\n },\n\n // Remove duplicates in an array\n dedupe(array) {\n if (!utils.is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n },\n\n // Get the closest value in an array\n closest(array, value) {\n if (!utils.is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n },\n\n // Get the provider for a given URL\n getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert a URL to a location object\n parseUrl(url) {\n const parser = document.createElement('a');\n parser.href = url;\n return parser;\n },\n\n // Get URL query parameters\n getUrlParams(input) {\n let search = input;\n\n // Parse URL if needed\n if (input.startsWith('http://') || input.startsWith('https://')) {\n ({ search } = this.parseUrl(input));\n }\n\n if (this.is.empty(search)) {\n return null;\n }\n\n const hashes = search.slice(search.indexOf('?') + 1).split('&');\n\n return hashes.reduce((params, hash) => {\n const [\n key,\n val,\n ] = hash.split('=');\n\n return Object.assign(params, { [key]: decodeURIComponent(val) });\n }, {});\n },\n\n // Convert object to URL parameters\n buildUrlParams(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n get transitionEndEvent() {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return utils.is.string(type) ? events[type] : false;\n },\n\n // Force repaint of element\n repaint(element) {\n setTimeout(() => {\n utils.toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n utils.toggleHidden(element, false);\n }, 0);\n },\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return null;\n }\n\n return this.media.querySelectorAll('source');\n },\n\n // Get quality levels\n getQualityOptions() {\n if (!this.isHTML5) {\n return null;\n }\n\n // Get sources\n const sources = html5.getSources.call(this);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n // Get <source> with size attribute\n const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size')));\n\n // If none, bail\n if (utils.is.empty(sizes)) {\n return null;\n }\n\n // Reduce to unique list\n return utils.dedupe(sizes.map(source => Number(source.getAttribute('size'))));\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source);\n\n if (utils.is.empty(matches)) {\n return null;\n }\n\n return Number(matches[0].getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return;\n }\n\n // Get matches for requested size\n const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input);\n\n // No matches for requested size\n if (utils.is.empty(matches)) {\n return;\n }\n\n // Get supported sources\n const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type')));\n\n // No supported sources\n if (utils.is.empty(supported)) {\n return;\n }\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality: input,\n });\n\n // Get current state\n const { currentTime, playing } = player;\n\n // Set new source\n player.media.src = supported[0].getAttribute('src');\n\n // Load new source\n player.media.load();\n\n // Resume playing\n if (playing) {\n player.play();\n }\n\n // Restore time\n player.currentTime = currentTime;\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n utils.removeElement(html5.getSources());\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport utils from './utils';\n\nconst i18n = {\n get(key = '', config = {}) {\n if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {\n return '';\n }\n\n let string = config.i18n[key];\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([\n key,\n value,\n ]) => {\n string = utils.replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n ui.updateVolume.call(this);\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n utils.dispatchEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Set the poster image\n ui.setPoster.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Set the poster image\n setPoster() {\n if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) {\n return;\n }\n\n // Set the inline style\n const posters = this.poster.split(',');\n this.elements.poster.style.backgroundImage = posters.map(p => `url('${p}')`).join(',');\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set ARIA state\n utils.toggleState(this.elements.buttons.play, this.playing);\n\n // Only update controls on non timeupdate events\n if (utils.is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n this.toggleControls(!this.playing);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = [\n 'stalled',\n 'waiting',\n ].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Check if media failed to load\n checkFailed() {\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState\n this.failed = this.media.networkState === 3;\n\n if (this.failed) {\n utils.toggleClass(this.elements.container, this.config.classNames.loading, false);\n utils.toggleClass(this.elements.container, this.config.classNames.error, true);\n }\n\n // Clear timer\n clearTimeout(this.timers.failed);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.element(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (utils.is.element(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!utils.is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set <progress> value\n setProgress(target, input) {\n const value = utils.is.number(input) ? input : 0;\n const progress = utils.is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !utils.is.event(event)) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!utils.is.element(target) || !utils.is.number(time)) {\n return;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = utils.getHours(this.duration) > 0;\n\n // eslint-disable-next-line no-param-reassign\n target.textContent = utils.formatTime(time, forceHours, inverted);\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded\n durationUpdate() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's a spot to display duration\n const hasDuration = utils.is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport i18n from './i18n';\nimport support from './support';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria value for https://github.com/sampotts/plyr/issues/905\n range.setAttribute('aria-valuenow', range.value);\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n },\n\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (utils.is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type, attr) {\n let text = i18n.get(type, this.config);\n const attributes = Object.assign({}, attr);\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n if ('class' in attributes) {\n attributes.class += ` ${this.config.classNames.hidden}`;\n } else {\n attributes.class = this.config.classNames.hidden;\n }\n\n return utils.createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (utils.is.empty(text)) {\n return null;\n }\n\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const button = utils.createElement('button');\n const attributes = Object.assign({}, attr);\n let type = utils.toCamelCase(buttonType);\n\n let toggle = false;\n let label;\n let icon;\n let labelPressed;\n let iconPressed;\n\n if (!('type' in attributes)) {\n attributes.type = 'button';\n }\n\n if ('class' in attributes) {\n if (attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n toggle = true;\n label = 'play';\n labelPressed = 'pause';\n icon = 'play';\n iconPressed = 'pause';\n break;\n\n case 'mute':\n toggle = true;\n label = 'mute';\n labelPressed = 'unmute';\n icon = 'volume';\n iconPressed = 'muted';\n break;\n\n case 'captions':\n toggle = true;\n label = 'enableCaptions';\n labelPressed = 'disableCaptions';\n icon = 'captions-off';\n iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n toggle = true;\n label = 'enterFullscreen';\n labelPressed = 'exitFullscreen';\n icon = 'enter-fullscreen';\n iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n label = 'play';\n icon = 'play';\n break;\n\n default:\n label = type;\n icon = buttonType;\n }\n\n // Setup toggle icon and labels\n if (toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));\n button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));\n button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));\n\n // Add aria attributes\n attributes['aria-pressed'] = false;\n } else {\n button.appendChild(controls.createIcon.call(this, icon));\n button.appendChild(controls.createLabel.call(this, label));\n }\n\n // Merge attributes\n utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n\n utils.setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!utils.is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek label\n const label = utils.createElement(\n 'label',\n {\n for: attributes.id,\n id: `${attributes.id}-label`,\n class: this.config.classNames.hidden,\n },\n i18n.get(type, this.config),\n );\n\n // Seek input\n const input = utils.createElement(\n 'input',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-labelledby': `${attributes.id}-label`,\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return {\n label,\n input,\n };\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = utils.createElement(\n 'progress',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(utils.createElement('span', null, '0'));\n\n let suffix = '';\n switch (type) {\n case 'played':\n suffix = i18n.get('played', this.config);\n break;\n\n case 'buffer':\n suffix = i18n.get('buffered', this.config);\n break;\n\n default:\n break;\n }\n\n progress.textContent = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = utils.createElement('div', utils.extend(attributes, {\n class: `plyr__time ${attributes.class}`,\n 'aria-label': i18n.get(type, this.config),\n }), '00:00');\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Create a settings menu item\n createMenuItem(value, list, type, title, badge = null, checked = false) {\n const item = utils.createElement('li');\n\n const label = utils.createElement('label', {\n class: this.config.classNames.control,\n });\n\n const radio = utils.createElement(\n 'input',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'radio',\n name: `plyr-${type}`,\n value,\n checked,\n class: 'plyr__sr-only',\n }),\n );\n\n const faux = utils.createElement('span', { hidden: '' });\n\n label.appendChild(radio);\n label.appendChild(faux);\n label.insertAdjacentHTML('beforeend', title);\n\n if (utils.is.element(badge)) {\n label.appendChild(badge);\n }\n\n item.appendChild(label);\n list.appendChild(item);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !utils.is.element(this.elements.inputs.seek) ||\n !utils.is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.inputs.seek.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (utils.is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (utils.is.event(event) && [\n 'mouseenter',\n 'mouseleave',\n ].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Hide/show a tab\n toggleTab(setting, toggle) {\n utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);\n },\n\n // Set the quality menu\n // TODO: Vimeo support\n setQualityMenu(options) {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panes.quality.querySelector('ul');\n\n // Set options if passed and filter based on config\n if (utils.is.array(options)) {\n this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n let label = '';\n\n switch (quality) {\n case 2160:\n label = '4K';\n break;\n\n case 1440:\n case 1080:\n case 720:\n label = 'HD';\n break;\n\n case 576:\n case 480:\n label = 'SD';\n break;\n\n default:\n break;\n }\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n const label = controls.getLabel.call(this, 'quality', quality);\n controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Translate a value into a nice label\n // TODO: Localisation\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (utils.is.number(value)) {\n return `${value}p`;\n }\n\n return utils.toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panes[setting];\n let value = null;\n let list = container;\n\n switch (setting) {\n case 'captions':\n if (this.captions.active) {\n if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) {\n value = this.captions.language;\n } else {\n value = 'enabled';\n }\n } else {\n value = '';\n }\n\n break;\n\n default:\n value = !utils.is.empty(input) ? input : this[setting];\n\n // Get default\n if (utils.is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n\n break;\n }\n\n // Get the list if we need to\n if (!utils.is.element(list)) {\n list = pane && pane.querySelector('ul');\n }\n\n // If there's no list it means it's not been rendered...\n if (!utils.is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`input[value=\"${value}\"]`);\n\n if (utils.is.element(target)) {\n target.checked = true;\n }\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panes.loop.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.loop, false);\n utils.toggleHidden(this.elements.settings.panes.loop, false);\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.loop.options);\n controls.toggleTab.call(this, 'loop', toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n options.forEach(option => {\n const item = utils.createElement('li');\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panes.captions.querySelector('ul');\n\n // Toggle the pane and tab\n const toggle = captions.getTracks.call(this).length;\n controls.toggleTab.call(this, type, toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Re-map the tracks into just the data we need\n const tracks = captions.getTracks.call(this).map(track => ({\n language: !utils.is.empty(track.language) ? track.language : 'enabled',\n label: captions.getLabel.call(this, track),\n }));\n\n // Add the \"Disabled\" option to turn off captions\n tracks.unshift({\n language: '',\n label: i18n.get('disabled', this.config),\n });\n\n // Generate options\n tracks.forEach(track => {\n controls.createMenuItem.call(\n this,\n track.language,\n list,\n 'language',\n track.label,\n track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null,\n track.language.toLowerCase() === this.captions.language.toLowerCase(),\n );\n });\n\n // Store reference\n this.options.captions = tracks.map(track => track.language);\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Do nothing if not selected\n if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) {\n return;\n }\n\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.speed)) {\n return;\n }\n\n const type = 'speed';\n\n // Set the speed options\n if (utils.is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the list to populate\n const list = this.elements.settings.panes.speed.querySelector('ul');\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Create items\n this.options.speed.forEach(speed => {\n const label = controls.getLabel.call(this, 'speed', speed);\n controls.createMenuItem.call(this, speed, list, type, label);\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { tabs } = this.elements.settings;\n const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);\n\n utils.toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Show/hide menu\n toggleMenu(event) {\n const { form } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!utils.is.element(form) || !utils.is.element(button)) {\n return;\n }\n\n const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');\n\n if (utils.is.event(event)) {\n const isMenuItem = utils.is.element(form) && form.contains(event.target);\n const isButton = event.target === this.elements.buttons.settings;\n\n // If the click was inside the form or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && !isButton && show)) {\n return;\n }\n\n // Prevent the toggle being caught by the doc listener\n if (isButton) {\n event.stopPropagation();\n }\n }\n\n // Set form and button attributes\n if (utils.is.element(button)) {\n button.setAttribute('aria-expanded', show);\n }\n\n if (utils.is.element(form)) {\n utils.toggleHidden(form, !show);\n utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n if (show) {\n form.removeAttribute('tabindex');\n } else {\n form.setAttribute('tabindex', -1);\n }\n }\n },\n\n // Get the natural size of a tab\n getTabSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Prevent input's being unchecked due to the name being identical\n Array.from(clone.querySelectorAll('input[name]')).forEach(input => {\n const name = input.getAttribute('name');\n input.setAttribute('name', `${name}-clone`);\n });\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n utils.removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Toggle Menu\n showTab(target = '') {\n const { menu } = this.elements.settings;\n const pane = document.getElementById(target);\n\n // Nothing to show, bail\n if (!utils.is.element(pane)) {\n return;\n }\n\n // Are we targetting a tab? If not, bail\n const isTab = pane.getAttribute('role') === 'tabpanel';\n if (!isTab) {\n return;\n }\n\n // Hide all other tabs\n // Get other tabs\n const current = menu.querySelector('[role=\"tabpanel\"]:not([hidden])');\n const container = current.parentNode;\n\n // Set other toggles to be expanded false\n Array.from(menu.querySelectorAll(`[aria-controls=\"${current.getAttribute('id')}\"]`)).forEach(toggle => {\n toggle.setAttribute('aria-expanded', false);\n });\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getTabSize.call(this, pane);\n\n // Restore auto height/width\n const restore = e => {\n // We're only bothered about height and width on the container\n if (e.target !== container || ![\n 'width',\n 'height',\n ].includes(e.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n utils.off(container, utils.transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n utils.on(container, utils.transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n utils.toggleHidden(current, true);\n current.setAttribute('tabindex', -1);\n\n // Set attributes on target\n utils.toggleHidden(pane, false);\n\n const tabs = utils.getElements.call(this, `[aria-controls=\"${target}\"]`);\n Array.from(tabs).forEach(tab => {\n tab.setAttribute('aria-expanded', true);\n });\n pane.removeAttribute('tabindex');\n\n // Focus the first item\n pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Do nothing if we want no controls\n if (utils.is.empty(this.config.controls)) {\n return null;\n }\n\n // Create the container\n const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n const seek = controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n });\n progress.appendChild(seek.label);\n progress.appendChild(seek.input);\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = utils.createElement(\n 'span',\n {\n role: 'tooltip',\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n container.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n const volume = utils.createElement('div', {\n class: 'plyr__volume',\n });\n\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n const range = controls.createRange.call(\n this,\n 'volume',\n utils.extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n );\n volume.appendChild(range.label);\n volume.appendChild(range.input);\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n const menu = utils.createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n menu.appendChild(\n controls.createButton.call(this, 'settings', {\n id: `plyr-settings-toggle-${data.id}`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const form = utils.createElement('form', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tablist',\n tabindex: -1,\n });\n\n const inner = utils.createElement('div');\n\n const home = utils.createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tabpanel',\n });\n\n // Create the tab list\n const tabs = utils.createElement('ul', {\n role: 'tablist',\n });\n\n // Build the tabs\n this.config.settings.forEach(type => {\n const tab = utils.createElement('li', {\n role: 'tab',\n hidden: '',\n });\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n id: `plyr-settings-${data.id}-${type}-tab`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-${type}`,\n 'aria-expanded': false,\n }),\n i18n.get(type, this.config),\n );\n\n const value = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n button.appendChild(value);\n tab.appendChild(button);\n tabs.appendChild(tab);\n\n this.elements.settings.tabs[type] = tab;\n });\n\n home.appendChild(tabs);\n inner.appendChild(home);\n\n // Build the panes\n this.config.settings.forEach(type => {\n const pane = utils.createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,\n role: 'tabpanel',\n tabindex: -1,\n });\n\n const back = utils.createElement(\n 'button',\n {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-home`,\n 'aria-expanded': false,\n },\n i18n.get(type, this.config),\n );\n\n pane.appendChild(back);\n\n const options = utils.createElement('ul');\n\n pane.appendChild(options);\n inner.appendChild(pane);\n\n this.elements.settings.panes[type] = pane;\n });\n\n form.appendChild(inner);\n menu.appendChild(form);\n container.appendChild(menu);\n\n this.elements.settings.form = form;\n this.elements.settings.menu = menu;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n utils.loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {\n // String or HTMLElement passed as the option\n container = this.config.controls;\n } else if (utils.is.function(this.config.controls)) {\n // A custom function to build controls\n // The function can return a HTMLElement or String\n container = this.config.controls.call(this, props);\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([\n key,\n value,\n ]) => {\n result = utils.replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (utils.is.string(this.config.controls)) {\n container = replace(container);\n } else if (utils.is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (utils.is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!utils.is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML\n if (utils.is.element(container)) {\n target.appendChild(container);\n } else if (container) {\n target.insertAdjacentHTML('beforeend', container);\n }\n\n // Find the elements if need be\n if (!utils.is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Edge sometimes doesn't finish the paint so force a redraw\n if (window.navigator.userAgent.includes('Edge')) {\n utils.repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const labels = utils.getElements.call(\n this,\n [\n this.config.selectors.controls.wrapper,\n ' ',\n this.config.selectors.labels,\n ' .',\n this.config.classNames.hidden,\n ].join(''),\n );\n\n Array.from(labels).forEach(label => {\n utils.toggleClass(label, this.config.classNames.hidden, false);\n utils.toggleClass(label, this.config.classNames.tooltip, true);\n label.setAttribute('role', 'tooltip');\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Set default language if not set\n const stored = this.storage.get('language');\n\n if (!utils.is.empty(stored)) {\n this.captions.language = stored;\n }\n\n if (utils.is.empty(this.captions.language)) {\n this.captions.language = this.config.captions.language.toLowerCase();\n }\n\n // Set captions enabled state if not set\n if (!utils.is.boolean(this.captions.active)) {\n const active = this.storage.get('captions');\n\n if (utils.is.boolean(active)) {\n this.captions.active = active;\n } else {\n this.captions.active = this.config.captions.active;\n }\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!utils.is.element(this.elements.captions)) {\n this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));\n\n utils.insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Set the class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));\n\n // Get tracks\n const tracks = captions.getTracks.call(this);\n\n // If no caption file exists, hide container for caption text\n if (utils.is.empty(tracks)) {\n return;\n }\n\n // Get browser info\n const browser = utils.getBrowser();\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const href = utils.parseUrl(src);\n\n if (href.hostname !== window.location.href.hostname && [\n 'http:',\n 'https:',\n ].includes(href.protocol)) {\n utils\n .fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n utils.removeElement(track);\n });\n }\n });\n }\n\n // Set language\n captions.setLanguage.call(this);\n\n // Enable UI\n captions.show.call(this);\n\n // Set available languages in list\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Set the captions language\n setLanguage() {\n // Setup HTML5 track rendering\n if (this.isHTML5 && this.isVideo) {\n captions.getTracks.call(this).forEach(track => {\n // Show track\n utils.on(track, 'cuechange', event => captions.setCue.call(this, event));\n\n // Turn off native caption rendering to avoid double captions\n // eslint-disable-next-line\n track.mode = 'hidden';\n });\n\n // Get current track\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Check if suported kind\n if (utils.is.track(currentTrack)) {\n // If we change the active track while a cue is already displayed we need to update it\n if (Array.from(currentTrack.activeCues || []).length) {\n captions.setCue.call(this, currentTrack);\n }\n }\n } else if (this.isVimeo && this.captions.active) {\n this.embed.enableTextTrack(this.language);\n }\n },\n\n // Get the tracks\n getTracks() {\n // Return empty array at least\n if (utils.is.nullOrUndefined(this.media)) {\n return [];\n }\n\n // Only get accepted kinds\n return Array.from(this.media.textTracks || []).filter(track => [\n 'captions',\n 'subtitles',\n ].includes(track.kind));\n },\n\n // Get the current track for the current language\n getCurrentTrack() {\n const tracks = captions.getTracks.call(this);\n\n if (!tracks.length) {\n return null;\n }\n\n // Get track based on current language\n let track = tracks.find(track => track.language.toLowerCase() === this.language);\n\n // Get the <track> with default attribute\n if (!track) {\n track = utils.getElement.call(this, 'track[default]');\n }\n\n // Get the first track\n if (!track) {\n [track] = tracks;\n }\n\n return track;\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (utils.is.track(currentTrack)) {\n if (!utils.is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!utils.is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Display active caption if it contains text\n setCue(input) {\n // Get the track from the event if needed\n const track = utils.is.event(input) ? input.target : input;\n const { activeCues } = track;\n const active = activeCues.length && activeCues[0];\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Only display current track\n if (track !== currentTrack) {\n return;\n }\n\n // Display a cue, if there is one\n if (utils.is.cue(active)) {\n captions.setText.call(this, active.getCueAsHTML());\n } else {\n captions.setText.call(this, null);\n }\n\n utils.dispatchEvent.call(this, this.media, 'cuechange');\n },\n\n // Set the current caption\n setText(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (utils.is.element(this.elements.captions)) {\n const content = utils.createElement('span');\n\n // Empty the container\n utils.emptyElement(this.elements.captions);\n\n // Default to empty\n const caption = !utils.is.nullOrUndefined(input) ? input : '';\n\n // Set the span content\n if (utils.is.string(caption)) {\n content.textContent = caption.trim();\n } else {\n content.appendChild(caption);\n }\n\n // Set new caption text\n this.elements.captions.appendChild(content);\n } else {\n this.debug.warn('No captions element to render to');\n }\n },\n\n // Display captions container and button (for initialization)\n show() {\n // Try to load the value from storage\n let active = this.storage.get('captions');\n\n // Otherwise fall back to the default config\n if (!utils.is.boolean(active)) {\n ({ active } = this.config.captions);\n } else {\n this.captions.active = active;\n }\n\n if (active) {\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true);\n utils.toggleState(this.elements.buttons.captions, true);\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [\n 4320,\n 2880,\n 2160,\n 1440,\n 1080,\n 720,\n 576,\n 480,\n 360,\n 240,\n 'default', // YouTube's \"auto\"\n ],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: (navigator.language || navigator.userLanguage).split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: [\n 'captions',\n 'quality',\n 'speed',\n ],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n },\n\n // URLs\n urls: {\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n ads: 'plyr__ads',\n control: 'plyr__control',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n error: 'plyr--has-error',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// ==========================================================================\n\nimport utils from './utils';\n\nconst browser = utils.getBrowser();\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (utils.is.element(button)) {\n utils.toggleState(button, this.active);\n }\n\n // Trigger an event\n utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n utils.trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n // TODO: Filter for target??\n onChange.call(this);\n });\n\n // Fullscreen toggle on double click\n utils.on(this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (utils.is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n\n prefixes.some(pre => {\n if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native) {\n return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.playing) {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!utils.is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!utils.is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.player.currentTime = this.player.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n this.player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n this.player.muted = !this.player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.player.forward();\n break;\n\n case 37:\n // Arrow back\n this.player.rewind();\n break;\n\n case 70:\n // F key\n this.player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n this.player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.player.loop = !this.player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) {\n this.player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n this.player.touch = true;\n\n // Add touch class\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);\n\n // Clean up\n utils.off(document.body, 'touchstart', this.firstTouch);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n // Keyboard shortcuts\n if (this.player.config.keyboard.global) {\n utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n utils.on(document.body, 'touchstart', this.firstTouch);\n }\n\n // Container listeners\n container() {\n // Keyboard shortcuts\n if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {\n utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.player.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.player.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.player.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => {\n this.player.toggleControls(event);\n });\n }\n }\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));\n\n // Display duration\n utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event));\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n utils.on(this.player.media, 'loadeddata', () => {\n utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);\n utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);\n });\n\n // Handle the media finishing\n utils.on(this.player.media, 'ended', () => {\n // Show poster on end\n if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {\n // Restart\n this.player.restart();\n }\n });\n\n // Check for buffer progress\n utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event));\n\n // Handle volume changes\n utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event));\n\n // Handle play/pause\n utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));\n\n // Loading state\n utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));\n\n // Check if media failed to load\n // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n utils.on(this.player.media, 'playing', () => {\n if (!this.player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (this.player.ads.enabled && !this.player.ads.initialized) {\n // Wait for manager response\n this.player.ads.managerPromise.then(() => this.player.ads.play()).catch(() => this.player.play());\n }\n });\n\n // Click video\n if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this.player, `.${this.player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!utils.is.element(wrapper)) {\n return;\n }\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.player.config.hideControls && this.player.touch && !this.player.paused) {\n return;\n }\n\n if (this.player.paused) {\n this.player.play();\n } else if (this.player.ended) {\n this.player.restart();\n this.player.play();\n } else {\n this.player.pause();\n }\n });\n }\n\n // Disable right click\n if (this.player.supported.ui && this.player.config.disableContextMenu) {\n utils.on(\n this.player.elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n utils.on(this.player.media, 'volumechange', () => {\n // Save to storage\n this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });\n });\n\n // Speed change\n utils.on(this.player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'speed');\n\n // Save to storage\n this.player.storage.set({ speed: this.player.speed });\n });\n\n // Quality request\n utils.on(this.player.media, 'qualityrequested', event => {\n // Save to storage\n this.player.storage.set({ quality: event.detail.quality });\n });\n\n // Quality change\n utils.on(this.player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);\n });\n\n // Caption language change\n utils.on(this.player.media, 'languagechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ language: this.player.language });\n });\n\n // Captions toggle\n utils.on(this.player.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ captions: this.player.captions.active });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.player.media, this.player.config.events.concat([\n 'keyup',\n 'keydown',\n ]).join(' '), event => {\n let detail = {};\n\n // Get error details from media\n if (event.type === 'error') {\n detail = this.player.media.error;\n }\n\n utils.dispatchEvent.call(this.player, this.player.elements.container, event.type, true, detail);\n });\n }\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Run default and custom handlers\n const proxy = (event, defaultHandler, customHandlerKey) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(this.player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && utils.is.function(defaultHandler)) {\n defaultHandler.call(this.player, event);\n }\n };\n\n // Trigger custom and default handlers\n const on = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n\n utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n };\n\n // Play/pause toggle\n on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play');\n\n // Pause\n on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');\n\n // Rewind\n on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');\n\n // Rewind\n on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');\n\n // Mute toggle\n on(\n this.player.elements.buttons.mute,\n 'click',\n () => {\n this.player.muted = !this.player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions);\n\n // Fullscreen toggle\n on(\n this.player.elements.buttons.fullscreen,\n 'click',\n () => {\n this.player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n on(\n this.player.elements.buttons.pip,\n 'click',\n () => {\n this.player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');\n\n // Settings menu\n on(this.player.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this.player, event);\n });\n\n // Settings menu\n on(this.player.elements.settings.form, 'click', event => {\n event.stopPropagation();\n\n // Go back to home tab on click\n const showHomeTab = () => {\n const id = `plyr-settings-${this.player.id}-home`;\n controls.showTab.call(this.player, id);\n };\n\n // Settings menu items - use event delegation as items are added/removed\n if (utils.matches(event.target, this.player.config.selectors.inputs.language)) {\n proxy(\n event,\n () => {\n this.player.language = event.target.value;\n showHomeTab();\n },\n 'language',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.quality)) {\n proxy(\n event,\n () => {\n this.player.quality = event.target.value;\n showHomeTab();\n },\n 'quality',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.speed)) {\n proxy(\n event,\n () => {\n this.player.speed = parseFloat(event.target.value);\n showHomeTab();\n },\n 'speed',\n );\n } else {\n const tab = event.target;\n controls.showTab.call(this.player, tab.getAttribute('aria-controls'));\n }\n });\n\n // Seek\n on(\n this.player.elements.inputs.seek,\n inputEvent,\n event => {\n this.player.currentTime = event.target.value / event.target.max * this.player.duration;\n },\n 'seek',\n );\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) {\n on(this.player.elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (this.player.currentTime === 0) {\n return;\n }\n\n this.player.config.invertTime = !this.player.config.invertTime;\n ui.timeUpdate.call(this.player);\n });\n }\n\n // Volume\n on(\n this.player.elements.inputs.volume,\n inputEvent,\n event => {\n this.player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n on(utils.getElements.call(this.player, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this.player, event.target);\n });\n }\n\n // Seek tooltip\n on(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event));\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mouseenter mouseleave', event => {\n this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.player.elements.controls.pressed = [\n 'mousedown',\n 'touchstart',\n ].includes(event.type);\n });\n\n // Focus in/out on controls\n on(this.player.elements.controls, 'focusin focusout', event => {\n this.player.toggleControls(event);\n });\n }\n\n // Mouse wheel for volume\n on(\n this.player.elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.player.decreaseVolume(step);\n direction = -1;\n } else {\n this.player.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.player.increaseVolume(step);\n direction = 1;\n } else {\n this.player.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n\n // Reset on destroy\n clear() {\n this.global(false);\n }\n}\n\nexport default Listeners;\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from './../captions';\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n vimeo.setAspectRatio.call(this);\n\n // Load the API if not already\n if (!utils.is.object(window.Vimeo)) {\n utils\n .loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // Set aspect ratio\n // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n if (this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n // muted: player.muted,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n };\n const params = utils.buildUrlParams(options);\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = utils.parseVimeoId(source);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = utils.format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Inject the package\n const wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = utils.replaceElement(wrapper, player.media);\n\n // Get poster image\n utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (utils.is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set attribute\n player.media.setAttribute('poster', url.href);\n\n // Update\n ui.setPoster.call(player);\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play().then(() => {\n player.media.paused = false;\n });\n };\n\n player.media.pause = () => {\n player.embed.pause().then(() => {\n player.media.paused = true;\n });\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time).catch(() => {\n // Do nothing\n });\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([\n player.embed.getVideoWidth(),\n player.embed.getVideoHeight(),\n ]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.setText.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n utils.dispatchEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\n// Standardise YouTube quality unit\nfunction mapQualityUnit(input) {\n switch (input) {\n case 'hd2160':\n return 2160;\n\n case 2160:\n return 'hd2160';\n\n case 'hd1440':\n return 1440;\n\n case 1440:\n return 'hd1440';\n\n case 'hd1080':\n return 1080;\n\n case 1080:\n return 'hd1080';\n\n case 'hd720':\n return 720;\n\n case 720:\n return 'hd720';\n\n case 'large':\n return 480;\n\n case 480:\n return 'large';\n\n case 'medium':\n return 360;\n\n case 360:\n return 'medium';\n\n case 'small':\n return 240;\n\n case 240:\n return 'small';\n\n default:\n return 'default';\n }\n}\n\nfunction mapQualityUnits(levels) {\n if (utils.is.empty(levels)) {\n return levels;\n }\n\n return utils.dedupe(levels.map(level => mapQualityUnit(level)));\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n youtube.setAspectRatio.call(this);\n\n // Setup API\n if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n utils.loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (utils.is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (utils.is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (utils.is.string(key) && !utils.is.empty(key)) {\n const url = utils.format(this.config.urls.youtube.api, videoId, key);\n\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // Set aspect ratio\n setAspectRatio() {\n const ratio = this.config.ratio.split(':');\n this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`;\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = utils.parseYouTubeId(source);\n const id = utils.generateId(player.provider);\n const container = utils.createElement('div', { id });\n player.media = utils.replaceElement(container, player.media);\n\n // Set poster image\n player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId));\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n playerVars: {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: 1, // Allow iOS inline playback\n\n // Tracking for stats\n // origin: window ? `${window.location.protocol}//${window.location.host}` : null,\n widget_referrer: window ? window.location.href : null,\n\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n },\n events: {\n onError(event) {\n // If we've already fired an error, don't do it again\n // YouTube fires onError twice\n if (utils.is.object(player.media.error)) {\n return;\n }\n\n const detail = {\n code: event.data,\n };\n\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n switch (event.data) {\n case 2:\n detail.message =\n 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.';\n break;\n\n case 5:\n detail.message =\n 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';\n break;\n\n case 100:\n detail.message =\n 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';\n break;\n\n case 101:\n case 150:\n detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';\n break;\n\n default:\n detail.message = 'An unknown error occured';\n break;\n }\n\n player.media.error = detail;\n\n utils.dispatchEvent.call(player, player.media, 'error');\n },\n onPlaybackQualityChange() {\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: player.media.quality,\n });\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n instance.playVideo();\n };\n\n player.media.pause = () => {\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n return mapQualityUnit(instance.getPlaybackQuality());\n },\n set(input) {\n const quality = input;\n\n // Set via API\n instance.setPlaybackQuality(mapQualityUnit(quality));\n\n // Trigger request event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality,\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n utils.dispatchEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n player.media.paused = true;\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n utils.dispatchEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // If we were seeking, fire seeked event\n if (player.media.seeking) {\n utils.dispatchEvent.call(player, player.media, 'seeked');\n }\n player.media.seeking = false;\n\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n\n utils.dispatchEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n\n // Get quality\n controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));\n\n break;\n\n case 2:\n player.media.paused = true;\n\n utils.dispatchEvent.call(player, player.media, 'pause');\n\n break;\n\n default:\n break;\n }\n\n utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport utils from './utils';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = utils.createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isEmbed) {\n switch (this.provider) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n } else if (this.isHTML5) {\n html5.extend.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport i18n from '../i18n';\nimport utils from '../utils';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.publisherId = player.config.ads.publisherId;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId);\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) {\n utils\n .loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the default tag URL\n get tagUrl() {\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${utils.buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = utils.createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = utils.formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!utils.is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (utils.is.element(seekElement)) {\n const cuePercentage = 100 / this.player.duration * cuePoint;\n const cue = utils.createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Get skippable state\n // TODO: Skip button\n // this.player.debug.warn(this.manager.getAdSkippableState());\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n utils.dispatchEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('seeking', () => {\n time = this.player.currentTime;\n return time;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (utils.is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (utils.is.array(handlers)) {\n handlers.forEach(handler => {\n if (utils.is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!utils.is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!utils.is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport { providers } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n this.type = input.type;\n this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;\n\n // Check for support\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // Create new markup\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n this.media = utils.createElement('video');\n break;\n\n case 'html5:audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n this.media = utils.createElement('div', {\n src: input.sources[0].src,\n });\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!utils.is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport utils from './utils';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (utils.is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return utils.is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (utils.is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.3.6\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport Console from './console';\nimport controls from './controls';\nimport defaults from './defaults';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport { providers, types } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n captions: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n let params = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (utils.is.element(iframe)) {\n // Detect provider\n url = iframe.getAttribute('src');\n this.provider = utils.getProviderByUrl(url);\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n params = utils.getUrlParams(url);\n if (!utils.is.empty(params)) {\n const truthy = [\n '1',\n 'true',\n ];\n\n if (truthy.includes(params.autoplay)) {\n this.config.autoplay = true;\n }\n if (truthy.includes(params.loop)) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(params.playsinline);\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!utils.is.element(this.elements.container)) {\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n }\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n this.ads = new Ads(this);\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!utils.is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !utils.is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = utils.is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (utils.is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (utils.is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // True duration\n const realDuration = this.media ? Number(this.media.duration) : 0;\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!utils.is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n }\n\n if (!utils.is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!utils.is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n let quality = null;\n\n if (!utils.is.empty(input)) {\n quality = Number(input);\n }\n\n if (!utils.is.number(quality) || quality === 0) {\n quality = this.storage.get('quality');\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.selected;\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.default;\n }\n\n if (!this.options.quality.length) {\n return;\n }\n\n if (!this.options.quality.includes(quality)) {\n const closest = utils.closest(this.options.quality, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);\n quality = closest;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n ui.setPoster.call(this);\n }\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);\n\n // Nothing to change...\n if (this.captions.active === show) {\n return;\n }\n\n // Set global\n this.captions.active = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.active);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n /**\n * Set the captions language\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // If empty string is passed, assume disable captions\n if (utils.is.empty(input)) {\n this.toggleCaptions(false);\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // Check for support\n if (!this.options.captions.includes(language)) {\n this.debug.warn(`Unsupported language option: ${language}`);\n return;\n }\n\n // Ensure captions are enabled\n this.toggleCaptions(true);\n\n // Enabled only\n if (language === 'enabled') {\n return;\n }\n\n // If nothing to change, bail\n if (this.language === language) {\n return;\n }\n\n // Update config\n this.captions.language = language;\n\n // Clear caption\n captions.setText.call(this, null);\n\n // Update captions\n captions.setLanguage.call(this);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n }\n\n /**\n * Get the current captions language\n */\n get language() {\n return this.captions.language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} toggle - Whether to show the controls\n */\n toggleControls(toggle) {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Don't hide if no UI support or it's audio\n if (!this.supported.ui || this.isAudio) {\n return;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n\n // Get toggle state if not set\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Events that show the controls\n const showEvents = [\n 'touchstart',\n 'touchmove',\n 'mouseenter',\n 'mousemove',\n 'focusin',\n ];\n\n // Events that delay hiding\n const delayEvents = [\n 'touchmove',\n 'touchend',\n 'mousemove',\n ];\n\n // Whether to show controls\n show = showEvents.includes(toggle.type);\n\n // Delay hiding on move events\n if (delayEvents.includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (!this.touch && toggle.type === 'focusin') {\n delay = 3000;\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer on every call\n clearTimeout(this.timers.controls);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.paused || this.loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.paused || this.loading) {\n return;\n }\n\n // Delay for hiding on touch\n if (this.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || this.playing) {\n this.timers.controls = setTimeout(() => {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Restore transition behaviour\n if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) {\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false);\n }\n\n // Set hideControls class\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, this.config.hideControls);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n utils.removeElement(this.elements.buttons.play);\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n this.listeners.clear();\n\n // Replace the container with the original element provided\n utils.replaceElement(this.elements.original, this.elements.container);\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Type specific stuff\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n case 'html5:audio':\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n case 'youtube:video':\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && utils.is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo:video':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return utils.loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (utils.is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (utils.is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (utils.is.array(selector)) {\n targets = selector.filter(i => utils.is.element(i));\n }\n\n if (utils.is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nexport default Plyr;\n"]}
\ No newline at end of file +{"version":3,"sources":["src/js/utils/is.js","src/js/utils/events.js","src/js/utils/elements.js","src/js/utils/animation.js","src/js/utils/browser.js","src/js/support.js","src/js/html5.js","src/js/utils/arrays.js","src/js/utils/objects.js","src/js/utils/strings.js","src/js/utils/i18n.js","src/js/storage.js","src/js/utils/fetch.js","src/js/utils/loadSprite.js","src/js/utils/time.js","src/js/controls.js","src/js/utils/urls.js","src/js/captions.js","src/js/config/defaults.js","src/js/config/states.js","src/js/config/types.js","src/js/console.js","src/js/fullscreen.js","src/js/utils/loadImage.js","src/js/ui.js","src/js/utils/style.js","src/js/listeners.js","node_modules/loadjs/dist/loadjs.umd.js","src/js/utils/loadScript.js","src/js/plugins/vimeo.js","src/js/plugins/youtube.js","src/js/media.js","src/js/plugins/ads.js","src/js/plugins/previewThumbnails.js","src/js/source.js","src/js/plyr.js"],"names":["getConstructor","input","constructor","instanceOf","Boolean","isNullOrUndefined","isObject","Object","isString","String","isArray","Array","isNodeList","NodeList","isEmpty","length","keys","is","nullOrUndefined","object","number","Number","isNaN","string","boolean","function","Function","array","weakMap","WeakMap","nodeList","element","Element","textNode","Text","event","Event","keyboardEvent","KeyboardEvent","cue","window","TextTrackCue","VTTCue","track","TextTrack","kind","url","URL","startsWith","concat","hostname","e","empty","supportsPassiveListeners","supported","options","defineProperty","get","addEventListener","removeEventListener","toggleListener","callback","_this","this","toggle","arguments","undefined","passive","capture","events","split","forEach","type","eventListeners","push","on","call","off","once","_this2","onceCallback","_len","args","_key","apply","triggerEvent","bubbles","detail","CustomEvent","assign","plyr","dispatchEvent","wrap","elements","wrapper","targets","from","reverse","index","child","cloneNode","parent","parentNode","sibling","nextSibling","appendChild","insertBefore","setAttributes","attributes","entries","filter","_ref","value","_slicedToArray","_ref3","_ref4","key","setAttribute","createElement","text","document","innerText","insertElement","removeElement","removeChild","emptyElement","childNodes","lastChild","replaceElement","newChild","oldChild","replaceChild","getAttributesFromSelector","sel","existingAttributes","existing","s","selector","trim","className","replace","parts","charAt","class","id","toggleHidden","hidden","hide","removeAttribute","toggleClass","force","map","method","classList","contains","hasClass","matches","querySelectorAll","includes","getElements","container","getElement","querySelector","setFocus","tabFocus","focus","preventScroll","config","classNames","transitionEndEvent","WebkitTransition","MozTransition","OTransition","transition","find","style","repaint","setTimeout","offsetHeight","range","browser","isIE","documentMode","isEdge","navigator","userAgent","isWebkit","documentElement","test","isIPhone","platform","isIos","defaultCodecs","audio/ogg","audio/wav","video/webm","video/mp4","video/ogg","support","audio","video","check","provider","playsinline","canPlayInline","api","ui","rangeInput","pip","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","mime","mediaType","isHTML5","media","canPlayType","textTracks","touch","transitions","reducedMotion","matchMedia","html5","getSources","source","getAttribute","getQualityOptions","extend","player","set","_player$media","currentTime","paused","preload","readyState","src","play","load","quality","cancelRequests","blankVideo","debug","log","dedupe","item","indexOf","getDeep","path","reduce","obj","target","sources","shift","_defineProperty","format","toString","match","i","replaceAll","RegExp","toTitleCase","toUpperCase","substr","toLowerCase","toCamelCase","toPascalCase","slice","getHTML","innerHTML","resources","vimeo","youtube","i18n","{seektime}","seekTime","{title}","title","_ref2","Storage","_classCallCheck","enabled","storage","store","localStorage","getItem","json","JSON","parse","setItem","stringify","removeItem","fetch","responseType","Promise","resolve","reject","request","XMLHttpRequest","responseText","response","Error","status","open","send","loadSprite","hasId","exists","getElementById","update","data","body","insertAdjacentElement","useStorage","cached","content","then","result","catch","getHours","Math","trunc","getMinutes","getSeconds","formatTime","time","displayHours","inverted","hours","mins","secs","controls","getIconUrl","cors","iconUrl","location","host","svg4everybody","findElements","selectors","buttons","pause","restart","rewind","fastForward","mute","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","seekTooltip","tooltip","error","warn","toggleNativeControls","createIcon","iconPath","iconPrefix","icon","createElementNS","role","focusable","use","setAttributeNS","createLabel","attr","join","createBadge","badge","menu","createButton","buttonType","props","label","labelPressed","iconPressed","control","button","createRange","min","max","step","autocomplete","aria-label","aria-valuemin","aria-valuemax","aria-valuenow","updateRangeFill","createProgress","aria-hidden","suffixKey","played","suffix","createTime","bindMenuItemShortcuts","menuItem","which","preventDefault","stopPropagation","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","list","_ref$badge","_ref$checked","checked","aria-checked","flex","enumerable","children","node","listeners","bind","currentTrack","speed","parseFloat","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","_this3","current","toFixed","getElementsByTagName","nodeValue","setProgress","buffered","percent","setProperty","updateSeekTooltip","_this4","tooltips","clientRect","getBoundingClientRect","visible","width","pageX","left","timeUpdate","invert","invertTime","seeking","durationUpdate","pow","hasDuration","displayDuration","toggleMenuButton","setting","updateSetting","pane","panels","default","getLabel","setQualityMenu","_this5","checkMenu","getBadge","sort","a","b","sorting","setCaptionsMenu","_this6","tracks","getTracks","toggled","language","unshift","setSpeedMenu","_this7","isVimeo","values","some","popup","firstItem","toggleMenu","show","isMenuItem","getMenuSize","tab","clone","position","opacity","scrollWidth","height","scrollHeight","_this8","size","restore","propertyName","setDownloadLink","download","create","_this9","aria-haspopup","aria-controls","aria-expanded","inner","home","backButton","href","urls","isEmbed","inject","_this10","floor","random","seektime","addProperty","controlPressed","_this$config","labels","parseUrl","parser","buildUrlParams","params","URLSearchParams","setup","isVideo","isYouTube","protocol","blob","createObjectURL","languages","userLanguage","active","trackEvents","_this$captions","meta","currentTrackNode","languageExists","mode","updateCues","setLanguage","activeClass","findTrack","_toConsumableArray","embed","enableTextTrack","has","sortIsDefault","sorted","every","getCurrentTrack","cues","activeCues","getCueAsHTML","cueText","caption","defaults","autoplay","autopause","toggleInvert","ratio","clickToPlay","hideControls","resetOnEnd","disableContextMenu","loop","selected","keyboard","focused","global","fallback","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","start","end","all","reset","disabled","advertisement","qualityBadge","2160","1440","1080","720","576","480","sdk","iframe","googleIMA","editable","embedContainer","poster","posterEnabled","ads","playing","stopped","loading","hover","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","google","publisherId","tagUrl","byline","portrait","transparent","noCookie","rel","showinfo","iv_load_policy","modestbranding","providers","types","noop","Console","console","prototype","onChange","first","last","keyCode","activeElement","shiftKey","toggleFallback","scrollPosition","x","scrollX","y","scrollY","scrollTo","overflow","viewport","head","property","hasProperty","cleanupViewport","part","Fullscreen","prefix","forceFallback","native","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","exit","enter","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","loadImage","minWidth","image","Image","handler","onload","onerror","naturalWidth","addStyleHook","build","checkPlaying","ready","setTitle","setPoster","togglePoster","enable","err","backgroundImage","backgroundSize","toggleControls","checkLoading","clearTimeout","timers","recentTouchSeek","lastSeekTime","Date","now","setAspectRatio","_ratio$split$map2","padding","paddingBottom","offset","transform","Listeners","lastKey","focusTimer","lastKeyDown","handleKey","setTabFocus","firstTouch","code","repeat","altKey","ctrlKey","metaKey","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","usingNative","timeStamp","wasKeyDown","delay","setPlayerSize","measure","rect","resized","_player$fullscreen","isEnter","_setPlayerSize","firstChild","_player$embed$ratio$s2","videoWidth","videoHeight","maxWidth","margin","setGutter","hasAudio","initialized","managerPromise","isAudio","ended","proxy","proxyEvents","_event$detail","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","currentTarget","hasAttribute","done","seekTo","loaded","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","_map2","deltaX","deltaY","direction","sign","abs","module","exports","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","q","splice","executeCallbacks","depsNotFound","success","loadFile","callbackFn","numTries","isCss","doc","async","maxTries","numRetries","beforeCallbackFn","before","pathStripped","onbeforeload","ev","sheet","cssText","defaultPrevented","loadjs","paths","arg1","arg2","fn","numWaiting","loadFiles","deps","bundleIds","r","subscribe","isDefined","factory","loadScript","assurePlaybackState","hasPlayed","Vimeo","gesture","$2","thumbnail_large","pathname","Player","disableTextTrack","stop","restorePause","setVolume","setCurrentTime","setPlaybackRate","name","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","_dimensions","setAutopause","state","getVideoTitle","getCurrentTime","getDuration","getTextTracks","_ref$cues","strippedCues","fragment","createDocumentFragment","getPaused","seconds","parseInt","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getTitle","videoId","getVideoData","items","snippet","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","onError","message","2","5","100","101","150","onPlaybackRateChange","instance","playbackRate","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","getAvailablePlaybackRates","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","displayContainer","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","LOG","adError","getMessage","cancel","contentComplete","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","init","zIndex","destroy","_this11","handlers","_this12","AV_PUBLISHERID","AV_CHANNELID","AV_URL","cb","AV_WIDTH","AV_HEIGHT","AV_CDIM2","PreviewThumbnails","thumbnails","lastMouseMoveTime","mouseDown","loadedImages","thumb","scrubbing","getThumbnails","render","determineContainerAutoSizing","promises","u","getThumbnail","vttDataString","processedList","thumbnail","frames","frame","line","startTime","lineSplit","_lineSplit","_lineSplit$1$split2","w","h","matchTimes","endTime","urlPrefix","substring","lastIndexOf","tempImage","naturalHeight","percentage","mousePosX","showImageAtCurrentTime","toggleThumbContainer","toggleScrubbingContainer","ceil","lastTime","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","findIndex","hasThumb","qualityIndex","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","filename","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","tagName","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","clientHeight","sizeSpecifiedInCSS","thumbWidth","thumbAspectRatio","setThumbContainerPos","seekbarRect","plyrRect","minVal","maxVal","right","clientWidth","previewPos","multiplier","top","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","attribute","change","_sources$","_sources$$provider","crossorigin","Plyr","failed","jQuery","original","getProviderByUrl","search","truthy","searchParams","tabindex","webkitShowPlaybackTargetPicker","isHidden","hiding","eventName","soft","unload","inputIsValid","fauxDuration","realDuration","Infinity","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","updateStorage","prev","curr","closest","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","inline","t"],"mappings":"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","file":"plyr.min.js","sourcesContent":["// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isWeakMap = input => instanceOf(input, WeakMap);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isTextNode = input => getConstructor(input) === Text;\nconst isEvent = input => instanceOf(input, Event);\nconst isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\nconst isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\n\nconst isEmpty = input =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (e) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: this,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise(resolve =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport { toggleListener } from './events';\nimport is from './is';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) {\n return;\n }\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) {\n return;\n }\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) {\n return;\n }\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) {\n return;\n }\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.object(existing) && is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Trap focus inside container\nexport function trapFocus(element = null, toggle = false) {\n if (!is.element(element)) {\n return;\n }\n\n const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = document.activeElement;\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n if (!is.element(element)) {\n return;\n }\n\n // Set regular focus\n element.focus({ preventScroll: true });\n\n // If we want to mimic keyboard focus via tab\n if (tabFocus) {\n toggleClass(element, this.config.classNames.tabFocus);\n }\n}\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport { toggleHidden } from './elements';\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element) {\n setTimeout(() => {\n try {\n toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n toggleHidden(element, false);\n } catch (e) {\n // Do nothing\n }\n }, 0);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isEdge: window.navigator.userAgent.includes('Edge'),\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (e) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map(source => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(source => source.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n // Get first match for requested size\n const source = sources.find(source => Number(source.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n player.play();\n }\n });\n\n // Load new source\n player.media.load();\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport function replaceAll(input = '', find = '', replace = '') {\n return input.replace(\n new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'),\n replace.toString(),\n );\n}\n\n// Convert to title case\nexport function toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n}\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([key, value]) => {\n string = replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(result => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = value => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = value => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`,\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n\n const attributes = Object.assign({}, attr, {\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),\n });\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = Object.assign({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-label': i18n.get(type, this.config),\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on(\n menuItem,\n 'keydown keyup',\n event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![32, 38, 39, 40].includes(event.which)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [32, 39].includes(event.which)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.which !== 32) {\n if (event.which === 40 || (isRadioButton && event.which === 39)) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on(menuItem, 'keyup', event => {\n if (event.which !== 13) {\n return;\n }\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behaviour\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(checked) {\n // Ensure exclusivity\n if (checked) {\n Array.from(menuItem.parentNode.children)\n .filter(node => matches(node, '[role=\"menuitemradio\"]'))\n .forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n event => {\n if (is.keyboardEvent(event) && event.which !== 32) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const value = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Set the speed options\n if (is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, tabFocus = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, tabFocus);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.which === 27) {\n show = false;\n } else if (is.event(input)) {\n const isMenuItem = popup.contains(input.target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', tabFocus = false) {\n const target = document.getElementById(`plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, tabFocus);\n },\n\n // Set the download link\n setDownloadLink() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set download link\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Volume controls\n if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {\n const volume = createElement('div', {\n class: 'plyr__volume',\n });\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n volume.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n controls.createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n\n this.elements.volume = volume;\n }\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n const control = createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n control.appendChild(\n controls.createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on(menuItem, 'click', () => {\n controls.showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on(\n pane,\n 'keydown',\n event => {\n // We only care about <-\n if (event.which !== 37) {\n return;\n }\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n controls.showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on(backButton, 'click', () => {\n controls.showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n control.appendChild(popup);\n container.appendChild(control);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = control;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Download button\n if (this.config.controls.includes('download')) {\n const attributes = {\n element: 'a',\n href: this.download,\n target: '_blank',\n };\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(controls.createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n // Set available quality levels\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n } else if (is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n Object.defineProperty(button, 'pressed', {\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button)\n .filter(Boolean)\n .forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {string} input - the URL to be parsed\n * @param {boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (e) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n track.mode = 'hidden';\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n\n // Update available languages in list\n if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter(track => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(track => track.language === language);\n return !track; // Break iteration if there is a match\n });\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || [])\n .map(cue => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api:\n 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n },\n\n // YouTube plugin\n youtube: {\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { hasClass, toggleClass, trapFocus } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Trigger an event\n triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n\n if (!hasProperty) {\n viewport.content += `,${property}`;\n }\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter(part => part.trim() !== property)\n .join(',');\n }\n\n // Force a repaint as sometimes Safari doesn't want to fill the screen\n setTimeout(() => repaint(this.target), 100);\n }\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n onChange.call(this);\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get usingNative() {\n return Fullscreen.native && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n let mode;\n\n if (this.forceFallback) {\n mode = 'Fallback (forced)';\n } else if (Fullscreen.native) {\n mode = 'Native';\n } else {\n mode = 'Fallback';\n }\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitEnterFullscreen();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/loadImage';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('poster', poster);\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch(err => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw err;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n ui.togglePoster.call(this, true);\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n target.pressed = this.playing;\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls } = this.elements;\n\n if (controls && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now());\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport is from './is';\n\n/* function reduceAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n} */\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n let ratio = input;\n\n if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) {\n ({ ratio } = this.embed);\n }\n\n if (!is.string(ratio)) {\n ({ ratio } = this.config);\n }\n\n const [x, y] = ratio.split(':').map(Number);\n const padding = (100 / x) * y;\n\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n\n return { padding, ratio };\n}\n\nexport default { setAspectRatio };\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { setAspectRatio } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.setTabFocus = this.setTabFocus.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keycodes should we prevent default\n const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n player.forward();\n break;\n\n case 37:\n // Arrow back\n player.rewind();\n break;\n\n case 70:\n // F key\n player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n player.loop = !player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n }\n\n setTabFocus(event) {\n const { player } = this;\n const { elements } = player;\n\n clearTimeout(this.focusTimer);\n\n // Ignore any key other than tab\n if (event.type === 'keydown' && event.which !== 9) {\n return;\n }\n\n // Store reference to event timeStamp\n if (event.type === 'keydown') {\n this.lastKeyDown = event.timeStamp;\n }\n\n // Remove current classes\n const removeCurrent = () => {\n const className = player.config.classNames.tabFocus;\n const current = getElements.call(player, `.${className}`);\n toggleClass(current, className, false);\n };\n\n // Determine if a key was pressed to trigger this event\n const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n // Ignore focus events if a key was pressed prior\n if (event.type === 'focus' && !wasKeyDown) {\n return;\n }\n\n // Remove all current\n removeCurrent();\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n this.focusTimer = setTimeout(() => {\n const focused = document.activeElement;\n\n // Ignore if current focus element isn't inside the player\n if (!elements.container.contains(focused)) {\n return;\n }\n\n toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n }, 10);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n\n // Tab focus detection\n toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);\n }\n\n // Container listeners\n container() {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n event => {\n const { controls } = elements;\n\n // Remove button states for fullscreen\n if (controls && event.type === 'enterfullscreen') {\n controls.pressed = false;\n controls.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Force edge to repaint on exit fullscreen\n // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen\n /* if (browser.isEdge) {\n on.call(player, elements.container, 'exitfullscreen', () => {\n setTimeout(() => repaint(elements.container), 100);\n });\n } */\n\n // Set a gutter for Vimeo\n const setGutter = (ratio, padding, toggle) => {\n if (!player.isVimeo) {\n return;\n }\n\n const target = player.elements.wrapper.firstChild;\n const [, height] = ratio.split(':').map(Number);\n const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number);\n\n target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null;\n target.style.margin = toggle ? '0 auto' : null;\n };\n\n // Resize on fullscreen change\n const setPlayerSize = measure => {\n // If we don't need to measure the viewport\n if (!measure) {\n return setAspectRatio.call(player);\n }\n\n const rect = elements.container.getBoundingClientRect();\n const { width, height } = rect;\n\n return setAspectRatio.call(player, `${width}:${height}`);\n };\n\n const resized = () => {\n window.clearTimeout(timers.resized);\n timers.resized = window.setTimeout(setPlayerSize, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const { target, usingNative } = player.fullscreen;\n\n // Ignore for iOS native\n if (!player.isEmbed || target !== elements.container) {\n return;\n }\n\n const isEnter = event.type === 'enterfullscreen';\n\n // Set the player size when entering fullscreen to viewport size\n const { padding, ratio } = setPlayerSize(isEnter);\n\n // Set Vimeo gutter\n setGutter(ratio, padding, isEnter);\n\n // If not using native fullscreen, we need to check for resizes of viewport\n if (!usingNative) {\n if (isEnter) {\n on.call(player, window, 'resize', resized);\n } else {\n off.call(player, window, 'resize', resized);\n }\n }\n });\n }\n\n // Listen for media events\n media() {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event =>\n controls.durationUpdate.call(player, event),\n );\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n on.call(player, player.media, 'canplay loadeddata', () => {\n toggleHidden(elements.volume, !player.hasAudio);\n toggleHidden(elements.buttons.mute, !player.hasAudio);\n });\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n on.call(player, player.media, 'playing', () => {\n if (!player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (player.ads.enabled && !player.ads.initialized) {\n // Wait for manager response\n player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play());\n }\n });\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, player.play, 'play');\n } else {\n this.proxy(event, player.togglePlay, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadLink.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, event => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n }\n\n // Run default and custom handlers\n proxy(event, defaultHandler, customHandlerKey) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n }\n\n // Trigger custom and default handlers\n bind(element, type, defaultHandler, customHandlerKey, passive = true) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n event => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n }\n\n // Listen for control events\n controls() {\n const { player } = this;\n const { elements } = player;\n\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', player.togglePlay, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward');\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n\n controls.toggleMenu.call(player, event);\n });\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n event => {\n const code = event.which;\n\n // We only care about space and return\n if (![13, 32].includes(code)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (code === 13) {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.which === 27) {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const code = event.keyCode ? event.keyCode : event.which;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n player.play();\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n event => {\n const seek = event.currentTarget;\n\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n event => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, elements, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));\n\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n}\n\nexport default Listeners;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, stripHTML } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n setAspectRatio.call(this);\n\n // Load the API if not already\n if (!is.object(window.Vimeo)) {\n loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams(\n extend(\n {},\n {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n },\n config,\n ),\n );\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = parseId(source);\n\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Get poster, if already set\n const { poster } = player;\n\n // Inject the package\n const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n\n // Get poster image\n fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set and show poster\n ui.setPoster.call(player, url.href).catch(() => {});\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n controls.setDownloadLink.call(player);\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = `${width}:${height}`;\n setAspectRatio.call(this, player.embed.ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/loadImage';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n setAspectRatio.call(this);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (is.string(key) && !is.empty(key)) {\n const url = format(this.config.urls.youtube.api, videoId, key);\n\n fetch(url)\n .then(result => {\n if (is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n\n // Get poster, if already set\n const { poster } = player;\n\n // Replace media element\n const container = createElement('div', { id, poster });\n player.media = replaceElement(container, player.media);\n\n // Id to poster wrapper\n const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src))\n .then(posterSrc => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!posterSrc.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n\n const config = player.config.youtube;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined,\n playerVars: extend(\n {},\n {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n hl: player.config.hl, // iframe interface language\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occured';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.extend.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n event => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n triggerEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1]) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6]) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load() {\n // Togglethe regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) {\n return;\n }\n\n this.getThumbnails().then(() => {\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n this.loaded = true;\n });\n }\n\n // Download VTT files and parse them\n getThumbnails() {\n return new Promise(resolve => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n\n Promise.all(promises).then(() => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n });\n });\n }\n\n // Process individual VTT file\n getThumbnail(url) {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n if (!thumbnail.frames[0].text.startsWith('/')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n }\n\n startMove(event) {\n if (!this.loaded) {\n return;\n }\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n return;\n }\n\n // Wait until media has a duration\n if (!this.player.media.duration) {\n return;\n }\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n\n endMove() {\n this.toggleThumbContainer(false, true);\n }\n\n startScrubbing(event) {\n // Only act on left mouse button (0), or touch device (event.button is false)\n if (event.button === false || event.button === 0) {\n this.mouseDown = true;\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n }\n\n finishScrubbing() {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n }\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners() {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n }\n\n /**\n * Create HTML elements for image containers\n */\n render() {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.container.appendChild(timeContainer);\n\n // Inject the whole thumb\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n }\n\n showImageAtCurrentTime() {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.toggleThumbContainer(true);\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n this.toggleThumbContainer(hasThumb);\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumbnum or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n }\n\n // Show the image that's currently specified in this.showingThumb\n loadImage(qualityIndex = 0) {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () =>\n this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n }\n\n showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n }\n\n // Remove all preview images that aren't the designated current image\n removeOldImages(currentImage) {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n image.dataset.deleting = true;\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n }\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby(thumbNum, forward = true) {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename))\n this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n }\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n }\n\n get currentImageContainer() {\n if (this.mouseDown) {\n return this.elements.scrubbing.container;\n }\n\n return this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n if (this.mouseDown) {\n return this.currentScrubbingImageElement;\n }\n\n return this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer(toggle = false, clearShowing = false) {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n toggleScrubbingContainer(toggle = false) {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n determineContainerAutoSizing() {\n if (this.elements.thumb.imageContainer.clientHeight > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n }\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos() {\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n }\n\n this.setThumbContainerPos();\n }\n\n setThumbContainerPos() {\n const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n const plyrRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const minVal = plyrRect.left - seekbarRect.left + 10;\n const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n if (previewPos < minVal) {\n previewPos = minVal;\n }\n\n if (previewPos > maxVal) {\n previewPos = maxVal;\n }\n\n container.style.left = `${previewPos}px`;\n }\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize() {\n this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`;\n // Can't use media.clientHeight - html5 video goes big and does black bars above and below\n this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`;\n }\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset(previewImage, frame) {\n if (!this.usingSprites) {\n return;\n }\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;\n previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;\n previewImage.style.left = `-${frame.x * multiplier}px`;\n previewImage.style.top = `-${frame.y * multiplier}px`;\n }\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Reload thumbnails\n if (this.previewThumbnails) {\n this.previewThumbnails.load();\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.4.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/previewThumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { cloneDeep, extend } from './utils/objects';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div', { tabindex: 0 });\n wrap(this.media, this.elements.container);\n }\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n this.increaseVolume(-step);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {number} - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} [toggle] - Whether to show the controls\n */\n toggleControls(toggle) {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n on.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Add event listeners once\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n once(event, callback) {\n once.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.min.mjs b/dist/plyr.min.mjs new file mode 100644 index 00000000..913b5a35 --- /dev/null +++ b/dist/plyr.min.mjs @@ -0,0 +1 @@ +function _defineProperties(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function _createClass(e,t,i){return t&&_defineProperties(e.prototype,t),i&&_defineProperties(e,i),e}function _defineProperty(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function _slicedToArray(e,t){return _arrayWithHoles(e)||_iterableToArrayLimit(e,t)||_nonIterableRest()}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_nonIterableSpread()}function _arrayWithoutHoles(e){if(Array.isArray(e)){for(var t=0,i=new Array(e.length);t<e.length;t++)i[t]=e[t];return i}}function _arrayWithHoles(e){if(Array.isArray(e))return e}function _iterableToArray(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function _iterableToArrayLimit(e,t){var i=[],n=!0,s=!1,a=void 0;try{for(var o,r=e[Symbol.iterator]();!(n=(o=r.next()).done)&&(i.push(o.value),!t||i.length!==t);n=!0);}catch(e){s=!0,a=e}finally{try{n||null==r.return||r.return()}finally{if(s)throw a}}return i}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}var getConstructor=function(e){return null!=e?e.constructor:null},instanceOf=function(e,t){return Boolean(e&&t&&e instanceof t)},isNullOrUndefined=function(e){return null==e},isObject=function(e){return getConstructor(e)===Object},isNumber=function(e){return getConstructor(e)===Number&&!Number.isNaN(e)},isString=function(e){return getConstructor(e)===String},isBoolean=function(e){return getConstructor(e)===Boolean},isFunction=function(e){return getConstructor(e)===Function},isArray=function(e){return Array.isArray(e)},isWeakMap=function(e){return instanceOf(e,WeakMap)},isNodeList=function(e){return instanceOf(e,NodeList)},isElement=function(e){return instanceOf(e,Element)},isTextNode=function(e){return getConstructor(e)===Text},isEvent=function(e){return instanceOf(e,Event)},isKeyboardEvent=function(e){return instanceOf(e,KeyboardEvent)},isCue=function(e){return instanceOf(e,window.TextTrackCue)||instanceOf(e,window.VTTCue)},isTrack=function(e){return instanceOf(e,TextTrack)||!isNullOrUndefined(e)&&isString(e.kind)},isEmpty=function(e){return isNullOrUndefined(e)||(isString(e)||isArray(e)||isNodeList(e))&&!e.length||isObject(e)&&!Object.keys(e).length},isUrl=function(e){if(instanceOf(e,window.URL))return!0;if(!isString(e))return!1;var t=e;e.startsWith("http://")&&e.startsWith("https://")||(t="http://".concat(e));try{return!isEmpty(new URL(t).hostname)}catch(e){return!1}},is={nullOrUndefined:isNullOrUndefined,object:isObject,number:isNumber,string:isString,boolean:isBoolean,function:isFunction,array:isArray,weakMap:isWeakMap,nodeList:isNodeList,element:isElement,textNode:isTextNode,event:isEvent,keyboardEvent:isKeyboardEvent,cue:isCue,track:isTrack,url:isUrl,empty:isEmpty},supportsPassiveListeners=function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(e){}return e}();function toggleListener(e,t,i){var n=this,s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(e&&"addEventListener"in e&&!is.empty(t)&&is.function(i)){var r=t.split(" "),l=o;supportsPassiveListeners&&(l={passive:a,capture:o}),r.forEach(function(t){n&&n.eventListeners&&s&&n.eventListeners.push({element:e,type:t,callback:i,options:l}),e[s?"addEventListener":"removeEventListener"](t,i,l)})}}function on(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,t,i,!0,n,s)}function off(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,t,i,!1,n,s)}function once(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,i,function o(){off(e,i,o,s,a);for(var r=arguments.length,l=new Array(r),c=0;c<r;c++)l[c]=arguments[c];n.apply(t,l)},!0,s,a)}function triggerEvent(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(is.element(e)&&!is.empty(t)){var s=new CustomEvent(t,{bubbles:i,detail:Object.assign({},n,{plyr:this})});e.dispatchEvent(s)}}function unbindListeners(){this&&this.eventListeners&&(this.eventListeners.forEach(function(e){var t=e.element,i=e.type,n=e.callback,s=e.options;t.removeEventListener(i,n,s)}),this.eventListeners=[])}function ready(){var e=this;return new Promise(function(t){return e.ready?setTimeout(t,0):on.call(e,e.elements.container,"ready",t)}).then(function(){})}function wrap(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})}function setAttributes(e,t){is.element(e)&&!is.empty(t)&&Object.entries(t).filter(function(e){var t=_slicedToArray(e,2)[1];return!is.nullOrUndefined(t)}).forEach(function(t){var i=_slicedToArray(t,2),n=i[0],s=i[1];return e.setAttribute(n,s)})}function createElement(e,t,i){var n=document.createElement(e);return is.object(t)&&setAttributes(n,t),is.string(i)&&(n.innerText=i),n}function insertAfter(e,t){is.element(e)&&is.element(t)&&t.parentNode.insertBefore(e,t.nextSibling)}function insertElement(e,t,i,n){is.element(t)&&t.appendChild(createElement(e,i,n))}function removeElement(e){is.nodeList(e)||is.array(e)?Array.from(e).forEach(removeElement):is.element(e)&&is.element(e.parentNode)&&e.parentNode.removeChild(e)}function emptyElement(e){if(is.element(e))for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1}function replaceElement(e,t){return is.element(t)&&is.element(t.parentNode)&&is.element(e)?(t.parentNode.replaceChild(e,t),e):null}function getAttributesFromSelector(e,t){if(!is.string(e)||is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),s=t.replace(".",""),a=t.replace(/[[\]]/g,"").split("="),o=a[0],r=a.length>1?a[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":is.object(n)&&is.string(n.class)&&(n.class+=" ".concat(s)),i.class=s;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i}function toggleHidden(e,t){if(is.element(e)){var i=t;is.boolean(i)||(i=!e.hidden),i?e.setAttribute("hidden",""):e.removeAttribute("hidden")}}function toggleClass(e,t,i){if(is.nodeList(e))return Array.from(e).map(function(e){return toggleClass(e,t,i)});if(is.element(e)){var n="toggle";return void 0!==i&&(n=i?"add":"remove"),e.classList[n](t),e.classList.contains(t)}return!1}function hasClass(e,t){return is.element(e)&&e.classList.contains(t)}function matches(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function getElements(e){return this.elements.container.querySelectorAll(e)}function getElement(e){return this.elements.container.querySelector(e)}function trapFocus(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(is.element(e)){var i=getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),n=i[0],s=i[i.length-1];toggleListener.call(this,this.elements.container,"keydown",function(e){if("Tab"===e.key&&9===e.keyCode){var t=document.activeElement;t!==s||e.shiftKey?t===n&&e.shiftKey&&(s.focus(),e.preventDefault()):(n.focus(),e.preventDefault())}},t,!1)}}function setFocus(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];is.element(e)&&(e.focus({preventScroll:!0}),t&&toggleClass(e,this.config.classNames.tabFocus))}var transitionEndEvent=function(){var e=document.createElement("span"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},i=Object.keys(t).find(function(t){return void 0!==e.style[t]});return!!is.string(i)&&t[i]}();function repaint(e){setTimeout(function(){try{toggleHidden(e,!0),e.offsetHeight,toggleHidden(e,!1)}catch(e){}},0)}var browser={isIE:!!document.documentMode,isEdge:window.navigator.userAgent.includes("Edge"),isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)},defaultCodecs={"audio/ogg":"vorbis","audio/wav":"1","video/webm":"vp8, vorbis","video/mp4":"avc1.42E01E, mp4a.40.2","video/ogg":"theora"},support={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,i){var n=browser.isIPhone&&i&&support.playsinline,s=support[e]||"html5"!==t;return{api:s,ui:s&&support.rangeInput&&("video"!==e||!browser.isIPhone||n)}},pip:!(browser.isIPhone||!is.function(createElement("video").webkitSetPresentationMode)&&(!document.pictureInPictureEnabled||createElement("video").disablePictureInPicture)),airplay:is.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){if(is.empty(e))return!1;var t=_slicedToArray(e.split("/"),1)[0],i=e;if(!this.isHTML5||t!==this.type)return!1;Object.keys(defaultCodecs).includes(i)&&(i+='; codecs="'.concat(defaultCodecs[e],'"'));try{return Boolean(i&&this.media.canPlayType(i).replace(/no/,""))}catch(e){return!1}},textTracks:"textTracks"in document.createElement("video"),rangeInput:function(){var e=document.createElement("input");return e.type="range","range"===e.type}(),touch:"ontouchstart"in document.documentElement,transitions:!1!==transitionEndEvent,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},html5={getSources:function(){var e=this;return this.isHTML5?Array.from(this.media.querySelectorAll("source")).filter(function(t){var i=t.getAttribute("type");return!!is.empty(i)||support.mime.call(e,i)}):[]},getQualityOptions:function(){return html5.getSources.call(this).map(function(e){return Number(e.getAttribute("size"))}).filter(Boolean)},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=html5.getSources.call(e).find(function(t){return t.getAttribute("src")===e.source});return t&&Number(t.getAttribute("size"))},set:function(t){var i=html5.getSources.call(e).find(function(e){return Number(e.getAttribute("size"))===t});if(i){var n=e.media,s=n.currentTime,a=n.paused,o=n.preload,r=n.readyState;e.media.src=i.getAttribute("src"),("none"!==o||r)&&(e.once("loadedmetadata",function(){e.currentTime=s,a||e.play()}),e.media.load()),triggerEvent.call(e,e.media,"qualitychange",!1,{quality:t})}}})}},cancelRequests:function(){this.isHTML5&&(removeElement(html5.getSources.call(this)),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}};function dedupe(e){return is.array(e)?e.filter(function(t,i){return e.indexOf(t)===i}):e}function closest(e,t){return is.array(e)&&e.length?e.reduce(function(e,i){return Math.abs(i-t)<Math.abs(e-t)?i:e}):null}function cloneDeep(e){return JSON.parse(JSON.stringify(e))}function getDeep(e,t){return t.split(".").reduce(function(e,t){return e&&e[t]},e)}function extend(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,i=new Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];if(!i.length)return e;var s=i.shift();return is.object(s)?(Object.keys(s).forEach(function(t){is.object(s[t])?(Object.keys(e).includes(t)||Object.assign(e,_defineProperty({},t,{})),extend(e[t],s[t])):Object.assign(e,_defineProperty({},t,s[t]))}),extend.apply(void 0,[e].concat(i))):e}function generateId(e){return"".concat(e,"-").concat(Math.floor(1e4*Math.random()))}function format(e){for(var t=arguments.length,i=new Array(t>1?t-1:0),n=1;n<t;n++)i[n-1]=arguments[n];return is.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return i[t].toString()})}function getPercentage(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)}function replaceAll(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"),i.toString())}function toTitleCase(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}function toPascalCase(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=replaceAll(e,"-"," "),e=replaceAll(e,"_"," "),replaceAll(e=toTitleCase(e)," ","")}function toCamelCase(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=toPascalCase(e)).charAt(0).toLowerCase()+e.slice(1)}function stripHTML(e){var t=document.createDocumentFragment(),i=document.createElement("div");return t.appendChild(i),i.innerHTML=e,t.firstChild.innerText}function getHTML(e){var t=document.createElement("div");return t.appendChild(e),t.innerHTML}var resources={pip:"PIP",airplay:"AirPlay",html5:"HTML5",vimeo:"Vimeo",youtube:"YouTube"},i18n={get:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(is.empty(e)||is.empty(t))return"";var i=getDeep(t.i18n,e);if(is.empty(i))return Object.keys(resources).includes(e)?resources[e]:"";var n={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(n).forEach(function(e){var t=_slicedToArray(e,2),n=t[0],s=t[1];i=replaceAll(i,n,s)}),i}},Storage=function(){function e(t){_classCallCheck(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return _createClass(e,[{key:"get",value:function(t){if(!e.supported||!this.enabled)return null;var i=window.localStorage.getItem(this.key);if(is.empty(i))return null;var n=JSON.parse(i);return is.string(t)&&t.length?n[t]:n}},{key:"set",value:function(t){if(e.supported&&this.enabled&&is.object(t)){var i=this.get();is.empty(i)&&(i={}),extend(i,t),window.localStorage.setItem(this.key,JSON.stringify(i))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();function fetch(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(i,n){try{var s=new XMLHttpRequest;if(!("withCredentials"in s))return;s.addEventListener("load",function(){if("text"===t)try{i(JSON.parse(s.responseText))}catch(e){i(s.responseText)}else i(s.response)}),s.addEventListener("error",function(){throw new Error(s.status)}),s.open("GET",e,!0),s.responseType=t,s.send()}catch(e){n(e)}})}function loadSprite(e,t){if(is.string(e)){var i=is.string(t),n=function(){return null!==document.getElementById(t)},s=function(e,t){e.innerHTML=t,i&&n()||document.body.insertAdjacentElement("afterbegin",e)};if(!i||!n()){var a=Storage.supported,o=document.createElement("div");if(o.setAttribute("hidden",""),i&&o.setAttribute("id",t),a){var r=window.localStorage.getItem("".concat("cache","-").concat(t));if(null!==r){var l=JSON.parse(r);s(o,l.content)}}fetch(e).then(function(e){is.empty(e)||(a&&window.localStorage.setItem("".concat("cache","-").concat(t),JSON.stringify({content:e})),s(o,e))}).catch(function(){})}}}var getHours=function(e){return Math.trunc(e/60/60%60,10)},getMinutes=function(e){return Math.trunc(e/60%60,10)},getSeconds=function(e){return Math.trunc(e%60,10)};function formatTime(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!is.number(e))return formatTime(null,t,i);var n=function(e){return"0".concat(e).slice(-2)},s=getHours(e),a=getMinutes(e),o=getSeconds(e);return s=t||s>0?"".concat(s,":"):"","".concat(i&&e>0?"-":"").concat(s).concat(n(a),":").concat(n(o))}var controls={getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||browser.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:getElements.call(this,this.config.selectors.buttons.play),pause:getElement.call(this,this.config.selectors.buttons.pause),restart:getElement.call(this,this.config.selectors.buttons.restart),rewind:getElement.call(this,this.config.selectors.buttons.rewind),fastForward:getElement.call(this,this.config.selectors.buttons.fastForward),mute:getElement.call(this,this.config.selectors.buttons.mute),pip:getElement.call(this,this.config.selectors.buttons.pip),airplay:getElement.call(this,this.config.selectors.buttons.airplay),settings:getElement.call(this,this.config.selectors.buttons.settings),captions:getElement.call(this,this.config.selectors.buttons.captions),fullscreen:getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:getElement.call(this,this.config.selectors.inputs.seek),volume:getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:getElement.call(this,this.config.selectors.display.buffer),currentTime:getElement.call(this,this.config.selectors.display.currentTime),duration:getElement.call(this,this.config.selectors.display.duration)},is.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip))),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var i=controls.getIconUrl.call(this),n="".concat(i.cors?"":i.url,"#").concat(this.config.iconPrefix),s=document.createElementNS("http://www.w3.org/2000/svg","svg");setAttributes(s,extend(t,{role:"presentation",focusable:"false"}));var a=document.createElementNS("http://www.w3.org/2000/svg","use"),o="".concat(n,"-").concat(e);return"href"in a&&a.setAttributeNS("http://www.w3.org/1999/xlink","href",o),a.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),s.appendChild(a),s},createLabel:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=i18n.get(e,this.config);return createElement("span",Object.assign({},t,{class:[t.class,this.config.classNames.hidden].filter(Boolean).join(" ")}),i)},createBadge:function(e){if(is.empty(e))return null;var t=createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=Object.assign({},t),n=toCamelCase(e),s={element:"button",toggle:!1,label:null,icon:null,labelPressed:null,iconPressed:null};switch(["element","icon","label"].forEach(function(e){Object.keys(i).includes(e)&&(s[e]=i[e],delete i[e])}),"button"!==s.element||Object.keys(i).includes("type")||(i.type="button"),Object.keys(i).includes("class")?i.class.includes(this.config.classNames.control)||(i.class+=" ".concat(this.config.classNames.control)):i.class=this.config.classNames.control,e){case"play":s.toggle=!0,s.label="play",s.labelPressed="pause",s.icon="play",s.iconPressed="pause";break;case"mute":s.toggle=!0,s.label="mute",s.labelPressed="unmute",s.icon="volume",s.iconPressed="muted";break;case"captions":s.toggle=!0,s.label="enableCaptions",s.labelPressed="disableCaptions",s.icon="captions-off",s.iconPressed="captions-on";break;case"fullscreen":s.toggle=!0,s.label="enterFullscreen",s.labelPressed="exitFullscreen",s.icon="enter-fullscreen",s.iconPressed="exit-fullscreen";break;case"play-large":i.class+=" ".concat(this.config.classNames.control,"--overlaid"),n="play",s.label="play",s.icon="play";break;default:is.empty(s.label)&&(s.label=n),is.empty(s.icon)&&(s.icon=e)}var a=createElement(s.element);return s.toggle?(a.appendChild(controls.createIcon.call(this,s.iconPressed,{class:"icon--pressed"})),a.appendChild(controls.createIcon.call(this,s.icon,{class:"icon--not-pressed"})),a.appendChild(controls.createLabel.call(this,s.labelPressed,{class:"label--pressed"})),a.appendChild(controls.createLabel.call(this,s.label,{class:"label--not-pressed"}))):(a.appendChild(controls.createIcon.call(this,s.icon)),a.appendChild(controls.createLabel.call(this,s.label))),extend(i,getAttributesFromSelector(this.config.selectors.buttons[n],i)),setAttributes(a,i),"play"===n?(is.array(this.elements.buttons[n])||(this.elements.buttons[n]=[]),this.elements.buttons[n].push(a)):this.elements.buttons[n]=a,a},createRange:function(e,t){var i=createElement("input",extend(getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-label":i18n.get(e,this.config),"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=i,controls.updateRangeFill.call(this,i),i},createProgress:function(e,t){var i=createElement("progress",extend(getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){i.appendChild(createElement("span",null,"0"));var n={played:"played",buffer:"buffered"}[e],s=n?i18n.get(n,this.config):"";i.innerText="% ".concat(s.toLowerCase())}return this.elements.display[e]=i,i},createTime:function(e){var t=getAttributesFromSelector(this.config.selectors.display[e]),i=createElement("div",extend(t,{class:"".concat(this.config.classNames.display.time," ").concat(t.class?t.class:"").trim(),"aria-label":i18n.get(e,this.config)}),"00:00");return this.elements.display[e]=i,i},bindMenuItemShortcuts:function(e,t){var i=this;on(e,"keydown keyup",function(n){if([32,38,39,40].includes(n.which)&&(n.preventDefault(),n.stopPropagation(),"keydown"!==n.type)){var s,a=matches(e,'[role="menuitemradio"]');if(!a&&[32,39].includes(n.which))controls.showMenuPanel.call(i,t,!0);else 32!==n.which&&(40===n.which||a&&39===n.which?(s=e.nextElementSibling,is.element(s)||(s=e.parentNode.firstElementChild)):(s=e.previousElementSibling,is.element(s)||(s=e.parentNode.lastElementChild)),setFocus.call(i,s,!0))}},!1),on(e,"keyup",function(e){13===e.which&&controls.focusFirstMenuItem.call(i,null,!0)})},createMenuItem:function(e){var t=this,i=e.value,n=e.list,s=e.type,a=e.title,o=e.badge,r=void 0===o?null:o,l=e.checked,c=void 0!==l&&l,u=getAttributesFromSelector(this.config.selectors.inputs[s]),d=createElement("button",extend(u,{type:"button",role:"menuitemradio",class:"".concat(this.config.classNames.control," ").concat(u.class?u.class:"").trim(),"aria-checked":c,value:i})),h=createElement("span");h.innerHTML=a,is.element(r)&&h.appendChild(r),d.appendChild(h),Object.defineProperty(d,"checked",{enumerable:!0,get:function(){return"true"===d.getAttribute("aria-checked")},set:function(e){e&&Array.from(d.parentNode.children).filter(function(e){return matches(e,'[role="menuitemradio"]')}).forEach(function(e){return e.setAttribute("aria-checked","false")}),d.setAttribute("aria-checked",e?"true":"false")}}),this.listeners.bind(d,"click keyup",function(e){if(!is.keyboardEvent(e)||32===e.which){switch(e.preventDefault(),e.stopPropagation(),d.checked=!0,s){case"language":t.currentTrack=Number(i);break;case"quality":t.quality=i;break;case"speed":t.speed=parseFloat(i)}controls.showMenuPanel.call(t,"home",is.keyboardEvent(e))}},s,!1),controls.bindMenuItemShortcuts.call(this,d,s),n.appendChild(d)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return is.number(e)?formatTime(e,getHours(this.duration)>0,t):e},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];is.element(e)&&is.number(t)&&(e.innerText=controls.formatTime(t,i))},updateVolume:function(){this.supported.ui&&(is.element(this.elements.inputs.volume)&&controls.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),is.element(this.elements.buttons.mute)&&(this.elements.buttons.mute.pressed=this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;is.element(e)&&(e.value=t,controls.updateRangeFill.call(this,e))},updateProgress:function(e){var t=this;if(this.supported.ui&&is.event(e)){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":case"seeked":i=getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&controls.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":!function(e,i){var n=is.number(i)?i:0,s=is.element(e)?e:t.elements.display.buffer;if(is.element(s)){s.value=n;var a=s.getElementsByTagName("span")[0];is.element(a)&&(a.childNodes[0].nodeValue=n)}}(this.elements.display.buffer,100*this.buffered)}}},updateRangeFill:function(e){var t=is.event(e)?e.target:e;if(is.element(t)&&"range"===t.getAttribute("type")){if(matches(t,this.config.selectors.inputs.seek)){t.setAttribute("aria-valuenow",this.currentTime);var i=controls.formatTime(this.currentTime),n=controls.formatTime(this.duration),s=i18n.get("seekLabel",this.config);t.setAttribute("aria-valuetext",s.replace("{currentTime}",i).replace("{duration}",n))}else if(matches(t,this.config.selectors.inputs.volume)){var a=100*t.value;t.setAttribute("aria-valuenow",a),t.setAttribute("aria-valuetext","".concat(a.toFixed(1),"%"))}else t.setAttribute("aria-valuenow",t.value);browser.isWebkit&&t.style.setProperty("--value","".concat(t.value/t.max*100,"%"))}},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&is.element(this.elements.inputs.seek)&&is.element(this.elements.display.seekTooltip)&&0!==this.duration){var i=0,n=this.elements.progress.getBoundingClientRect(),s="".concat(this.config.classNames.tooltip,"--visible"),a=function(e){toggleClass(t.elements.display.seekTooltip,s,e)};if(this.touch)a(!1);else{if(is.event(e))i=100/n.width*(e.pageX-n.left);else{if(!hasClass(this.elements.display.seekTooltip,s))return;i=parseFloat(this.elements.display.seekTooltip.style.left,10)}i<0?i=0:i>100&&(i=100),controls.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*i),this.elements.display.seekTooltip.style.left="".concat(i,"%"),is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&a("mouseenter"===e.type)}}},timeUpdate:function(e){var t=!is.element(this.elements.display.duration)&&this.config.invertTime;controls.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||controls.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui&&(this.config.invertTime||!this.currentTime)){if(this.duration>=Math.pow(2,32))return toggleHidden(this.elements.display.currentTime,!0),void toggleHidden(this.elements.progress,!0);is.element(this.elements.inputs.seek)&&this.elements.inputs.seek.setAttribute("aria-valuemax",this.duration);var e=is.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&controls.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&controls.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),controls.updateSeekTooltip.call(this)}},toggleMenuButton:function(e,t){toggleHidden(this.elements.settings.buttons[e],!t)},updateSetting:function(e,t,i){var n=this.elements.settings.panels[e],s=null,a=t;if("captions"===e)s=this.currentTrack;else{if(s=is.empty(i)?this[e]:i,is.empty(s)&&(s=this.config[e].default),!is.empty(this.options[e])&&!this.options[e].includes(s))return void this.debug.warn("Unsupported value of '".concat(s,"' for ").concat(e));if(!this.config[e].options.includes(s))return void this.debug.warn("Disabled value of '".concat(s,"' for ").concat(e))}if(is.element(a)||(a=n&&n.querySelector('[role="menu"]')),is.element(a)){this.elements.settings.buttons[e].querySelector(".".concat(this.config.classNames.menu.value)).innerHTML=controls.getLabel.call(this,e,s);var o=a&&a.querySelector('[value="'.concat(s,'"]'));is.element(o)&&(o.checked=!0)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?i18n.get("normal",this.config):"".concat(t,"×");case"quality":if(is.number(t)){var i=i18n.get("qualityLabel.".concat(t),this.config);return i.length?i:"".concat(t,"p")}return toTitleCase(t);case"captions":return captions.getLabel.call(this);default:return null}},setQualityMenu:function(e){var t=this;if(is.element(this.elements.settings.panels.quality)){var i=this.elements.settings.panels.quality.querySelector('[role="menu"]');is.array(e)&&(this.options.quality=dedupe(e).filter(function(e){return t.config.quality.options.includes(e)}));var n=!is.empty(this.options.quality)&&this.options.quality.length>1;if(controls.toggleMenuButton.call(this,"quality",n),emptyElement(i),controls.checkMenu.call(this),n){var s=function(e){var i=i18n.get("qualityBadge.".concat(e),t.config);return i.length?controls.createBadge.call(t,i):null};this.options.quality.sort(function(e,i){var n=t.config.quality.options;return n.indexOf(e)>n.indexOf(i)?1:-1}).forEach(function(e){controls.createMenuItem.call(t,{value:e,list:i,type:"quality",title:controls.getLabel.call(t,"quality",e),badge:s(e)})}),controls.updateSetting.call(this,"quality",i)}}},setCaptionsMenu:function(){var e=this;if(is.element(this.elements.settings.panels.captions)){var t=this.elements.settings.panels.captions.querySelector('[role="menu"]'),i=captions.getTracks.call(this),n=Boolean(i.length);if(controls.toggleMenuButton.call(this,"captions",n),emptyElement(t),controls.checkMenu.call(this),n){var s=i.map(function(i,n){return{value:n,checked:e.captions.toggled&&e.currentTrack===n,title:captions.getLabel.call(e,i),badge:i.language&&controls.createBadge.call(e,i.language.toUpperCase()),list:t,type:"language"}});s.unshift({value:-1,checked:!this.captions.toggled,title:i18n.get("disabled",this.config),list:t,type:"language"}),s.forEach(controls.createMenuItem.bind(this)),controls.updateSetting.call(this,"captions",t)}}},setSpeedMenu:function(e){var t=this;if(is.element(this.elements.settings.panels.speed)){var i=this.elements.settings.panels.speed.querySelector('[role="menu"]');is.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var n=!is.empty(this.options.speed)&&this.options.speed.length>1;controls.toggleMenuButton.call(this,"speed",n),emptyElement(i),controls.checkMenu.call(this),n&&(this.options.speed.forEach(function(e){controls.createMenuItem.call(t,{value:e,list:i,type:"speed",title:controls.getLabel.call(t,"speed",e)})}),controls.updateSetting.call(this,"speed",i))}},checkMenu:function(){var e=this.elements.settings.buttons,t=!is.empty(e)&&Object.values(e).some(function(e){return!e.hidden});toggleHidden(this.elements.settings.menu,!t)},focusFirstMenuItem:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!this.elements.settings.popup.hidden){var i=e;is.element(i)||(i=Object.values(this.elements.settings.panels).find(function(e){return!e.hidden}));var n=i.querySelector('[role^="menuitem"]');setFocus.call(this,n,t)}},toggleMenu:function(e){var t=this.elements.settings.popup,i=this.elements.buttons.settings;if(is.element(t)&&is.element(i)){var n=t.hidden,s=n;if(is.boolean(e))s=e;else if(is.keyboardEvent(e)&&27===e.which)s=!1;else if(is.event(e)){var a=t.contains(e.target);if(a||!a&&e.target!==i&&s)return}i.setAttribute("aria-expanded",s),toggleHidden(t,!s),toggleClass(this.elements.container,this.config.classNames.menu.open,s),s&&is.keyboardEvent(e)?controls.focusFirstMenuItem.call(this,null,!0):s||n||setFocus.call(this,i,is.keyboardEvent(e))}},getMenuSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return removeElement(t),{width:i,height:n}},showMenuPanel:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=document.getElementById("plyr-settings-".concat(this.id,"-").concat(t));if(is.element(n)){var s=n.parentNode,a=Array.from(s.children).find(function(e){return!e.hidden});if(support.transitions&&!support.reducedMotion){s.style.width="".concat(a.scrollWidth,"px"),s.style.height="".concat(a.scrollHeight,"px");var o=controls.getMenuSize.call(this,n);on.call(this,s,transitionEndEvent,function t(i){i.target===s&&["width","height"].includes(i.propertyName)&&(s.style.width="",s.style.height="",off.call(e,s,transitionEndEvent,t))}),s.style.width="".concat(o.width,"px"),s.style.height="".concat(o.height,"px")}toggleHidden(a,!0),toggleHidden(n,!1),controls.focusFirstMenuItem.call(this,n,i)}},setDownloadLink:function(){var e=this.elements.buttons.download;is.element(e)&&e.setAttribute("href",this.download)},create:function(e){var t=this,i=createElement("div",getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(controls.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(controls.createButton.call(this,"rewind")),this.config.controls.includes("play")&&i.appendChild(controls.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&i.appendChild(controls.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=createElement("div",getAttributesFromSelector(this.config.selectors.progress));if(n.appendChild(controls.createRange.call(this,"seek",{id:"plyr-seek-".concat(e.id)})),n.appendChild(controls.createProgress.call(this,"buffer")),this.config.tooltips.seek){var s=createElement("span",{class:this.config.classNames.tooltip},"00:00");n.appendChild(s),this.elements.display.seekTooltip=s}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(controls.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(controls.createTime.call(this,"duration")),this.config.controls.includes("mute")||this.config.controls.includes("volume")){var a=createElement("div",{class:"plyr__volume"});if(this.config.controls.includes("mute")&&a.appendChild(controls.createButton.call(this,"mute")),this.config.controls.includes("volume")){var o={max:1,step:.05,value:this.config.volume};a.appendChild(controls.createRange.call(this,"volume",extend(o,{id:"plyr-volume-".concat(e.id)}))),this.elements.volume=a}i.appendChild(a)}if(this.config.controls.includes("captions")&&i.appendChild(controls.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!is.empty(this.config.settings)){var r=createElement("div",{class:"plyr__menu",hidden:""});r.appendChild(controls.createButton.call(this,"settings",{"aria-haspopup":!0,"aria-controls":"plyr-settings-".concat(e.id),"aria-expanded":!1}));var l=createElement("div",{class:"plyr__menu__container",id:"plyr-settings-".concat(e.id),hidden:""}),c=createElement("div"),u=createElement("div",{id:"plyr-settings-".concat(e.id,"-home")}),d=createElement("div",{role:"menu"});u.appendChild(d),c.appendChild(u),this.elements.settings.panels.home=u,this.config.settings.forEach(function(i){var n=createElement("button",extend(getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--forward"),role:"menuitem","aria-haspopup":!0,hidden:""}));controls.bindMenuItemShortcuts.call(t,n,i),on(n,"click",function(){controls.showMenuPanel.call(t,i,!1)});var s=createElement("span",null,i18n.get(i,t.config)),a=createElement("span",{class:t.config.classNames.menu.value});a.innerHTML=e[i],s.appendChild(a),n.appendChild(s),d.appendChild(n);var o=createElement("div",{id:"plyr-settings-".concat(e.id,"-").concat(i),hidden:""}),r=createElement("button",{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--back")});r.appendChild(createElement("span",{"aria-hidden":!0},i18n.get(i,t.config))),r.appendChild(createElement("span",{class:t.config.classNames.hidden},i18n.get("menuBack",t.config))),on(o,"keydown",function(e){37===e.which&&(e.preventDefault(),e.stopPropagation(),controls.showMenuPanel.call(t,"home",!0))},!1),on(r,"click",function(){controls.showMenuPanel.call(t,"home",!1)}),o.appendChild(r),o.appendChild(createElement("div",{role:"menu"})),c.appendChild(o),t.elements.settings.buttons[i]=n,t.elements.settings.panels[i]=o}),l.appendChild(c),r.appendChild(l),i.appendChild(r),this.elements.settings.popup=l,this.elements.settings.menu=r}if(this.config.controls.includes("pip")&&support.pip&&i.appendChild(controls.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&support.airplay&&i.appendChild(controls.createButton.call(this,"airplay")),this.config.controls.includes("download")){var h={element:"a",href:this.download,target:"_blank"},m=this.config.urls.download;!is.url(m)&&this.isEmbed&&extend(h,{icon:"logo-".concat(this.provider),label:this.provider}),i.appendChild(controls.createButton.call(this,"download",h))}return this.config.controls.includes("fullscreen")&&i.appendChild(controls.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(controls.createButton.call(this,"play-large")),this.elements.controls=i,this.isHTML5&&controls.setQualityMenu.call(this,html5.getQualityOptions.call(this)),controls.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=controls.getIconUrl.call(this);t.cors&&loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;this.elements.controls=null;var n={id:this.id,seektime:this.config.seekTime,title:this.config.title},s=!0;is.function(this.config.controls)&&(this.config.controls=this.config.controls.call(this,n)),this.config.controls||(this.config.controls=[]),is.element(this.config.controls)||is.string(this.config.controls)?i=this.config.controls:(i=controls.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:captions.getLabel.call(this)}),s=!1);var a,o=function(e){var t=e;return Object.entries(n).forEach(function(e){var i=_slicedToArray(e,2),n=i[0],s=i[1];t=replaceAll(t,"{".concat(n,"}"),s)}),t};if(s&&(is.string(this.config.controls)?i=o(i):is.element(i)&&(i.innerHTML=o(i.innerHTML))),is.string(this.config.selectors.controls.container)&&(a=document.querySelector(this.config.selectors.controls.container)),is.element(a)||(a=this.elements.container),a[is.element(i)?"insertAdjacentElement":"insertAdjacentHTML"]("afterbegin",i),is.element(this.elements.controls)||controls.findElements.call(this),!is.empty(this.elements.buttons)){var r=function(t){var i=e.config.classNames.controlPressed;Object.defineProperty(t,"pressed",{enumerable:!0,get:function(){return hasClass(t,i)},set:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];toggleClass(t,i,e)}})};Object.values(this.elements.buttons).filter(Boolean).forEach(function(e){is.array(e)||is.nodeList(e)?Array.from(e).filter(Boolean).forEach(r):r(e)})}if(browser.isEdge&&repaint(a),this.config.tooltips.controls){var l=this.config,c=l.classNames,u=l.selectors,d="".concat(u.controls.wrapper," ").concat(u.labels," .").concat(c.hidden),h=getElements.call(this,d);Array.from(h).forEach(function(t){toggleClass(t,e.config.classNames.hidden,!1),toggleClass(t,e.config.classNames.tooltip,!0)})}}};function parseUrl(e){var t=e;if(!(arguments.length>1&&void 0!==arguments[1])||arguments[1]){var i=document.createElement("a");i.href=t,t=i.href}try{return new URL(t)}catch(e){return null}}function buildUrlParams(e){var t=new URLSearchParams;return is.object(e)&&Object.entries(e).forEach(function(e){var i=_slicedToArray(e,2),n=i[0],s=i[1];t.set(n,s)}),t}var captions={setup:function(){if(this.supported.ui)if(!this.isVideo||this.isYouTube||this.isHTML5&&!support.textTracks)is.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&controls.setCaptionsMenu.call(this);else{if(is.element(this.elements.captions)||(this.elements.captions=createElement("div",getAttributesFromSelector(this.config.selectors.captions)),insertAfter(this.elements.captions,this.elements.wrapper)),browser.isIE&&window.URL){var e=this.media.querySelectorAll("track");Array.from(e).forEach(function(e){var t=e.getAttribute("src"),i=parseUrl(t);null!==i&&i.hostname!==window.location.href.hostname&&["http:","https:"].includes(i.protocol)&&fetch(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){removeElement(e)})})}var t=dedupe((navigator.languages||[navigator.language||navigator.userLanguage||"en"]).map(function(e){return e.split("-")[0]})),i=(this.storage.get("language")||this.config.captions.language||"auto").toLowerCase();if("auto"===i)i=_slicedToArray(t,1)[0];var n=this.storage.get("captions");if(is.boolean(n)||(n=this.config.captions.active),Object.assign(this.captions,{toggled:!1,active:n,language:i,languages:t}),this.isHTML5){var s=this.config.captions.update?"addtrack removetrack":"removetrack";on.call(this,this.media.textTracks,s,captions.update.bind(this))}setTimeout(captions.update.bind(this),0)}},update:function(){var e=this,t=captions.getTracks.call(this,!0),i=this.captions,n=i.active,s=i.language,a=i.meta,o=i.currentTrackNode,r=Boolean(t.find(function(e){return e.language===s}));this.isHTML5&&this.isVideo&&t.filter(function(e){return!a.get(e)}).forEach(function(t){e.debug.log("Track added",t),a.set(t,{default:"showing"===t.mode}),t.mode="hidden",on.call(e,t,"cuechange",function(){return captions.updateCues.call(e)})}),(r&&this.language!==s||!t.includes(o))&&(captions.setLanguage.call(this,s),captions.toggle.call(this,n&&r)),toggleClass(this.elements.container,this.config.classNames.captions.enabled,!is.empty(t)),(this.config.controls||[]).includes("settings")&&this.config.settings.includes("captions")&&controls.setCaptionsMenu.call(this)},toggle:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.supported.ui){var i=this.captions.toggled,n=this.config.classNames.captions.active,s=is.nullOrUndefined(e)?!i:e;if(s!==i){if(t||(this.captions.active=s,this.storage.set({captions:s})),!this.language&&s&&!t){var a=captions.getTracks.call(this),o=captions.findTrack.call(this,[this.captions.language].concat(_toConsumableArray(this.captions.languages)),!0);return this.captions.language=o.language,void captions.set.call(this,a.indexOf(o))}this.elements.buttons.captions&&(this.elements.buttons.captions.pressed=s),toggleClass(this.elements.container,n,s),this.captions.toggled=s,controls.updateSetting.call(this,"captions"),triggerEvent.call(this,this.media,s?"captionsenabled":"captionsdisabled")}}},set:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=captions.getTracks.call(this);if(-1!==e)if(is.number(e))if(e in i){if(this.captions.currentTrack!==e){this.captions.currentTrack=e;var n=i[e],s=(n||{}).language;this.captions.currentTrackNode=n,controls.updateSetting.call(this,"captions"),t||(this.captions.language=s,this.storage.set({language:s})),this.isVimeo&&this.embed.enableTextTrack(s),triggerEvent.call(this,this.media,"languagechange")}captions.toggle.call(this,!0,t),this.isHTML5&&this.isVideo&&captions.updateCues.call(this)}else this.debug.warn("Track not found",e);else this.debug.warn("Invalid caption argument",e);else captions.toggle.call(this,!1,t)},setLanguage:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(is.string(e)){var i=e.toLowerCase();this.captions.language=i;var n=captions.getTracks.call(this),s=captions.findTrack.call(this,[i]);captions.set.call(this,n.indexOf(s),t)}else this.debug.warn("Invalid language argument",e)},getTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Array.from((this.media||{}).textTracks||[]).filter(function(i){return!e.isHTML5||t||e.captions.meta.has(i)}).filter(function(e){return["captions","subtitles"].includes(e.kind)})},findTrack:function(e){var t,i=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],s=captions.getTracks.call(this),a=function(e){return Number((i.captions.meta.get(e)||{}).default)},o=Array.from(s).sort(function(e,t){return a(t)-a(e)});return e.every(function(e){return!(t=o.find(function(t){return t.language===e}))}),t||(n?o[0]:void 0)},getCurrentTrack:function(){return captions.getTracks.call(this)[this.currentTrack]},getLabel:function(e){var t=e;return!is.track(t)&&support.textTracks&&this.captions.toggled&&(t=captions.getCurrentTrack.call(this)),is.track(t)?is.empty(t.label)?is.empty(t.language)?i18n.get("enabled",this.config):e.language.toUpperCase():t.label:i18n.get("disabled",this.config)},updateCues:function(e){if(this.supported.ui)if(is.element(this.elements.captions))if(is.nullOrUndefined(e)||Array.isArray(e)){var t=e;if(!t){var i=captions.getCurrentTrack.call(this);t=Array.from((i||{}).activeCues||[]).map(function(e){return e.getCueAsHTML()}).map(getHTML)}var n=t.map(function(e){return e.trim()}).join("\n");if(n!==this.elements.captions.innerHTML){emptyElement(this.elements.captions);var s=createElement("span",getAttributesFromSelector(this.config.selectors.caption));s.innerHTML=n,this.elements.captions.appendChild(s),triggerEvent.call(this,this.media,"cuechange")}}else this.debug.warn("updateCues: Invalid input",e);else this.debug.warn("No captions element to render to")}},defaults={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,playsinline:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.4.8/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:"auto",update:!1},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",seekLabel:"{currentTime} of {duration}",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",download:"Download",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",menuBack:"Go back to previous menu",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad",qualityBadge:{2160:"4K",1440:"HD",1080:"HD",720:"HD",576:"SD",480:"SD"}},urls:{download:null,vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,download:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","download","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',download:'[data-plyr="download"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress__buffer",loop:".plyr__progress__loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",caption:".plyr__caption",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",posterEnabled:"plyr__poster-enabled",ads:"plyr__ads",control:"plyr__control",controlPressed:"plyr__control--pressed",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",display:{time:"plyr__time"},menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus",previewThumbnails:{thumbContainer:"plyr__preview-thumb",thumbContainerShown:"plyr__preview-thumb--is-shown",imageContainer:"plyr__preview-thumb__image-container",timeContainer:"plyr__preview-thumb__time-container",scrubbingContainer:"plyr__preview-scrubbing",scrubbingContainerShown:"plyr__preview-scrubbing--is-shown"}},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:"",tagUrl:""},previewThumbnails:{enabled:!1,src:""},vimeo:{byline:!1,portrait:!1,title:!1,speed:!0,transparent:!1},youtube:{noCookie:!1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1}},pip={active:"picture-in-picture",inactive:"inline"},providers={html5:"html5",youtube:"youtube",vimeo:"vimeo"},types={audio:"audio",video:"video"};function getProviderByUrl(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e)?providers.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?providers.vimeo:null}var noop=function(){},Console=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];_classCallCheck(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return _createClass(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):noop}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):noop}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):noop}}]),e}();function onChange(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;is.element(e)&&(e.pressed=this.active),triggerEvent.call(this.player,this.target,this.active?"enterfullscreen":"exitfullscreen",!0),browser.isIos||trapFocus.call(this.player,this.target,this.active)}}function toggleFallback(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(t?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=t?"hidden":"",toggleClass(this.target,this.player.config.classNames.fullscreen.fallback,t),browser.isIos){var i=document.head.querySelector('meta[name="viewport"]'),n="viewport-fit=cover";i||(i=document.createElement("meta")).setAttribute("name","viewport");var s=is.string(i.content)&&i.content.includes(n);t?(this.cleanupViewport=!s,s||(i.content+=",".concat(n))):this.cleanupViewport&&(i.content=i.content.split(",").filter(function(e){return e.trim()!==n}).join(",")),setTimeout(function(){return repaint(e.target)},100)}onChange.call(this)}var Fullscreen=function(){function e(t){var i=this;_classCallCheck(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},this.forceFallback="force"===t.config.fullscreen.fallback,on.call(this.player,document,"ms"===this.prefix?"MSFullscreenChange":"".concat(this.prefix,"fullscreenchange"),function(){onChange.call(i)}),on.call(this.player,this.player.elements.container,"dblclick",function(e){is.element(i.player.elements.controls)&&i.player.elements.controls.contains(e.target)||i.toggle()}),this.update()}return _createClass(e,[{key:"update",value:function(){var t;this.enabled?(t=this.forceFallback?"Fallback (forced)":e.native?"Native":"Fallback",this.player.debug.log("".concat(t," fullscreen enabled"))):this.player.debug.log("Fullscreen not supported and fallback disabled");toggleClass(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(browser.isIos&&this.player.config.fullscreen.iosNative?this.target.webkitEnterFullscreen():!e.native||this.forceFallback?toggleFallback.call(this,!0):this.prefix?is.empty(this.prefix)||this.target["".concat(this.prefix,"Request").concat(this.property)]():this.target.requestFullscreen())}},{key:"exit",value:function(){if(this.enabled)if(browser.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(!e.native||this.forceFallback)toggleFallback.call(this,!1);else if(this.prefix){if(!is.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document["".concat(this.prefix).concat(t).concat(this.property)]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"usingNative",get:function(){return e.native&&!this.forceFallback}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(!e.native||this.forceFallback?hasClass(this.target,this.player.config.classNames.fullscreen.fallback):(this.prefix?document["".concat(this.prefix).concat(this.property,"Element")]:document.fullscreenElement)===this.target)}},{key:"target",get:function(){return browser.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(is.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!is.function(document["".concat(t,"ExitFullscreen")])&&!is.function(document["".concat(t,"CancelFullScreen")]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}();function loadImage(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return new Promise(function(i,n){var s=new Image,a=function(){delete s.onload,delete s.onerror,(s.naturalWidth>=t?i:n)(s)};Object.assign(s,{onload:a,onerror:a,src:e})})}var ui={addStyleHook:function(){toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for ".concat(this.provider," ").concat(this.type)),void ui.toggleNativeControls.call(this,!0);is.element(this.elements.controls)||(controls.inject.call(this),this.listeners.controls()),ui.toggleNativeControls.call(this),this.isHTML5&&captions.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,controls.updateVolume.call(this),controls.timeUpdate.call(this),ui.checkPlaying.call(this),toggleClass(this.elements.container,this.config.classNames.pip.supported,support.pip&&this.isHTML5&&this.isVideo),toggleClass(this.elements.container,this.config.classNames.airplay.supported,support.airplay&&this.isHTML5),toggleClass(this.elements.container,this.config.classNames.isIos,browser.isIos),toggleClass(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){triggerEvent.call(e,e.media,"ready")},0),ui.setTitle.call(this),this.poster&&ui.setPoster.call(this,this.poster,!1).catch(function(){}),this.config.duration&&controls.durationUpdate.call(this)},setTitle:function(){var e=i18n.get("play",this.config);if(is.string(this.config.title)&&!is.empty(this.config.title)&&(e+=", ".concat(this.config.title)),Array.from(this.elements.buttons.play||[]).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=getElement.call(this,"iframe");if(!is.element(t))return;var i=is.empty(this.config.title)?"video":this.config.title,n=i18n.get("frameTitle",this.config);t.setAttribute("title",n.replace("{title}",i))}},togglePoster:function(e){toggleClass(this.elements.container,this.config.classNames.posterEnabled,e)},setPoster:function(e){var t=this;return arguments.length>1&&void 0!==arguments[1]&&!arguments[1]||!this.poster?(this.media.setAttribute("poster",e),ready.call(this).then(function(){return loadImage(e)}).catch(function(i){throw e===t.poster&&ui.togglePoster.call(t,!1),i}).then(function(){if(e!==t.poster)throw new Error("setPoster cancelled by later call to setPoster")}).then(function(){return Object.assign(t.elements.poster.style,{backgroundImage:"url('".concat(e,"')"),backgroundSize:""}),ui.togglePoster.call(t,!0),e})):Promise.reject(new Error("Poster already set"))},checkPlaying:function(e){var t=this;toggleClass(this.elements.container,this.config.classNames.playing,this.playing),toggleClass(this.elements.container,this.config.classNames.paused,this.paused),toggleClass(this.elements.container,this.config.classNames.stopped,this.stopped),Array.from(this.elements.buttons.play||[]).forEach(function(e){e.pressed=t.playing}),is.event(e)&&"timeupdate"===e.type||ui.toggleControls.call(this)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){toggleClass(t.elements.container,t.config.classNames.loading,t.loading),ui.toggleControls.call(t)},this.loading?250:0)},toggleControls:function(e){var t=this.elements.controls;if(t&&this.config.hideControls){var i=this.touch&&this.lastSeekTime+2e3>Date.now();this.toggleControls(Boolean(e||this.loading||this.paused||t.pressed||t.hover||i))}}};function setAspectRatio(e){var t=e;is.string(t)||is.nullOrUndefined(this.embed)||(t=this.embed.ratio),is.string(t)||(t=this.config.ratio);var i=_slicedToArray(t.split(":").map(Number),2),n=100/i[0]*i[1];if(this.elements.wrapper.style.paddingBottom="".concat(n,"%"),this.isVimeo&&this.supported.ui){var s=(240-n)/4.8;this.media.style.transform="translateY(-".concat(s,"%)")}return{padding:n,ratio:t}}var Listeners=function(){function e(t){_classCallCheck(this,e),this.player=t,this.lastKey=null,this.focusTimer=null,this.lastKeyDown=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.setTabFocus=this.setTabFocus.bind(this),this.firstTouch=this.firstTouch.bind(this)}return _createClass(e,[{key:"handleKey",value:function(e){var t=this.player,i=t.elements,n=e.keyCode?e.keyCode:e.which,s="keydown"===e.type,a=s&&n===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&is.number(n)){if(s){var o=document.activeElement;if(is.element(o)){var r=t.config.selectors.editable;if(o!==i.inputs.seek&&matches(o,r))return;if(32===e.which&&matches(o,'button, [role^="menuitem"]'))return}switch([32,37,38,39,40,48,49,50,51,52,53,54,56,57,67,70,73,75,76,77,79].includes(n)&&(e.preventDefault(),e.stopPropagation()),n){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:a||(t.currentTime=t.duration/10*(n-48));break;case 32:case 75:a||t.togglePlay();break;case 38:t.increaseVolume(.1);break;case 40:t.decreaseVolume(.1);break;case 77:a||(t.muted=!t.muted);break;case 39:t.forward();break;case 37:t.rewind();break;case 70:t.fullscreen.toggle();break;case 67:a||t.toggleCaptions();break;case 76:t.loop=!t.loop}27===n&&!t.fullscreen.usingNative&&t.fullscreen.active&&t.fullscreen.toggle(),this.lastKey=n}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){controls.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){var e=this.player,t=e.elements;e.touch=!0,toggleClass(t.container,e.config.classNames.isTouch,!0)}},{key:"setTabFocus",value:function(e){var t=this.player,i=t.elements;if(clearTimeout(this.focusTimer),"keydown"!==e.type||9===e.which){"keydown"===e.type&&(this.lastKeyDown=e.timeStamp);var n,s=e.timeStamp-this.lastKeyDown<=20;if("focus"!==e.type||s)n=t.config.classNames.tabFocus,toggleClass(getElements.call(t,".".concat(n)),n,!1),this.focusTimer=setTimeout(function(){var e=document.activeElement;i.container.contains(e)&&toggleClass(document.activeElement,t.config.classNames.tabFocus,!0)},10)}}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.player;t.config.keyboard.global&&toggleListener.call(t,window,"keydown keyup",this.handleKey,e,!1),toggleListener.call(t,document.body,"click",this.toggleMenu,e),once.call(t,document.body,"touchstart",this.firstTouch),toggleListener.call(t,document.body,"keydown focus blur",this.setTabFocus,e,!1,!0)}},{key:"container",value:function(){var e=this.player,t=e.config,i=e.elements,n=e.timers;!t.keyboard.global&&t.keyboard.focused&&on.call(e,i.container,"keydown keyup",this.handleKey,!1),on.call(e,i.container,"mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",function(t){var s=i.controls;s&&"enterfullscreen"===t.type&&(s.pressed=!1,s.hover=!1);var a=0;["touchstart","touchmove","mousemove"].includes(t.type)&&(ui.toggleControls.call(e,!0),a=e.touch?3e3:2e3),clearTimeout(n.controls),n.controls=setTimeout(function(){return ui.toggleControls.call(e,!1)},a)});var s=function(t){if(!t)return setAspectRatio.call(e);var n=i.container.getBoundingClientRect(),s=n.width,a=n.height;return setAspectRatio.call(e,"".concat(s,":").concat(a))},a=function(){window.clearTimeout(n.resized),n.resized=window.setTimeout(s,50)};on.call(e,i.container,"enterfullscreen exitfullscreen",function(t){var n=e.fullscreen,o=n.target,r=n.usingNative;if(e.isEmbed&&o===i.container){var l="enterfullscreen"===t.type,c=s(l);c.padding;!function(t,i,n){if(e.isVimeo){var s=e.elements.wrapper.firstChild,a=_slicedToArray(t.split(":").map(Number),2)[1],o=_slicedToArray(e.embed.ratio.split(":").map(Number),2),r=o[0],l=o[1];s.style.maxWidth=n?"".concat(a/l*r,"px"):null,s.style.margin=n?"0 auto":null}}(c.ratio,0,l),r||(l?on.call(e,window,"resize",a):off.call(e,window,"resize",a))}})}},{key:"media",value:function(){var e=this,t=this.player,i=t.elements;if(on.call(t,t.media,"timeupdate seeking seeked",function(e){return controls.timeUpdate.call(t,e)}),on.call(t,t.media,"durationchange loadeddata loadedmetadata",function(e){return controls.durationUpdate.call(t,e)}),on.call(t,t.media,"canplay loadeddata",function(){toggleHidden(i.volume,!t.hasAudio),toggleHidden(i.buttons.mute,!t.hasAudio)}),on.call(t,t.media,"ended",function(){t.isHTML5&&t.isVideo&&t.config.resetOnEnd&&t.restart()}),on.call(t,t.media,"progress playing seeking seeked",function(e){return controls.updateProgress.call(t,e)}),on.call(t,t.media,"volumechange",function(e){return controls.updateVolume.call(t,e)}),on.call(t,t.media,"playing play pause ended emptied timeupdate",function(e){return ui.checkPlaying.call(t,e)}),on.call(t,t.media,"waiting canplay seeked playing",function(e){return ui.checkLoading.call(t,e)}),on.call(t,t.media,"playing",function(){t.ads&&t.ads.enabled&&!t.ads.initialized&&t.ads.managerPromise.then(function(){return t.ads.play()}).catch(function(){return t.play()})}),t.supported.ui&&t.config.clickToPlay&&!t.isAudio){var n=getElement.call(t,".".concat(t.config.classNames.video));if(!is.element(n))return;on.call(t,i.container,"click",function(s){([i.container,n].includes(s.target)||n.contains(s.target))&&(t.touch&&t.config.hideControls||(t.ended?(e.proxy(s,t.restart,"restart"),e.proxy(s,t.play,"play")):e.proxy(s,t.togglePlay,"play")))})}t.supported.ui&&t.config.disableContextMenu&&on.call(t,i.wrapper,"contextmenu",function(e){e.preventDefault()},!1),on.call(t,t.media,"volumechange",function(){t.storage.set({volume:t.volume,muted:t.muted})}),on.call(t,t.media,"ratechange",function(){controls.updateSetting.call(t,"speed"),t.storage.set({speed:t.speed})}),on.call(t,t.media,"qualitychange",function(e){controls.updateSetting.call(t,"quality",null,e.detail.quality)}),on.call(t,t.media,"ready qualitychange",function(){controls.setDownloadLink.call(t)});var s=t.config.events.concat(["keyup","keydown"]).join(" ");on.call(t,t.media,s,function(e){var n=e.detail,s=void 0===n?{}:n;"error"===e.type&&(s=t.media.error),triggerEvent.call(t,i.container,e.type,!0,s)})}},{key:"proxy",value:function(e,t,i){var n=this.player,s=n.config.listeners[i],a=!0;is.function(s)&&(a=s.call(n,e)),a&&is.function(t)&&t.call(n,e)}},{key:"bind",value:function(e,t,i,n){var s=this,a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=this.player,r=o.config.listeners[n],l=is.function(r);on.call(o,e,t,function(e){return s.proxy(e,i,n)},a&&!l)}},{key:"controls",value:function(){var e=this,t=this.player,i=t.elements,n=browser.isIE?"change":"input";if(i.buttons.play&&Array.from(i.buttons.play).forEach(function(i){e.bind(i,"click",t.togglePlay,"play")}),this.bind(i.buttons.restart,"click",t.restart,"restart"),this.bind(i.buttons.rewind,"click",t.rewind,"rewind"),this.bind(i.buttons.fastForward,"click",t.forward,"fastForward"),this.bind(i.buttons.mute,"click",function(){t.muted=!t.muted},"mute"),this.bind(i.buttons.captions,"click",function(){return t.toggleCaptions()}),this.bind(i.buttons.download,"click",function(){triggerEvent.call(t,t.media,"download")},"download"),this.bind(i.buttons.fullscreen,"click",function(){t.fullscreen.toggle()},"fullscreen"),this.bind(i.buttons.pip,"click",function(){t.pip="toggle"},"pip"),this.bind(i.buttons.airplay,"click",t.airplay,"airplay"),this.bind(i.buttons.settings,"click",function(e){e.stopPropagation(),controls.toggleMenu.call(t,e)}),this.bind(i.buttons.settings,"keyup",function(e){var i=e.which;[13,32].includes(i)&&(13!==i?(e.preventDefault(),e.stopPropagation(),controls.toggleMenu.call(t,e)):controls.focusFirstMenuItem.call(t,null,!0))},null,!1),this.bind(i.settings.menu,"keydown",function(e){27===e.which&&controls.toggleMenu.call(t,e)}),this.bind(i.inputs.seek,"mousedown mousemove",function(e){var t=i.progress.getBoundingClientRect(),n=100/t.width*(e.pageX-t.left);e.currentTarget.setAttribute("seek-value",n)}),this.bind(i.inputs.seek,"mousedown mouseup keydown keyup touchstart touchend",function(e){var i=e.currentTarget,n=e.keyCode?e.keyCode:e.which;if(!is.keyboardEvent(e)||39===n||37===n){t.lastSeekTime=Date.now();var s=i.hasAttribute("play-on-seeked"),a=["mouseup","touchend","keyup"].includes(e.type);s&&a?(i.removeAttribute("play-on-seeked"),t.play()):!a&&t.playing&&(i.setAttribute("play-on-seeked",""),t.pause())}}),browser.isIos){var s=getElements.call(t,'input[type="range"]');Array.from(s).forEach(function(t){return e.bind(t,n,function(e){return repaint(e.target)})})}this.bind(i.inputs.seek,n,function(e){var i=e.currentTarget,n=i.getAttribute("seek-value");is.empty(n)&&(n=i.value),i.removeAttribute("seek-value"),t.currentTime=n/i.max*t.duration},"seek"),this.bind(i.progress,"mouseenter mouseleave mousemove",function(e){return controls.updateSeekTooltip.call(t,e)}),this.bind(i.progress,"mousemove touchmove",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.startMove(e)}),this.bind(i.progress,"mouseleave click",function(){var e=t.previewThumbnails;e&&e.loaded&&e.endMove(!1,!0)}),this.bind(i.progress,"mousedown touchstart",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.startScrubbing(e)}),this.bind(i.progress,"mouseup touchend",function(e){var i=t.previewThumbnails;i&&i.loaded&&i.endScrubbing(e)}),browser.isWebkit&&Array.from(getElements.call(t,'input[type="range"]')).forEach(function(i){e.bind(i,"input",function(e){return controls.updateRangeFill.call(t,e.target)})}),t.config.toggleInvert&&!is.element(i.display.duration)&&this.bind(i.display.currentTime,"click",function(){0!==t.currentTime&&(t.config.invertTime=!t.config.invertTime,controls.timeUpdate.call(t))}),this.bind(i.inputs.volume,n,function(e){t.volume=e.target.value},"volume"),this.bind(i.controls,"mouseenter mouseleave",function(e){i.controls.hover=!t.touch&&"mouseenter"===e.type}),this.bind(i.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){i.controls.pressed=["mousedown","touchstart"].includes(e.type)}),this.bind(i.controls,"focusin",function(){var i=t.config,n=t.elements,s=t.timers;toggleClass(n.controls,i.classNames.noTransition,!0),ui.toggleControls.call(t,!0),setTimeout(function(){toggleClass(n.controls,i.classNames.noTransition,!1)},0);var a=e.touch?3e3:4e3;clearTimeout(s.controls),s.controls=setTimeout(function(){return ui.toggleControls.call(t,!1)},a)}),this.bind(i.inputs.volume,"wheel",function(e){var i=e.webkitDirectionInvertedFromDevice,n=_slicedToArray([e.deltaX,-e.deltaY].map(function(e){return i?-e:e}),2),s=n[0],a=n[1],o=Math.sign(Math.abs(s)>Math.abs(a)?s:a);t.increaseVolume(o/50);var r=t.media.volume;(1===o&&r<1||-1===o&&r>0)&&e.preventDefault()},"volume",!1)}}]),e}(),commonjsGlobal="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function createCommonjsModule(e,t){return e(t={exports:{}},t.exports),t.exports}var loadjs_umd=createCommonjsModule(function(e,t){e.exports=function(){var e=function(){},t={},i={},n={};function s(e,t){if(e){var s=n[e];if(i[e]=t,s)for(;s.length;)s[0](e,t),s.splice(0,1)}}function a(t,i){t.call&&(t={success:t}),i.length?(t.error||e)(i):(t.success||e)(t)}function o(t,i,n,s){var a,r,l=document,c=n.async,u=(n.numRetries||0)+1,d=n.before||e,h=t.replace(/^(css|img)!/,"");s=s||0,/(^css!|\.css$)/.test(t)?(a=!0,(r=l.createElement("link")).rel="stylesheet",r.href=h):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(r=l.createElement("img")).src=h:((r=l.createElement("script")).src=t,r.async=void 0===c||c),r.onload=r.onerror=r.onbeforeload=function(e){var l=e.type[0];if(a&&"hideFocus"in r)try{r.sheet.cssText.length||(l="e")}catch(e){18!=e.code&&(l="e")}if("e"==l&&(s+=1)<u)return o(t,i,n,s);i(t,l,e.defaultPrevented)},!1!==d(t,r)&&l.head.appendChild(r)}function r(e,i,n){var r,l;if(i&&i.trim&&(r=i),l=(r?n:i)||{},r){if(r in t)throw"LoadJS";t[r]=!0}!function(e,t,i){var n,s,a=(e=e.push?e:[e]).length,r=a,l=[];for(n=function(e,i,n){if("e"==i&&l.push(e),"b"==i){if(!n)return;l.push(e)}--a||t(l)},s=0;s<r;s++)o(e[s],n,i)}(e,function(e){a(l,e),s(r,e)},l)}return r.ready=function(e,t){return function(e,t){e=e.push?e:[e];var s,a,o,r=[],l=e.length,c=l;for(s=function(e,i){i.length&&r.push(e),--c||t(r)};l--;)a=e[l],(o=i[a])?s(a,o):(n[a]=n[a]||[]).push(s)}(e,function(e){a(t,e)}),r},r.done=function(e){s(e,[])},r.reset=function(){t={},i={},n={}},r.isDefined=function(e){return e in t},r}()});function loadScript(e){return new Promise(function(t,i){loadjs_umd(e,{success:t,error:i})})}function parseId(e){if(is.empty(e))return null;if(is.number(Number(e)))return e;return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e}function assurePlaybackState(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,triggerEvent.call(this,this.media,e?"play":"pause"))}var vimeo={setup:function(){var e=this;toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),setAspectRatio.call(this),is.object(window.Vimeo)?vimeo.ready.call(this):loadScript(this.config.urls.vimeo.sdk).then(function(){vimeo.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},ready:function(){var e=this,t=this,i=t.config.vimeo,n=buildUrlParams(extend({},{loop:t.config.loop.active,autoplay:t.autoplay,muted:t.muted,gesture:"media",playsinline:!this.config.fullscreen.iosNative},i)),s=t.media.getAttribute("src");is.empty(s)&&(s=t.media.getAttribute(t.config.attributes.embed.id));var a=parseId(s),o=createElement("iframe"),r=format(t.config.urls.vimeo.iframe,a,n);o.setAttribute("src",r),o.setAttribute("allowfullscreen",""),o.setAttribute("allowtransparency",""),o.setAttribute("allow","autoplay");var l=createElement("div",{poster:t.poster,class:t.config.classNames.embedContainer});l.appendChild(o),t.media=replaceElement(l,t.media),fetch(format(t.config.urls.vimeo.api,a),"json").then(function(e){if(!is.empty(e)){var i=new URL(e[0].thumbnail_large);i.pathname="".concat(i.pathname.split("_")[0],".jpg"),ui.setPoster.call(t,i.href).catch(function(){})}}),t.embed=new window.Vimeo.Player(o,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){return assurePlaybackState.call(t,!0),t.embed.play()},t.media.pause=function(){return assurePlaybackState.call(t,!1),t.embed.pause()},t.media.stop=function(){t.pause(),t.currentTime=0};var c=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return c},set:function(e){var i=t.embed,n=t.media,s=t.paused,a=t.volume,o=s&&!i.hasPlayed;n.seeking=!0,triggerEvent.call(t,n,"seeking"),Promise.resolve(o&&i.setVolume(0)).then(function(){return i.setCurrentTime(e)}).then(function(){return o&&i.pause()}).then(function(){return o&&i.setVolume(a)}).catch(function(){})}});var u=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return u},set:function(e){t.embed.setPlaybackRate(e).then(function(){u=e,triggerEvent.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&controls.setSpeedMenu.call(t,[])})}});var d=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return d},set:function(e){t.embed.setVolume(e).then(function(){d=e,triggerEvent.call(t,t.media,"volumechange")})}});var h=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return h},set:function(e){var i=!!is.boolean(e)&&e;t.embed.setVolume(i?0:t.config.volume).then(function(){h=i,triggerEvent.call(t,t.media,"volumechange")})}});var m,p=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return p},set:function(e){var i=is.boolean(e)?e:t.config.loop.active;t.embed.setLoop(i).then(function(){p=i})}}),t.embed.getVideoUrl().then(function(e){m=e,controls.setDownloadLink.call(t)}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return m}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(i){var n=_slicedToArray(i,2),s=n[0],a=n[1];t.embed.ratio="".concat(s,":").concat(a),setAspectRatio.call(e,t.embed.ratio)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(i){t.config.title=i,ui.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){c=e,triggerEvent.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,triggerEvent.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,captions.setup.call(t)}),t.embed.on("cuechange",function(e){var i=e.cues,n=(void 0===i?[]:i).map(function(e){return stripHTML(e.text)});captions.updateCues.call(t,n)}),t.embed.on("loaded",function(){(t.embed.getPaused().then(function(e){assurePlaybackState.call(t,!e),e||triggerEvent.call(t,t.media,"playing")}),is.element(t.embed.element)&&t.supported.ui)&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){assurePlaybackState.call(t,!0),triggerEvent.call(t,t.media,"playing")}),t.embed.on("pause",function(){assurePlaybackState.call(t,!1)}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,c=e.seconds,triggerEvent.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,triggerEvent.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&triggerEvent.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,triggerEvent.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,triggerEvent.call(t,t.media,"seeked")}),t.embed.on("ended",function(){t.media.paused=!0,triggerEvent.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,triggerEvent.call(t,t.media,"error")}),setTimeout(function(){return ui.build.call(t)},0)}};function parseId$1(e){if(is.empty(e))return null;return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:e}function assurePlaybackState$1(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,triggerEvent.call(this,this.media,e?"play":"pause"))}var youtube={setup:function(){var e=this;toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),setAspectRatio.call(this),is.object(window.YT)&&is.function(window.YT.Player)?youtube.ready.call(this):(loadScript(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){youtube.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(is.function(this.embed.getVideoData)){var i=this.embed.getVideoData().title;if(is.empty(i))return this.config.title=i,void ui.setTitle.call(this)}var n=this.config.keys.google;is.string(n)&&!is.empty(n)&&fetch(format(this.config.urls.youtube.api,e,n)).then(function(e){is.object(e)&&(t.config.title=e.items[0].snippet.title,ui.setTitle.call(t))}).catch(function(){})},ready:function(){var e=this,t=e.media.getAttribute("id");if(is.empty(t)||!t.startsWith("youtube-")){var i=e.media.getAttribute("src");is.empty(i)&&(i=e.media.getAttribute(this.config.attributes.embed.id));var n=parseId$1(i),s=generateId(e.provider),a=createElement("div",{id:s,poster:e.poster});e.media=replaceElement(a,e.media);var o=function(e){return"https://img.youtube.com/vi/".concat(n,"/").concat(e,"default.jpg")};loadImage(o("maxres"),121).catch(function(){return loadImage(o("sd"),121)}).catch(function(){return loadImage(o("hq"))}).then(function(t){return ui.setPoster.call(e,t.src)}).then(function(t){t.includes("maxres")||(e.elements.poster.style.backgroundSize="cover")}).catch(function(){});var r=e.config.youtube;e.embed=new window.YT.Player(s,{videoId:n,host:r.noCookie?"https://www.youtube-nocookie.com":void 0,playerVars:extend({},{autoplay:e.config.autoplay?1:0,hl:e.config.hl,controls:e.supported.ui?0:1,disablekb:1,playsinline:e.config.fullscreen.iosNative?0:1,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language,widget_referrer:window?window.location.href:null},r),events:{onError:function(t){if(!e.media.error){var i=t.data,n={2:"The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.",5:"The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",100:"The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.",101:"The owner of the requested video does not allow it to be played in embedded players.",150:"The owner of the requested video does not allow it to be played in embedded players."}[i]||"An unknown error occured";e.media.error={code:i,message:n},triggerEvent.call(e,e.media,"error")}},onPlaybackRateChange:function(t){var i=t.target;e.media.playbackRate=i.getPlaybackRate(),triggerEvent.call(e,e.media,"ratechange")},onReady:function(t){if(!is.function(e.media.play)){var i=t.target;youtube.getTitle.call(e,n),e.media.play=function(){assurePlaybackState$1.call(e,!0),i.playVideo()},e.media.pause=function(){assurePlaybackState$1.call(e,!1),i.pauseVideo()},e.media.stop=function(){i.stopVideo()},e.media.duration=i.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(t){e.paused&&!e.embed.hasPlayed&&e.embed.mute(),e.media.seeking=!0,triggerEvent.call(e,e.media,"seeking"),i.seekTo(t)}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}});var s=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return s},set:function(t){s=t,i.setVolume(100*s),triggerEvent.call(e,e.media,"volumechange")}});var a=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return a},set:function(t){var n=is.boolean(t)?t:a;a=n,i[n?"mute":"unMute"](),triggerEvent.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=i.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),triggerEvent.call(e,e.media,"timeupdate"),triggerEvent.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=i.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&triggerEvent.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),triggerEvent.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return ui.build.call(e)},50)}},onStateChange:function(t){var i=t.target;switch(clearInterval(e.timers.playing),e.media.seeking&&[1,2].includes(t.data)&&(e.media.seeking=!1,triggerEvent.call(e,e.media,"seeked")),t.data){case-1:triggerEvent.call(e,e.media,"timeupdate"),e.media.buffered=i.getVideoLoadedFraction(),triggerEvent.call(e,e.media,"progress");break;case 0:assurePlaybackState$1.call(e,!1),e.media.loop?(i.stopVideo(),i.playVideo()):triggerEvent.call(e,e.media,"ended");break;case 1:e.media.paused&&!e.embed.hasPlayed?e.media.pause():(assurePlaybackState$1.call(e,!0),triggerEvent.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){triggerEvent.call(e,e.media,"timeupdate")},50),e.media.duration!==i.getDuration()&&(e.media.duration=i.getDuration(),triggerEvent.call(e,e.media,"durationchange")));break;case 2:e.muted||e.embed.unMute(),assurePlaybackState$1.call(e,!1)}triggerEvent.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},media={setup:function(){this.media?(toggleClass(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),toggleClass(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&toggleClass(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=createElement("div",{class:this.config.classNames.video}),wrap(this.media,this.elements.wrapper),this.elements.poster=createElement("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isHTML5?html5.extend.call(this):this.isYouTube?youtube.setup.call(this):this.isVimeo&&vimeo.setup.call(this)):this.debug.warn("No media element found!")}},Ads=function(){function e(t){var i=this;_classCallCheck(this,e),this.player=t,this.config=t.config.ads,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){i.on("loaded",e),i.on("error",t)}),this.load()}return _createClass(e,[{key:"load",value:function(){var e=this;this.enabled&&(is.object(window.google)&&is.object(window.google.ima)?this.ready():loadScript(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=createElement("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var i=new google.ima.AdsRequest;i.adTagUrl=this.tagUrl,i.linearAdSlotWidth=t.offsetWidth,i.linearAdSlotHeight=t.offsetHeight,i.nonLinearAdSlotWidth=t.offsetWidth,i.nonLinearAdSlotHeight=t.offsetHeight,i.forceNonLinearFullSlot=!1,i.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(i)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=formatTime(Math.max(e.manager.getRemainingTime(),0)),i="".concat(i18n.get("advertisement",e.player.config)," - ").concat(t);e.elements.container.setAttribute("data-badge-text",i)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this;if(this.enabled){var i=new google.ima.AdsRenderingSettings;i.restoreCustomPlaybackStateOnAdBreakComplete=!0,i.enablePreloading=!0,this.manager=e.getAdsManager(this.player,i),this.cuePoints=this.manager.getCuePoints(),is.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var i=t.player.elements.progress;if(is.element(i)){var n=100/t.player.duration*e,s=createElement("span",{class:t.player.config.classNames.cues});s.style.left="".concat(n.toString(),"%"),i.appendChild(s)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}}},{key:"onAdEvent",value:function(e){var t=this,i=this.player.elements.container,n=e.getAd(),s=e.getAdData(),a=function(e){var i="ads".concat(e.replace(/_/g,"").toLowerCase());triggerEvent.call(t.player,t.player.media,i)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),a(e.type),this.pollCountdown(!0),n.isLinear()||(n.width=i.offsetWidth,n.height=i.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:a(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:a(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:a(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:a(e.type);break;case google.ima.AdEvent.Type.LOG:s.adError&&this.player.debug.warn("Non-fatal ad error: ".concat(s.adError.getMessage()))}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e,t=this,i=this.player.elements.container;this.player.on("ended",function(){t.loader.contentComplete()}),this.player.on("timeupdate",function(){e=t.player.currentTime}),this.player.on("seeked",function(){var i=t.player.currentTime;is.empty(t.cuePoints)||t.cuePoints.forEach(function(n,s){e<n&&n<i&&(t.manager.discardAdBreak(),t.cuePoints.splice(s,1))})}),window.addEventListener("resize",function(){t.manager&&t.manager.resize(i.offsetWidth,i.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,i=arguments.length,n=new Array(i>1?i-1:0),s=1;s<i;s++)n[s-1]=arguments[s];var a=this.events[e];is.array(a)&&a.forEach(function(e){is.function(e)&&e.apply(t,n)})}},{key:"on",value:function(e,t){return is.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var i=this;this.player.debug.log("Safety timer invoked from: ".concat(t)),this.safetyTimer=setTimeout(function(){i.cancel(),i.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){is.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: ".concat(e)),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){var e=this.config;return this.player.isHTML5&&this.player.isVideo&&e.enabled&&(!is.empty(e.publisherId)||is.url(e.tagUrl))}},{key:"tagUrl",get:function(){var e=this.config;if(is.url(e.tagUrl))return e.tagUrl;var t={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:window.location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"".concat("https://go.aniview.com/api/adserver6/vast/","?").concat(buildUrlParams(t))}}]),e}(),parseVtt=function(e){var t=[];return e.split(/\r\n\r\n|\n\n|\r\r/).forEach(function(e){var i={};e.split(/\r\n|\n|\r/).forEach(function(e){if(is.number(i.startTime)){if(!is.empty(e.trim())&&is.empty(i.text)){var t=e.trim().split("#xywh="),n=_slicedToArray(t,1);if(i.text=n[0],t[1]){var s=_slicedToArray(t[1].split(","),4);i.x=s[0],i.y=s[1],i.w=s[2],i.h=s[3]}}}else{var a=e.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);a&&(i.startTime=60*Number(a[1])*60+60*Number(a[2])+Number(a[3])+Number("0.".concat(a[4])),i.endTime=60*Number(a[6])*60+60*Number(a[7])+Number(a[8])+Number("0.".concat(a[9])))}}),i.text&&t.push(i)}),t},PreviewThumbnails=function(){function e(t){_classCallCheck(this,e),this.player=t,this.thumbnails=[],this.loaded=!1,this.lastMouseMoveTime=Date.now(),this.mouseDown=!1,this.loadedImages=[],this.elements={thumb:{},scrubbing:{}},this.load()}return _createClass(e,[{key:"load",value:function(){var e=this;this.player.elements.display.seekTooltip&&(this.player.elements.display.seekTooltip.hidden=this.enabled),this.enabled&&this.getThumbnails().then(function(){e.render(),e.determineContainerAutoSizing(),e.loaded=!0})}},{key:"getThumbnails",value:function(){var e=this;return new Promise(function(t){var i=e.player.config.previewThumbnails.src;if(is.empty(i))throw new Error("Missing previewThumbnails.src config attribute");var n=(is.string(i)?[i]:i).map(function(t){return e.getThumbnail(t)});Promise.all(n).then(function(){e.thumbnails.sort(function(e,t){return e.height-t.height}),e.player.debug.log("Preview thumbnails",e.thumbnails),t()})})}},{key:"getThumbnail",value:function(e){var t=this;return new Promise(function(i){fetch(e).then(function(n){var s={frames:parseVtt(n),height:null,urlPrefix:""};s.frames[0].text.startsWith("/")||(s.urlPrefix=e.substring(0,e.lastIndexOf("/")+1));var a=new Image;a.onload=function(){s.height=a.naturalHeight,s.width=a.naturalWidth,t.thumbnails.push(s),i()},a.src=s.urlPrefix+s.frames[0].text})})}},{key:"startMove",value:function(e){if(this.loaded&&is.event(e)&&["touchmove","mousemove"].includes(e.type)&&this.player.media.duration){if("touchmove"===e.type)this.seekTime=this.player.media.duration*(this.player.elements.inputs.seek.value/100);else{var t=this.player.elements.progress.getBoundingClientRect(),i=100/t.width*(e.pageX-t.left);this.seekTime=this.player.media.duration*(i/100),this.seekTime<0&&(this.seekTime=0),this.seekTime>this.player.media.duration-1&&(this.seekTime=this.player.media.duration-1),this.mousePosX=e.pageX,this.elements.thumb.time.innerText=formatTime(this.seekTime)}this.showImageAtCurrentTime()}}},{key:"endMove",value:function(){this.toggleThumbContainer(!1,!0)}},{key:"startScrubbing",value:function(e){!1!==e.button&&0!==e.button||(this.mouseDown=!0,this.player.media.duration&&(this.toggleScrubbingContainer(!0),this.toggleThumbContainer(!1,!0),this.showImageAtCurrentTime()))}},{key:"finishScrubbing",value:function(){var e=this;this.mouseDown=!1,Math.ceil(this.lastTime)===Math.ceil(this.player.media.currentTime)?this.toggleScrubbingContainer(!1):once.call(this.player,this.player.media,"timeupdate",function(){e.mouseDown||e.toggleScrubbingContainer(!1)})}},{key:"listeners",value:function(){var e=this;this.player.on("play",function(){e.toggleThumbContainer(!1,!0)}),this.player.on("seeked",function(){e.toggleThumbContainer(!1)}),this.player.on("timeupdate",function(){e.lastTime=e.player.media.currentTime})}},{key:"render",value:function(){this.elements.thumb.container=createElement("div",{class:this.player.config.classNames.previewThumbnails.thumbContainer}),this.elements.thumb.imageContainer=createElement("div",{class:this.player.config.classNames.previewThumbnails.imageContainer}),this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);var e=createElement("div",{class:this.player.config.classNames.previewThumbnails.timeContainer});this.elements.thumb.time=createElement("span",{},"00:00"),e.appendChild(this.elements.thumb.time),this.elements.thumb.container.appendChild(e),this.player.elements.progress.appendChild(this.elements.thumb.container),this.elements.scrubbing.container=createElement("div",{class:this.player.config.classNames.previewThumbnails.scrubbingContainer}),this.player.elements.wrapper.appendChild(this.elements.scrubbing.container)}},{key:"showImageAtCurrentTime",value:function(){var e=this;this.mouseDown?this.setScrubbingContainerSize():(this.toggleThumbContainer(!0),this.setThumbContainerSizeAndPos());var t=this.thumbnails[0].frames.findIndex(function(t){return e.seekTime>=t.startTime&&e.seekTime<=t.endTime}),i=t>=0,n=0;this.toggleThumbContainer(i),i&&(this.thumbnails.forEach(function(i,s){e.loadedImages.includes(i.frames[t].text)&&(n=s)}),t!==this.showingThumb&&(this.showingThumb=t,this.loadImage(n)))}},{key:"loadImage",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,i=this.showingThumb,n=this.thumbnails[t],s=n.urlPrefix,a=n.frames[i],o=n.frames[i].text,r=s+o;if(this.currentImageElement&&this.currentImageElement.dataset.filename===o)this.showImage(this.currentImageElement,a,t,i,o,!1),this.currentImageElement.dataset.index=i,this.removeOldImages(this.currentImageElement);else{this.loadingImage&&this.usingSprites&&(this.loadingImage.onload=null);var l=new Image;l.src=r,l.dataset.index=i,l.dataset.filename=o,this.showingThumbFilename=o,this.player.debug.log("Loading image: ".concat(r)),l.onload=function(){return e.showImage(l,a,t,i,o,!0)},this.loadingImage=l,this.removeOldImages(l)}}},{key:"showImage",value:function(e,t,i,n,s){var a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];this.player.debug.log("Showing thumb: ".concat(s,". num: ").concat(n,". qual: ").concat(i,". newimg: ").concat(a)),this.setImageSizeAndOffset(e,t),a&&(this.currentImageContainer.appendChild(e),this.currentImageElement=e,this.loadedImages.includes(s)||this.loadedImages.push(s)),this.preloadNearby(n,!0).then(this.preloadNearby(n,!1)).then(this.getHigherQuality(i,e,t,s))}},{key:"removeOldImages",value:function(e){var t=this;Array.from(this.currentImageContainer.children).forEach(function(i){if("img"===i.tagName.toLowerCase()){var n=t.usingSprites?500:1e3;if(i.dataset.index!==e.dataset.index&&!i.dataset.deleting){i.dataset.deleting=!0;var s=t.currentImageContainer;setTimeout(function(){s.removeChild(i),t.player.debug.log("Removing thumb: ".concat(i.dataset.filename))},n)}}})}},{key:"preloadNearby",value:function(e){var t=this,i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return new Promise(function(n){setTimeout(function(){var s=t.thumbnails[0].frames[e].text;if(t.showingThumbFilename===s){var a;a=i?t.thumbnails[0].frames.slice(e):t.thumbnails[0].frames.slice(0,e).reverse();var o=!1;a.forEach(function(e){var i=e.text;if(i!==s&&!t.loadedImages.includes(i)){o=!0,t.player.debug.log("Preloading thumb filename: ".concat(i));var a=t.thumbnails[0].urlPrefix+i,r=new Image;r.src=a,r.onload=function(){t.player.debug.log("Preloaded thumb filename: ".concat(i)),t.loadedImages.includes(i)||t.loadedImages.push(i),n()}}}),o||n()}},300)})}},{key:"getHigherQuality",value:function(e,t,i,n){var s=this;if(e<this.thumbnails.length-1){var a=t.naturalHeight;this.usingSprites&&(a=i.h),a<this.thumbContainerHeight&&setTimeout(function(){s.showingThumbFilename===n&&(s.player.debug.log("Showing higher quality thumb for: ".concat(n)),s.loadImage(e+1))},300)}}},{key:"toggleThumbContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.player.config.classNames.previewThumbnails.thumbContainerShown;this.elements.thumb.container.classList.toggle(i,e),!e&&t&&(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"toggleScrubbingContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.player.config.classNames.previewThumbnails.scrubbingContainerShown;this.elements.scrubbing.container.classList.toggle(t,e),e||(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"determineContainerAutoSizing",value:function(){this.elements.thumb.imageContainer.clientHeight>20&&(this.sizeSpecifiedInCSS=!0)}},{key:"setThumbContainerSizeAndPos",value:function(){if(!this.sizeSpecifiedInCSS){var e=Math.floor(this.thumbContainerHeight*this.thumbAspectRatio);this.elements.thumb.imageContainer.style.height="".concat(this.thumbContainerHeight,"px"),this.elements.thumb.imageContainer.style.width="".concat(e,"px")}this.setThumbContainerPos()}},{key:"setThumbContainerPos",value:function(){var e=this.player.elements.progress.getBoundingClientRect(),t=this.player.elements.container.getBoundingClientRect(),i=this.elements.thumb.container,n=t.left-e.left+10,s=t.right-e.left-i.clientWidth-10,a=this.mousePosX-e.left-i.clientWidth/2;a<n&&(a=n),a>s&&(a=s),i.style.left="".concat(a,"px")}},{key:"setScrubbingContainerSize",value:function(){this.elements.scrubbing.container.style.width="".concat(this.player.media.clientWidth,"px"),this.elements.scrubbing.container.style.height="".concat(this.player.media.clientWidth/this.thumbAspectRatio,"px")}},{key:"setImageSizeAndOffset",value:function(e,t){if(this.usingSprites){var i=this.thumbContainerHeight/t.h;e.style.height="".concat(Math.floor(e.naturalHeight*i),"px"),e.style.width="".concat(Math.floor(e.naturalWidth*i),"px"),e.style.left="-".concat(t.x*i,"px"),e.style.top="-".concat(t.y*i,"px")}}},{key:"enabled",get:function(){return this.player.isHTML5&&this.player.isVideo&&this.player.config.previewThumbnails.enabled}},{key:"currentImageContainer",get:function(){return this.mouseDown?this.elements.scrubbing.container:this.elements.thumb.imageContainer}},{key:"usingSprites",get:function(){return Object.keys(this.thumbnails[0].frames[0]).includes("w")}},{key:"thumbAspectRatio",get:function(){return this.usingSprites?this.thumbnails[0].frames[0].w/this.thumbnails[0].frames[0].h:this.thumbnails[0].width/this.thumbnails[0].height}},{key:"thumbContainerHeight",get:function(){return this.mouseDown?Math.floor(this.player.media.clientWidth/this.thumbAspectRatio):Math.floor(this.player.media.clientWidth/this.thumbAspectRatio/4)}},{key:"currentImageElement",get:function(){return this.mouseDown?this.currentScrubbingImageElement:this.currentThumbnailImageElement},set:function(e){this.mouseDown?this.currentScrubbingImageElement=e:this.currentThumbnailImageElement=e}}]),e}(),source={insertElements:function(e,t){var i=this;is.string(t)?insertElement(e,this.media,{src:t}):is.array(t)&&t.forEach(function(t){insertElement(e,i.media,t)})},change:function(e){var t=this;getDeep(e,"sources.length")?(html5.cancelRequests.call(this),this.destroy.call(this,function(){t.options.quality=[],removeElement(t.media),t.media=null,is.element(t.elements.container)&&t.elements.container.removeAttribute("class");var i=e.sources,n=e.type,s=_slicedToArray(i,1)[0],a=s.provider,o=void 0===a?providers.html5:a,r=s.src,l="html5"===o?n:"div",c="html5"===o?{}:{src:r};Object.assign(t,{provider:o,type:n,supported:support.check(n,o,t.config.playsinline),media:createElement(l,c)}),t.elements.container.appendChild(t.media),is.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),is.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),ui.addStyleHook.call(t),t.isHTML5&&source.insertElements.call(t,"source",i),t.config.title=e.title,media.setup.call(t),t.isHTML5&&Object.keys(e).includes("tracks")&&source.insertElements.call(t,"track",e.tracks),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&ui.build.call(t),t.isHTML5&&t.media.load(),t.previewThumbnails&&t.previewThumbnails.load(),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},Plyr=function(){function e(t,i){var n=this;if(_classCallCheck(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=support.touch,this.media=t,is.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||is.nodeList(this.media)||is.array(this.media))&&(this.media=this.media[0]),this.config=extend({},defaults,e.defaults,i||{},function(){try{return JSON.parse(n.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,captions:null,buttons:{},display:{},progress:{},inputs:{},settings:{popup:null,menu:null,panels:{},buttons:{}}},this.captions={active:null,currentTrack:-1,meta:new WeakMap},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new Console(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",support),!is.nullOrUndefined(this.media)&&is.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(support.check().api){var s=this.media.cloneNode(!0);s.autoplay=!1,this.elements.original=s;var a=this.media.tagName.toLowerCase(),o=null,r=null;switch(a){case"div":if(o=this.media.querySelector("iframe"),is.element(o)){if(r=parseUrl(o.getAttribute("src")),this.provider=getProviderByUrl(r.toString()),this.elements.container=this.media,this.media=o,this.elements.container.className="",r.search.length){var l=["1","true"];l.includes(r.searchParams.get("autoplay"))&&(this.config.autoplay=!0),l.includes(r.searchParams.get("loop"))&&(this.config.loop.active=!0),this.isYouTube?(this.config.playsinline=l.includes(r.searchParams.get("playsinline")),this.config.youtube.hl=r.searchParams.get("hl")):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(is.empty(this.provider)||!Object.keys(providers).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=types.video;break;case"video":case"audio":this.type=a,this.provider=providers.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),(this.media.hasAttribute("playsinline")||this.media.hasAttribute("webkit-playsinline"))&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=support.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.eventListeners=[],this.listeners=new Listeners(this),this.storage=new Storage(this),this.media.plyr=this,is.element(this.elements.container)||(this.elements.container=createElement("div",{tabindex:0}),wrap(this.media,this.elements.container)),ui.addStyleHook.call(this),media.setup.call(this),this.config.debug&&on.call(this,this.elements.container,this.config.events.join(" "),function(e){n.debug.log("event: ".concat(e.type))}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&ui.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new Fullscreen(this),this.config.ads.enabled&&(this.ads=new Ads(this)),this.config.autoplay&&this.play(),this.lastSeekTime=0,this.config.previewThumbnails.enabled&&(this.previewThumbnails=new PreviewThumbnails(this))):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return _createClass(e,[{key:"play",value:function(){return is.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&is.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(is.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):is.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(is.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(is.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(is.number(e)?e:0)}},{key:"decreaseVolume",value:function(e){this.increaseVolume(-e)}},{key:"toggleCaptions",value:function(e){captions.toggle.call(this,e,!1)}},{key:"airplay",value:function(){support.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){if(this.supported.ui&&!this.isAudio){var t=hasClass(this.elements.container,this.config.classNames.hideControls),i=void 0===e?void 0:!e,n=toggleClass(this.elements.container,this.config.classNames.hideControls,i);if(n&&this.config.controls.includes("settings")&&!is.empty(this.config.settings)&&controls.toggleMenu.call(this,!1),n!==t){var s=n?"controlshidden":"controlsshown";triggerEvent.call(this,this.media,s)}return!n}return!1}},{key:"on",value:function(e,t){on.call(this,this.elements.container,e,t)}},{key:"once",value:function(e,t){once.call(this,this.elements.container,e,t)}},{key:"off",value:function(e,t){off(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var n=function(){document.body.style.overflow="",t.embed=null,i?(Object.keys(t.elements).length&&(removeElement(t.elements.buttons.play),removeElement(t.elements.captions),removeElement(t.elements.controls),removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),is.function(e)&&e()):(unbindListeners.call(t),replaceElement(t.elements.original,t.elements.container),triggerEvent.call(t,t.elements.original,"destroyed",!0),is.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};this.stop(),this.isHTML5?(clearTimeout(this.timers.loading),ui.toggleNativeControls.call(this,!0),n()):this.isYouTube?(clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&is.function(this.embed.destroy)&&this.embed.destroy(),n()):this.isVimeo&&(null!==this.embed&&this.embed.unload().then(n),setTimeout(n,200))}}},{key:"supports",value:function(e){return support.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===providers.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===providers.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===providers.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===types.video)}},{key:"isAudio",get:function(){return Boolean(this.type===types.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){if(this.duration){var t=is.number(e)&&e>0;this.media.currentTime=t?Math.min(e,this.duration):0,this.debug.log("Seeking to ".concat(this.currentTime," seconds"))}},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return is.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=(this.media||{}).duration,i=is.number(t)&&t!==1/0?t:0;return e||i}},{key:"volume",set:function(e){var t=e;is.string(t)&&(t=Number(t)),is.number(t)||(t=this.storage.get("volume")),is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!is.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;is.boolean(t)||(t=this.storage.get("muted")),is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;is.number(e)&&(t=e),is.number(t)||(t=this.storage.get("speed")),is.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed (".concat(t,")"))},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=this.config.quality,i=this.options.quality;if(i.length){var n=[!is.empty(e)&&Number(e),this.storage.get("quality"),t.selected,t.default].find(is.number),s=!0;if(!i.includes(n)){var a=closest(i,n);this.debug.warn("Unsupported quality option: ".concat(n,", using ").concat(a," instead")),n=a,s=!1}t.selected=n,this.media.quality=n,s&&this.storage.set({quality:n})}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){source.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"download",get:function(){var e=this.config.urls.download;return is.url(e)?e:this.source}},{key:"poster",set:function(e){this.isVideo?ui.setPoster.call(this,e,!1).catch(function(){}):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"currentTrack",set:function(e){captions.set.call(this,e,!1)},get:function(){var e=this.captions,t=e.toggled,i=e.currentTrack;return t?i:-1}},{key:"language",set:function(e){captions.setLanguage.call(this,e,!1)},get:function(){return(captions.getCurrentTrack.call(this)||{}).language}},{key:"pip",set:function(e){if(support.pip){var t=is.boolean(e)?e:!this.pip;is.function(this.media.webkitSetPresentationMode)&&this.media.webkitSetPresentationMode(t?pip.active:pip.inactive),is.function(this.media.requestPictureInPicture)&&(!this.pip&&t?this.media.requestPictureInPicture():this.pip&&!t&&document.exitPictureInPicture())}},get:function(){return support.pip?is.empty(this.media.webkitPresentationMode)?this.media===document.pictureInPictureElement:this.media.webkitPresentationMode===pip.active:null}}],[{key:"supported",value:function(e,t,i){return support.check(e,t,i)}},{key:"loadSprite",value:function(e,t){return loadSprite(e,t)}},{key:"setup",value:function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null;return is.string(t)?n=Array.from(document.querySelectorAll(t)):is.nodeList(t)?n=Array.from(t):is.array(t)&&(n=t.filter(is.element)),is.empty(n)?null:n.map(function(t){return new e(t,i)})}}]),e}();Plyr.defaults=cloneDeep(defaults);export default Plyr;
\ No newline at end of file diff --git a/dist/plyr.min.mjs.map b/dist/plyr.min.mjs.map new file mode 100644 index 00000000..c596a525 --- /dev/null +++ b/dist/plyr.min.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/js/utils/is.js","src/js/utils/events.js","src/js/utils/elements.js","src/js/utils/animation.js","src/js/utils/browser.js","src/js/support.js","src/js/html5.js","src/js/utils/arrays.js","src/js/utils/objects.js","src/js/utils/strings.js","src/js/utils/i18n.js","src/js/storage.js","src/js/utils/fetch.js","src/js/utils/loadSprite.js","src/js/utils/time.js","src/js/controls.js","src/js/utils/urls.js","src/js/captions.js","src/js/config/defaults.js","src/js/config/states.js","src/js/config/types.js","src/js/console.js","src/js/fullscreen.js","src/js/utils/loadImage.js","src/js/ui.js","src/js/utils/style.js","src/js/listeners.js","node_modules/loadjs/dist/loadjs.umd.js","src/js/utils/loadScript.js","src/js/plugins/vimeo.js","src/js/plugins/youtube.js","src/js/media.js","src/js/plugins/ads.js","src/js/plugins/previewThumbnails.js","src/js/source.js","src/js/plyr.js"],"names":["getConstructor","input","constructor","instanceOf","Boolean","isNullOrUndefined","isObject","Object","isNumber","Number","isNaN","isString","String","isBoolean","isFunction","Function","isArray","Array","isWeakMap","WeakMap","isNodeList","NodeList","isElement","Element","isTextNode","Text","isEvent","Event","isKeyboardEvent","KeyboardEvent","isCue","window","TextTrackCue","VTTCue","isTrack","TextTrack","kind","isEmpty","length","keys","isUrl","URL","string","startsWith","concat","hostname","e","is","nullOrUndefined","object","number","boolean","function","array","weakMap","nodeList","element","textNode","event","keyboardEvent","cue","track","url","empty","supportsPassiveListeners","supported","options","defineProperty","get","addEventListener","removeEventListener","toggleListener","callback","toggle","arguments","undefined","passive","capture","events","split","forEach","type","_this","eventListeners","push","on","call","this","off","once","onceCallback","args","_len","_key","apply","_this2","triggerEvent","bubbles","detail","CustomEvent","assign","plyr","dispatchEvent","unbindListeners","item","ready","Promise","resolve","_this3","setTimeout","elements","container","then","wrap","wrapper","targets","from","reverse","index","child","cloneNode","parent","parentNode","sibling","nextSibling","appendChild","insertBefore","setAttributes","attributes","entries","filter","_ref","value","_ref3","key","_ref4","setAttribute","createElement","text","document","innerText","insertAfter","target","insertElement","removeElement","removeChild","emptyElement","childNodes","lastChild","replaceElement","newChild","oldChild","replaceChild","getAttributesFromSelector","sel","existingAttributes","existing","s","selector","trim","className","replace","parts","charAt","class","id","toggleHidden","hidden","hide","removeAttribute","toggleClass","force","map","method","classList","contains","hasClass","matches","querySelectorAll","includes","getElements","getElement","querySelector","trapFocus","focusable","first","last","keyCode","focused","activeElement","shiftKey","focus","preventDefault","setFocus","tabFocus","preventScroll","config","classNames","transitionEndEvent","WebkitTransition","MozTransition","OTransition","transition","find","style","repaint","offsetHeight","browser","isIE","documentMode","isEdge","navigator","userAgent","isWebkit","documentElement","test","isIPhone","platform","isIos","defaultCodecs","support","audio","video","check","provider","playsinline","canPlayInline","api","ui","rangeInput","pip","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","mime","mediaType","isHTML5","media","canPlayType","textTracks","range","touch","transitions","reducedMotion","matchMedia","html5","getSources","source","getAttribute","getQualityOptions","extend","player","set","currentTime","_player$media","paused","preload","readyState","src","play","load","quality","cancelRequests","blankVideo","debug","log","dedupe","indexOf","closest","reduce","prev","curr","Math","abs","cloneDeep","JSON","parse","stringify","getDeep","path","obj","sources","shift","_defineProperty","generateId","prefix","floor","random","format","toString","match","i","getPercentage","current","max","toFixed","replaceAll","RegExp","toTitleCase","toUpperCase","substr","toLowerCase","toPascalCase","toCamelCase","slice","stripHTML","fragment","createDocumentFragment","innerHTML","firstChild","getHTML","resources","vimeo","youtube","i18n","seekTime","title","_ref2","Storage","enabled","storage","store","localStorage","getItem","json","setItem","removeItem","fetch","responseType","reject","request","XMLHttpRequest","responseText","response","Error","status","open","send","loadSprite","hasId","exists","getElementById","update","data","body","insertAdjacentElement","useStorage","cached","content","result","catch","getHours","trunc","getMinutes","getSeconds","formatTime","time","displayHours","inverted","hours","mins","secs","controls","getIconUrl","cors","iconUrl","location","host","svg4everybody","findElements","selectors","buttons","pause","restart","rewind","fastForward","mute","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","seekTooltip","tooltip","error","warn","toggleNativeControls","createIcon","iconPath","iconPrefix","icon","createElementNS","role","use","setAttributeNS","createLabel","attr","join","createBadge","badge","menu","createButton","buttonType","props","label","labelPressed","iconPressed","control","button","createRange","min","step","autocomplete","updateRangeFill","createProgress","suffixKey","played","suffix","createTime","bindMenuItemShortcuts","menuItem","which","stopPropagation","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","list","_ref$badge","checked","_ref$checked","flex","enumerable","children","node","listeners","bind","currentTrack","speed","parseFloat","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","getElementsByTagName","nodeValue","setProgress","buffered","percent","setProperty","updateSeekTooltip","tooltips","clientRect","getBoundingClientRect","visible","_this4","width","pageX","left","timeUpdate","invert","invertTime","seeking","durationUpdate","pow","hasDuration","displayDuration","toggleMenuButton","setting","updateSetting","pane","panels","default","getLabel","setQualityMenu","_this5","checkMenu","getBadge","sort","a","b","sorting","setCaptionsMenu","tracks","getTracks","_this6","toggled","language","unshift","setSpeedMenu","isVimeo","_this7","values","some","popup","firstItem","toggleMenu","show","isMenuItem","getMenuSize","tab","clone","position","opacity","scrollWidth","height","scrollHeight","size","restore","propertyName","_this8","setDownloadLink","download","create","inner","home","_this9","backButton","href","urls","isEmbed","inject","seektime","addProperty","_this10","controlPressed","_this$config","labels","parseUrl","parser","buildUrlParams","params","URLSearchParams","setup","isVideo","isYouTube","protocol","blob","createObjectURL","languages","userLanguage","active","trackEvents","_this$captions","meta","currentTrackNode","languageExists","mode","updateCues","setLanguage","activeClass","findTrack","_toConsumableArray","embed","enableTextTrack","has","sortIsDefault","sorted","every","getCurrentTrack","cues","activeCues","getCueAsHTML","cueText","caption","defaults","autoplay","autopause","toggleInvert","ratio","clickToPlay","hideControls","resetOnEnd","disableContextMenu","loop","selected","keyboard","global","fallback","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","start","end","all","reset","disabled","advertisement","qualityBadge","sdk","iframe","googleIMA","editable","embedContainer","poster","posterEnabled","ads","playing","stopped","loading","hover","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","google","publisherId","tagUrl","byline","portrait","transparent","noCookie","rel","showinfo","iv_load_policy","modestbranding","inactive","providers","types","getProviderByUrl","noop","Console","console","prototype","onChange","toggleFallback","scrollPosition","x","scrollX","y","scrollY","scrollTo","overflow","viewport","head","property","hasProperty","cleanupViewport","part","Fullscreen","forceFallback","native","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","exit","enter","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","loadImage","minWidth","image","Image","handler","onload","onerror","naturalWidth","addStyleHook","build","checkPlaying","setTitle","setPoster","togglePoster","enable","err","backgroundImage","backgroundSize","toggleControls","checkLoading","clearTimeout","timers","recentTouchSeek","lastSeekTime","Date","now","setAspectRatio","padding","_ratio$split$map2","paddingBottom","offset","transform","Listeners","lastKey","focusTimer","lastKeyDown","handleKey","setTabFocus","firstTouch","code","repeat","altKey","ctrlKey","metaKey","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","usingNative","timeStamp","wasKeyDown","delay","setPlayerSize","measure","rect","resized","_player$fullscreen","isEnter","_setPlayerSize","videoWidth","_player$embed$ratio$s2","videoHeight","maxWidth","margin","setGutter","hasAudio","initialized","managerPromise","isAudio","ended","proxy","proxyEvents","_event$detail","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","currentTarget","hasAttribute","done","seekTo","loaded","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","deltaX","deltaY","_map2","direction","sign","module","exports","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","q","splice","executeCallbacks","depsNotFound","success","loadFile","callbackFn","numTries","isCss","doc","async","maxTries","numRetries","beforeCallbackFn","before","pathStripped","onbeforeload","ev","sheet","cssText","defaultPrevented","loadjs","paths","arg1","arg2","fn","numWaiting","loadFiles","deps","bundleIds","r","subscribe","isDefined","factory","loadScript","parseId","$2","assurePlaybackState","hasPlayed","Vimeo","gesture","thumbnail_large","pathname","Player","disableTextTrack","stop","restorePause","setVolume","setCurrentTime","setPlaybackRate","name","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","_dimensions","setAutopause","state","getVideoTitle","getCurrentTime","getDuration","getTextTracks","strippedCues","_ref$cues","getPaused","seconds","parseInt","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getTitle","videoId","getVideoData","items","snippet","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","onError","message","onPlaybackRateChange","instance","playbackRate","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","getAvailablePlaybackRates","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","displayContainer","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","LOG","adError","getMessage","cancel","contentComplete","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","init","zIndex","destroy","handlers","_this11","_this12","AV_PUBLISHERID","AV_CHANNELID","AV_URL","cb","AV_WIDTH","AV_HEIGHT","AV_CDIM2","parseVtt","vttDataString","processedList","frame","line","startTime","lineSplit","_lineSplit","_lineSplit$1$split2","w","h","matchTimes","endTime","PreviewThumbnails","thumbnails","lastMouseMoveTime","mouseDown","loadedImages","thumb","scrubbing","getThumbnails","render","determineContainerAutoSizing","promises","u","getThumbnail","thumbnail","frames","urlPrefix","substring","lastIndexOf","tempImage","naturalHeight","percentage","mousePosX","showImageAtCurrentTime","toggleThumbContainer","toggleScrubbingContainer","ceil","lastTime","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","findIndex","hasThumb","qualityIndex","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","filename","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","tagName","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","clientHeight","sizeSpecifiedInCSS","thumbWidth","thumbAspectRatio","setThumbContainerPos","seekbarRect","plyrRect","minVal","maxVal","right","clientWidth","previewPos","multiplier","top","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","attribute","change","_sources$$provider","_sources$","crossorigin","Plyr","failed","jQuery","original","search","truthy","searchParams","tabindex","webkitShowPlaybackTargetPicker","isHidden","hiding","eventName","soft","unload","inputIsValid","fauxDuration","realDuration","Infinity","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","updateStorage","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","inline","t"],"mappings":"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","file":"plyr.min.mjs","sourcesContent":["// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isWeakMap = input => instanceOf(input, WeakMap);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isTextNode = input => getConstructor(input) === Text;\nconst isEvent = input => instanceOf(input, Event);\nconst isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\nconst isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\n\nconst isEmpty = input =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (e) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: this,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise(resolve =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport { toggleListener } from './events';\nimport is from './is';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) {\n return;\n }\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) {\n return;\n }\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) {\n return;\n }\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) {\n return;\n }\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.object(existing) && is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Trap focus inside container\nexport function trapFocus(element = null, toggle = false) {\n if (!is.element(element)) {\n return;\n }\n\n const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = document.activeElement;\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n if (!is.element(element)) {\n return;\n }\n\n // Set regular focus\n element.focus({ preventScroll: true });\n\n // If we want to mimic keyboard focus via tab\n if (tabFocus) {\n toggleClass(element, this.config.classNames.tabFocus);\n }\n}\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport { toggleHidden } from './elements';\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element) {\n setTimeout(() => {\n try {\n toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n toggleHidden(element, false);\n } catch (e) {\n // Do nothing\n }\n }, 0);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isEdge: window.navigator.userAgent.includes('Edge'),\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (e) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map(source => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(source => source.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n // Get first match for requested size\n const source = sources.find(source => Number(source.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n player.play();\n }\n });\n\n // Load new source\n player.media.load();\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport function replaceAll(input = '', find = '', replace = '') {\n return input.replace(\n new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'),\n replace.toString(),\n );\n}\n\n// Convert to title case\nexport function toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n}\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([key, value]) => {\n string = replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(result => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = value => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = value => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`,\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n\n const attributes = Object.assign({}, attr, {\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),\n });\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = Object.assign({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-label': i18n.get(type, this.config),\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on(\n menuItem,\n 'keydown keyup',\n event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![32, 38, 39, 40].includes(event.which)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [32, 39].includes(event.which)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.which !== 32) {\n if (event.which === 40 || (isRadioButton && event.which === 39)) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on(menuItem, 'keyup', event => {\n if (event.which !== 13) {\n return;\n }\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behaviour\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(checked) {\n // Ensure exclusivity\n if (checked) {\n Array.from(menuItem.parentNode.children)\n .filter(node => matches(node, '[role=\"menuitemradio\"]'))\n .forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n event => {\n if (is.keyboardEvent(event) && event.which !== 32) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const value = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Set the speed options\n if (is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, tabFocus = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, tabFocus);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.which === 27) {\n show = false;\n } else if (is.event(input)) {\n const isMenuItem = popup.contains(input.target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', tabFocus = false) {\n const target = document.getElementById(`plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, tabFocus);\n },\n\n // Set the download link\n setDownloadLink() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set download link\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Volume controls\n if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {\n const volume = createElement('div', {\n class: 'plyr__volume',\n });\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n volume.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n controls.createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n\n this.elements.volume = volume;\n }\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n const control = createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n control.appendChild(\n controls.createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on(menuItem, 'click', () => {\n controls.showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on(\n pane,\n 'keydown',\n event => {\n // We only care about <-\n if (event.which !== 37) {\n return;\n }\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n controls.showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on(backButton, 'click', () => {\n controls.showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n control.appendChild(popup);\n container.appendChild(control);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = control;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Download button\n if (this.config.controls.includes('download')) {\n const attributes = {\n element: 'a',\n href: this.download,\n target: '_blank',\n };\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(controls.createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n // Set available quality levels\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n } else if (is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n Object.defineProperty(button, 'pressed', {\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button)\n .filter(Boolean)\n .forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {string} input - the URL to be parsed\n * @param {boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (e) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n track.mode = 'hidden';\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n\n // Update available languages in list\n if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter(track => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(track => track.language === language);\n return !track; // Break iteration if there is a match\n });\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || [])\n .map(cue => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api:\n 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n },\n\n // YouTube plugin\n youtube: {\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { hasClass, toggleClass, trapFocus } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Trigger an event\n triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n\n if (!hasProperty) {\n viewport.content += `,${property}`;\n }\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter(part => part.trim() !== property)\n .join(',');\n }\n\n // Force a repaint as sometimes Safari doesn't want to fill the screen\n setTimeout(() => repaint(this.target), 100);\n }\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n onChange.call(this);\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get usingNative() {\n return Fullscreen.native && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n let mode;\n\n if (this.forceFallback) {\n mode = 'Fallback (forced)';\n } else if (Fullscreen.native) {\n mode = 'Native';\n } else {\n mode = 'Fallback';\n }\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitEnterFullscreen();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/loadImage';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('poster', poster);\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch(err => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw err;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n ui.togglePoster.call(this, true);\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n target.pressed = this.playing;\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls } = this.elements;\n\n if (controls && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now());\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport is from './is';\n\n/* function reduceAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n} */\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n let ratio = input;\n\n if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) {\n ({ ratio } = this.embed);\n }\n\n if (!is.string(ratio)) {\n ({ ratio } = this.config);\n }\n\n const [x, y] = ratio.split(':').map(Number);\n const padding = (100 / x) * y;\n\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n\n return { padding, ratio };\n}\n\nexport default { setAspectRatio };\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { setAspectRatio } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.setTabFocus = this.setTabFocus.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keycodes should we prevent default\n const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n player.forward();\n break;\n\n case 37:\n // Arrow back\n player.rewind();\n break;\n\n case 70:\n // F key\n player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n player.loop = !player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n }\n\n setTabFocus(event) {\n const { player } = this;\n const { elements } = player;\n\n clearTimeout(this.focusTimer);\n\n // Ignore any key other than tab\n if (event.type === 'keydown' && event.which !== 9) {\n return;\n }\n\n // Store reference to event timeStamp\n if (event.type === 'keydown') {\n this.lastKeyDown = event.timeStamp;\n }\n\n // Remove current classes\n const removeCurrent = () => {\n const className = player.config.classNames.tabFocus;\n const current = getElements.call(player, `.${className}`);\n toggleClass(current, className, false);\n };\n\n // Determine if a key was pressed to trigger this event\n const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n // Ignore focus events if a key was pressed prior\n if (event.type === 'focus' && !wasKeyDown) {\n return;\n }\n\n // Remove all current\n removeCurrent();\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n this.focusTimer = setTimeout(() => {\n const focused = document.activeElement;\n\n // Ignore if current focus element isn't inside the player\n if (!elements.container.contains(focused)) {\n return;\n }\n\n toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n }, 10);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n\n // Tab focus detection\n toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);\n }\n\n // Container listeners\n container() {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n event => {\n const { controls } = elements;\n\n // Remove button states for fullscreen\n if (controls && event.type === 'enterfullscreen') {\n controls.pressed = false;\n controls.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Force edge to repaint on exit fullscreen\n // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen\n /* if (browser.isEdge) {\n on.call(player, elements.container, 'exitfullscreen', () => {\n setTimeout(() => repaint(elements.container), 100);\n });\n } */\n\n // Set a gutter for Vimeo\n const setGutter = (ratio, padding, toggle) => {\n if (!player.isVimeo) {\n return;\n }\n\n const target = player.elements.wrapper.firstChild;\n const [, height] = ratio.split(':').map(Number);\n const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number);\n\n target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null;\n target.style.margin = toggle ? '0 auto' : null;\n };\n\n // Resize on fullscreen change\n const setPlayerSize = measure => {\n // If we don't need to measure the viewport\n if (!measure) {\n return setAspectRatio.call(player);\n }\n\n const rect = elements.container.getBoundingClientRect();\n const { width, height } = rect;\n\n return setAspectRatio.call(player, `${width}:${height}`);\n };\n\n const resized = () => {\n window.clearTimeout(timers.resized);\n timers.resized = window.setTimeout(setPlayerSize, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const { target, usingNative } = player.fullscreen;\n\n // Ignore for iOS native\n if (!player.isEmbed || target !== elements.container) {\n return;\n }\n\n const isEnter = event.type === 'enterfullscreen';\n\n // Set the player size when entering fullscreen to viewport size\n const { padding, ratio } = setPlayerSize(isEnter);\n\n // Set Vimeo gutter\n setGutter(ratio, padding, isEnter);\n\n // If not using native fullscreen, we need to check for resizes of viewport\n if (!usingNative) {\n if (isEnter) {\n on.call(player, window, 'resize', resized);\n } else {\n off.call(player, window, 'resize', resized);\n }\n }\n });\n }\n\n // Listen for media events\n media() {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event =>\n controls.durationUpdate.call(player, event),\n );\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n on.call(player, player.media, 'canplay loadeddata', () => {\n toggleHidden(elements.volume, !player.hasAudio);\n toggleHidden(elements.buttons.mute, !player.hasAudio);\n });\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n on.call(player, player.media, 'playing', () => {\n if (!player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (player.ads.enabled && !player.ads.initialized) {\n // Wait for manager response\n player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play());\n }\n });\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, player.play, 'play');\n } else {\n this.proxy(event, player.togglePlay, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadLink.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, event => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n }\n\n // Run default and custom handlers\n proxy(event, defaultHandler, customHandlerKey) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n }\n\n // Trigger custom and default handlers\n bind(element, type, defaultHandler, customHandlerKey, passive = true) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n event => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n }\n\n // Listen for control events\n controls() {\n const { player } = this;\n const { elements } = player;\n\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', player.togglePlay, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward');\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n\n controls.toggleMenu.call(player, event);\n });\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n event => {\n const code = event.which;\n\n // We only care about space and return\n if (![13, 32].includes(code)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (code === 13) {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.which === 27) {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const code = event.keyCode ? event.keyCode : event.which;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n player.play();\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n event => {\n const seek = event.currentTarget;\n\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n event => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, elements, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));\n\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n}\n\nexport default Listeners;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, stripHTML } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n setAspectRatio.call(this);\n\n // Load the API if not already\n if (!is.object(window.Vimeo)) {\n loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams(\n extend(\n {},\n {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n },\n config,\n ),\n );\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = parseId(source);\n\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Get poster, if already set\n const { poster } = player;\n\n // Inject the package\n const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n\n // Get poster image\n fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set and show poster\n ui.setPoster.call(player, url.href).catch(() => {});\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n controls.setDownloadLink.call(player);\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = `${width}:${height}`;\n setAspectRatio.call(this, player.embed.ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/loadImage';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n setAspectRatio.call(this);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (is.string(key) && !is.empty(key)) {\n const url = format(this.config.urls.youtube.api, videoId, key);\n\n fetch(url)\n .then(result => {\n if (is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n\n // Get poster, if already set\n const { poster } = player;\n\n // Replace media element\n const container = createElement('div', { id, poster });\n player.media = replaceElement(container, player.media);\n\n // Id to poster wrapper\n const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src))\n .then(posterSrc => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!posterSrc.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n\n const config = player.config.youtube;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined,\n playerVars: extend(\n {},\n {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n hl: player.config.hl, // iframe interface language\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occured';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.extend.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n event => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n triggerEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1]) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6]) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load() {\n // Togglethe regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) {\n return;\n }\n\n this.getThumbnails().then(() => {\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n this.loaded = true;\n });\n }\n\n // Download VTT files and parse them\n getThumbnails() {\n return new Promise(resolve => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n\n Promise.all(promises).then(() => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n });\n });\n }\n\n // Process individual VTT file\n getThumbnail(url) {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n if (!thumbnail.frames[0].text.startsWith('/')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n }\n\n startMove(event) {\n if (!this.loaded) {\n return;\n }\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n return;\n }\n\n // Wait until media has a duration\n if (!this.player.media.duration) {\n return;\n }\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n\n endMove() {\n this.toggleThumbContainer(false, true);\n }\n\n startScrubbing(event) {\n // Only act on left mouse button (0), or touch device (event.button is false)\n if (event.button === false || event.button === 0) {\n this.mouseDown = true;\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n }\n\n finishScrubbing() {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n }\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners() {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n }\n\n /**\n * Create HTML elements for image containers\n */\n render() {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.container.appendChild(timeContainer);\n\n // Inject the whole thumb\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n }\n\n showImageAtCurrentTime() {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.toggleThumbContainer(true);\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n this.toggleThumbContainer(hasThumb);\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumbnum or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n }\n\n // Show the image that's currently specified in this.showingThumb\n loadImage(qualityIndex = 0) {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () =>\n this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n }\n\n showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n }\n\n // Remove all preview images that aren't the designated current image\n removeOldImages(currentImage) {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n image.dataset.deleting = true;\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n }\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby(thumbNum, forward = true) {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename))\n this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n }\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n }\n\n get currentImageContainer() {\n if (this.mouseDown) {\n return this.elements.scrubbing.container;\n }\n\n return this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n if (this.mouseDown) {\n return this.currentScrubbingImageElement;\n }\n\n return this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer(toggle = false, clearShowing = false) {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n toggleScrubbingContainer(toggle = false) {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n determineContainerAutoSizing() {\n if (this.elements.thumb.imageContainer.clientHeight > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n }\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos() {\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n }\n\n this.setThumbContainerPos();\n }\n\n setThumbContainerPos() {\n const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n const plyrRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const minVal = plyrRect.left - seekbarRect.left + 10;\n const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n if (previewPos < minVal) {\n previewPos = minVal;\n }\n\n if (previewPos > maxVal) {\n previewPos = maxVal;\n }\n\n container.style.left = `${previewPos}px`;\n }\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize() {\n this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`;\n // Can't use media.clientHeight - html5 video goes big and does black bars above and below\n this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`;\n }\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset(previewImage, frame) {\n if (!this.usingSprites) {\n return;\n }\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;\n previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;\n previewImage.style.left = `-${frame.x * multiplier}px`;\n previewImage.style.top = `-${frame.y * multiplier}px`;\n }\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Reload thumbnails\n if (this.previewThumbnails) {\n this.previewThumbnails.load();\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.4.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/previewThumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { cloneDeep, extend } from './utils/objects';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div', { tabindex: 0 });\n wrap(this.media, this.elements.container);\n }\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n this.increaseVolume(-step);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {number} - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} [toggle] - Whether to show the controls\n */\n toggleControls(toggle) {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n on.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Add event listeners once\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n once(event, callback) {\n once.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.mjs b/dist/plyr.mjs new file mode 100644 index 00000000..dbef6001 --- /dev/null +++ b/dist/plyr.mjs @@ -0,0 +1,8593 @@ +typeof navigator === "object" && function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); +} + +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); +} + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); +} + +function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); +} + +// ========================================================================== +// Type checking utils +// ========================================================================== +var getConstructor = function getConstructor(input) { + return input !== null && typeof input !== 'undefined' ? input.constructor : null; +}; + +var instanceOf = function instanceOf(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); +}; + +var isNullOrUndefined = function isNullOrUndefined(input) { + return input === null || typeof input === 'undefined'; +}; + +var isObject = function isObject(input) { + return getConstructor(input) === Object; +}; + +var isNumber = function isNumber(input) { + return getConstructor(input) === Number && !Number.isNaN(input); +}; + +var isString = function isString(input) { + return getConstructor(input) === String; +}; + +var isBoolean = function isBoolean(input) { + return getConstructor(input) === Boolean; +}; + +var isFunction = function isFunction(input) { + return getConstructor(input) === Function; +}; + +var isArray = function isArray(input) { + return Array.isArray(input); +}; + +var isWeakMap = function isWeakMap(input) { + return instanceOf(input, WeakMap); +}; + +var isNodeList = function isNodeList(input) { + return instanceOf(input, NodeList); +}; + +var isElement = function isElement(input) { + return instanceOf(input, Element); +}; + +var isTextNode = function isTextNode(input) { + return getConstructor(input) === Text; +}; + +var isEvent = function isEvent(input) { + return instanceOf(input, Event); +}; + +var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); +}; + +var isCue = function isCue(input) { + return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); +}; + +var isTrack = function isTrack(input) { + return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind); +}; + +var isEmpty = function isEmpty(input) { + return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length; +}; + +var isUrl = function isUrl(input) { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } // Must be string from here + + + if (!isString(input)) { + return false; + } // Add the protocol if required + + + var string = input; + + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = "http://".concat(input); + } + + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } +}; + +var is = { + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty +}; + +// ========================================================================== +// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md +// https://www.youtube.com/watch?v=NPM6172J22g + +var supportsPassiveListeners = function () { + // Test via a getter in the options object to see if the passive property is accessed + var supported = false; + + try { + var options = Object.defineProperty({}, 'passive', { + get: function get() { + supported = true; + return null; + } + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) {// Do nothing + } + + return supported; +}(); // Toggle event listener + + +function toggleListener(element, event, callback) { + var _this = this; + + var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { + return; + } // Allow multiple events + + + var events = event.split(' '); // Build options + // Default to just the capture boolean for browsers with no passive listener support + + var options = capture; // If passive events listeners are supported + + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: passive, + // Whether the listener is a capturing listener or not + capture: capture + }; + } // If a single node is passed, bind the event listener + + + events.forEach(function (type) { + if (_this && _this.eventListeners && toggle) { + // Cache event listener + _this.eventListeners.push({ + element: element, + type: type, + callback: callback, + options: options + }); + } + + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); +} // Bind event handler + +function on(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, true, passive, capture); +} // Unbind event handler + +function off(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, false, passive, capture); +} // Bind once-only event handler + +function once(element) { + var _this2 = this; + + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + var onceCallback = function onceCallback() { + off(element, events, onceCallback, passive, capture); + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply(_this2, args); + }; + + toggleListener.call(this, element, events, onceCallback, true, passive, capture); +} // Trigger event + +function triggerEvent(element) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + // Bail if no element + if (!is.element(element) || is.empty(type)) { + return; + } // Create and dispatch the event + + + var event = new CustomEvent(type, { + bubbles: bubbles, + detail: Object.assign({}, detail, { + plyr: this + }) + }); // Dispatch the event + + element.dispatchEvent(event); +} // Unbind all cached event listeners + +function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(function (item) { + var element = item.element, + type = item.type, + callback = item.callback, + options = item.options; + element.removeEventListener(type, callback, options); + }); + this.eventListeners = []; + } +} // Run method when / if player is ready + +function ready() { + var _this3 = this; + + return new Promise(function (resolve) { + return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve); + }).then(function () {}); +} + +function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + + Array.from(targets).reverse().forEach(function (element, index) { + var child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling. + + var parent = element.parentNode; + var sibling = element.nextSibling; // Wrap the element (is automatically removed from its current + // parent). + + child.appendChild(element); // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); +} // Set attributes + +function setAttributes(element, attributes) { + if (!is.element(element) || is.empty(attributes)) { + return; + } // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" + + + Object.entries(attributes).filter(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + value = _ref2[1]; + + return !is.nullOrUndefined(value); + }).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + + return element.setAttribute(key, value); + }); +} // Create a DocumentFragment + +function createElement(type, attributes, text) { + // Create a new <element> + var element = document.createElement(type); // Set all passed attributes + + if (is.object(attributes)) { + setAttributes(element, attributes); + } // Add text node + + + if (is.string(text)) { + element.innerText = text; + } // Return built element + + + return element; +} // Inaert an element after another + +function insertAfter(element, target) { + if (!is.element(element) || !is.element(target)) { + return; + } + + target.parentNode.insertBefore(element, target.nextSibling); +} // Insert a DocumentFragment + +function insertElement(type, parent, attributes, text) { + if (!is.element(parent)) { + return; + } + + parent.appendChild(createElement(type, attributes, text)); +} // Remove element(s) + +function removeElement(element) { + if (is.nodeList(element) || is.array(element)) { + Array.from(element).forEach(removeElement); + return; + } + + if (!is.element(element) || !is.element(element.parentNode)) { + return; + } + + element.parentNode.removeChild(element); +} // Remove all child elements + +function emptyElement(element) { + if (!is.element(element)) { + return; + } + + var length = element.childNodes.length; + + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } +} // Replace element + +function replaceElement(newChild, oldChild) { + if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { + return null; + } + + oldChild.parentNode.replaceChild(newChild, oldChild); + return newChild; +} // Get an attribute object from a string selector + +function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + if (!is.string(sel) || is.empty(sel)) { + return {}; + } + + var attributes = {}; + var existing = existingAttributes; + sel.split(',').forEach(function (s) { + // Remove whitespace + var selector = s.trim(); + var className = selector.replace('.', ''); + var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value + + var parts = stripped.split('='); + var key = parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character + + var start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is.object(existing) && is.string(existing.class)) { + existing.class += " ".concat(className); + } + + attributes.class = className; + break; + + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + + case '[': + // Attribute selector + attributes[key] = value; + break; + + default: + break; + } + }); + return attributes; +} // Toggle hidden + +function toggleHidden(element, hidden) { + if (!is.element(element)) { + return; + } + + var hide = hidden; + + if (!is.boolean(hide)) { + hide = !element.hidden; + } + + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } +} // Mirror Element.classList.toggle, with IE compatibility for "force" argument + +function toggleClass(element, className, force) { + if (is.nodeList(element)) { + return Array.from(element).map(function (e) { + return toggleClass(e, className, force); + }); + } + + if (is.element(element)) { + var method = 'toggle'; + + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } + + element.classList[method](className); + return element.classList.contains(className); + } + + return false; +} // Has class name + +function hasClass(element, className) { + return is.element(element) && element.classList.contains(className); +} // Element matches selector + +function matches(element, selector) { + + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } + + var matches = match; + return matches.call(element, selector); +} // Find all elements + +function getElements(selector) { + return this.elements.container.querySelectorAll(selector); +} // Find a single element + +function getElement(selector) { + return this.elements.container.querySelector(selector); +} // Trap focus inside container + +function trapFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is.element(element)) { + return; + } + + var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + var first = focusable[0]; + var last = focusable[focusable.length - 1]; + + var trap = function trap(event) { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } // Get the current focused element + + + var focused = document.activeElement; + + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); +} // Set focus and tab focus class + +function setFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is.element(element)) { + return; + } // Set regular focus + + + element.focus({ + preventScroll: true + }); // If we want to mimic keyboard focus via tab + + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } +} + +// ========================================================================== +var transitionEndEvent = function () { + var element = document.createElement('span'); + var events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + var type = Object.keys(events).find(function (event) { + return element.style[event] !== undefined; + }); + return is.string(type) ? events[type] : false; +}(); // Force repaint of element + +function repaint(element) { + setTimeout(function () { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line + + toggleHidden(element, false); + } catch (e) {// Do nothing + } + }, 0); +} + +// ========================================================================== +// Browser sniffing +// Unfortunately, due to mixed support, UA sniffing is required +// ========================================================================== +var browser = { + isIE: + /* @cc_on!@ */ + !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) +}; + +var defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora' +}; // Check for feature support + +var support = { + // Basic support + audio: 'canPlayType' in document.createElement('audio'), + video: 'canPlayType' in document.createElement('video'), + // Check for support + // Basic functionality vs full UI + check: function check(type, provider, playsinline) { + var canPlayInline = browser.isIPhone && playsinline && support.playsinline; + var api = support[type] || provider !== 'html5'; + var ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); + return { + api: api, + ui: ui + }; + }, + // Picture-in-picture support + // Safari & Chrome only currently + pip: function () { + if (browser.isIPhone) { + return false; + } // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls + + + if (is.function(createElement('video').webkitSetPresentationMode)) { + return true; + } // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture + + + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } + + return false; + }(), + // Airplay support + // Safari only currently + airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent), + // Inline playback support + // https://webkit.org/blog/6784/new-video-policies-for-ios/ + playsinline: 'playsInline' in document.createElement('video'), + // Check for mime type support against a player instance + // Credits: http://diveintohtml5.info/everything.html + // Related: http://www.leanbackplayer.com/test/h5mt.html + mime: function mime(input) { + if (is.empty(input)) { + return false; + } + + var _input$split = input.split('/'), + _input$split2 = _slicedToArray(_input$split, 1), + mediaType = _input$split2[0]; + + var type = input; // Verify we're using HTML5 and there's no media type mismatch + + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } // Add codec if required + + + if (Object.keys(defaultCodecs).includes(type)) { + type += "; codecs=\"".concat(defaultCodecs[input], "\""); + } + + try { + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); + } catch (e) { + return false; + } + }, + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), + // <input type="range"> Sliders + rangeInput: function () { + var range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; + }(), + // Touch + // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event + touch: 'ontouchstart' in document.documentElement, + // Detect transitions support + transitions: transitionEndEvent !== false, + // Reduced motion iOS & MacOS setting + // https://webkit.org/blog/7551/responsive-design-for-motion/ + reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches +}; + +// ========================================================================== +var html5 = { + getSources: function getSources() { + var _this = this; + + if (!this.isHTML5) { + return []; + } + + var sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified) + + return sources.filter(function (source) { + var type = source.getAttribute('type'); + + if (is.empty(type)) { + return true; + } + + return support.mime.call(_this, type); + }); + }, + // Get quality levels + getQualityOptions: function getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources.call(this).map(function (source) { + return Number(source.getAttribute('size')); + }).filter(Boolean); + }, + extend: function extend() { + if (!this.isHTML5) { + return; + } + + var player = this; // Quality + + Object.defineProperty(player.media, 'quality', { + get: function get() { + // Get sources + var sources = html5.getSources.call(player); + var source = sources.find(function (source) { + return source.getAttribute('src') === player.source; + }); // Return size, if match is found + + return source && Number(source.getAttribute('size')); + }, + set: function set(input) { + // Get sources + var sources = html5.getSources.call(player); // Get first match for requested size + + var source = sources.find(function (source) { + return Number(source.getAttribute('size')) === input; + }); // No matching source found + + if (!source) { + return; + } // Get current state + + + var _player$media = player.media, + currentTime = _player$media.currentTime, + paused = _player$media.paused, + preload = _player$media.preload, + readyState = _player$media.readyState; // Set new source + + player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044) + + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', function () { + player.currentTime = currentTime; // Resume playing + + if (!paused) { + player.play(); + } + }); // Load new source + + player.media.load(); + } // Trigger change event + + + triggerEvent.call(player, player.media, 'qualitychange', false, { + quality: input + }); + } + }); + }, + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests: function cancelRequests() { + if (!this.isHTML5) { + return; + } // Remove child sources + + + removeElement(html5.getSources.call(this)); // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + + this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + + this.media.load(); // Debugging + + this.debug.log('Cancelled network requests'); + } +}; + +// ========================================================================== + +function dedupe(array) { + if (!is.array(array)) { + return array; + } + + return array.filter(function (item, index) { + return array.indexOf(item) === index; + }); +} // Get the closest value in an array + +function closest(array, value) { + if (!is.array(array) || !array.length) { + return null; + } + + return array.reduce(function (prev, curr) { + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); +} + +function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); +} // Get a nested value in an object + +function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); +} // Deep extend destination object with N more objects + +function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + if (!sources.length) { + return target; + } + + var source = sources.shift(); + + if (!is.object(source)) { + return target; + } + + Object.keys(source).forEach(function (key) { + if (is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); + } + + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); + } + }); + return extend.apply(void 0, [target].concat(sources)); +} + +// ========================================================================== + +function generateId(prefix) { + return "".concat(prefix, "-").concat(Math.floor(Math.random() * 10000)); +} // Format string + +function format(input) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (is.empty(input)) { + return input; + } + + return input.toString().replace(/{(\d+)}/g, function (match, i) { + return args[i].toString(); + }); +} // Get percentage + +function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } + + return (current / max * 100).toFixed(2); +} // Replace all occurances of a string in a string + +function replaceAll() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); +} // Convert to title case + +function toTitleCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return input.toString().replace(/\w\S*/g, function (text) { + return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); + }); +} // Convert string to pascalCase + +function toPascalCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert kebab case + + string = replaceAll(string, '-', ' '); // Convert snake case + + string = replaceAll(string, '_', ' '); // Convert to title case + + string = toTitleCase(string); // Convert to pascal case + + return replaceAll(string, ' ', ''); +} // Convert string to pascalCase + +function toCamelCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert to pascal case + + string = toPascalCase(string); // Convert first character to lowercase + + return string.charAt(0).toLowerCase() + string.slice(1); +} // Remove HTML from a string + +function stripHTML(source) { + var fragment = document.createDocumentFragment(); + var element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; +} // Like outerHTML, but also works for DocumentFragment + +function getHTML(element) { + var wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; +} + +var resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube' +}; +var i18n = { + get: function get() { + var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (is.empty(key) || is.empty(config)) { + return ''; + } + + var string = getDeep(config.i18n, key); + + if (is.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; + } + + return ''; + } + + var replace = { + '{seektime}': config.seekTime, + '{title}': config.title + }; + Object.entries(replace).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + string = replaceAll(string, key, value); + }); + return string; + } +}; + +var Storage = +/*#__PURE__*/ +function () { + function Storage(player) { + _classCallCheck(this, Storage); + + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } // Check for actual support (see if we can use it) + + + _createClass(Storage, [{ + key: "get", + value: function get(key) { + if (!Storage.supported || !this.enabled) { + return null; + } + + var store = window.localStorage.getItem(this.key); + + if (is.empty(store)) { + return null; + } + + var json = JSON.parse(store); + return is.string(key) && key.length ? json[key] : json; + } + }, { + key: "set", + value: function set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } // Can only store objectst + + + if (!is.object(object)) { + return; + } // Get current storage + + + var storage = this.get(); // Default to empty object + + if (is.empty(storage)) { + storage = {}; + } // Update the working copy of the values + + + extend(storage, object); // Update storage + + window.localStorage.setItem(this.key, JSON.stringify(storage)); + } + }], [{ + key: "supported", + get: function get() { + try { + if (!('localStorage' in window)) { + return false; + } + + var test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 + + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + } + }]); + + return Storage; +}(); + +// ========================================================================== +// Fetch wrapper +// Using XHR to avoid issues with older browsers +// ========================================================================== +function fetch(url) { + var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + return new Promise(function (resolve, reject) { + try { + var request = new XMLHttpRequest(); // Check for CORS support + + if (!('withCredentials' in request)) { + return; + } + + request.addEventListener('load', function () { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); + request.addEventListener('error', function () { + throw new Error(request.status); + }); + request.open('GET', url, true); // Set the required response type + + request.responseType = responseType; + request.send(); + } catch (e) { + reject(e); + } + }); +} + +// ========================================================================== + +function loadSprite(url, id) { + if (!is.string(url)) { + return; + } + + var prefix = 'cache'; + var hasId = is.string(id); + var isCached = false; + + var exists = function exists() { + return document.getElementById(id) !== null; + }; + + var update = function update(container, data) { + container.innerHTML = data; // Check again incase of race condition + + if (hasId && exists()) { + return; + } // Inject the SVG to the body + + + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set + + + if (!hasId || !exists()) { + var useStorage = Storage.supported; // Create container + + var container = document.createElement('div'); + container.setAttribute('hidden', ''); + + if (hasId) { + container.setAttribute('id', id); + } // Check in cache + + + if (useStorage) { + var cached = window.localStorage.getItem("".concat(prefix, "-").concat(id)); + isCached = cached !== null; + + if (isCached) { + var data = JSON.parse(cached); + update(container, data.content); + } + } // Get the sprite + + + fetch(url).then(function (result) { + if (is.empty(result)) { + return; + } + + if (useStorage) { + window.localStorage.setItem("".concat(prefix, "-").concat(id), JSON.stringify({ + content: result + })); + } + + update(container, result); + }).catch(function () {}); + } +} + +// ========================================================================== + +var getHours = function getHours(value) { + return Math.trunc(value / 60 / 60 % 60, 10); +}; +var getMinutes = function getMinutes(value) { + return Math.trunc(value / 60 % 60, 10); +}; +var getSeconds = function getSeconds(value) { + return Math.trunc(value % 60, 10); +}; // Format time to UI friendly string + +function formatTime() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if the value isn't a number + if (!is.number(time)) { + return formatTime(null, displayHours, inverted); + } // Format time component to add leading zero + + + var format = function format(value) { + return "0".concat(value).slice(-2); + }; // Breakdown to hours, mins, secs + + + var hours = getHours(time); + var mins = getMinutes(time); + var secs = getSeconds(time); // Do we need to display hours? + + if (displayHours || hours > 0) { + hours = "".concat(hours, ":"); + } else { + hours = ''; + } // Render + + + return "".concat(inverted && time > 0 ? '-' : '').concat(hours).concat(format(mins), ":").concat(format(secs)); +} + +var controls = { + // Get icon URL + getIconUrl: function getIconUrl() { + var url = new URL(this.config.iconUrl, window.location); + var cors = url.host !== window.location.host || browser.isIE && !window.svg4everybody; + return { + url: this.config.iconUrl, + cors: cors + }; + }, + // Find the UI controls + findElements: function findElements() { + try { + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons + + this.elements.buttons = { + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen) + }; // Progress + + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs + + this.elements.inputs = { + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume) + }; // Display + + this.elements.display = { + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration) + }; // Seek tooltip + + if (is.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip)); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls + + this.toggleNativeControls(true); + return false; + } + }, + // Create <svg> icon + createIcon: function createIcon(type, attributes) { + var namespace = 'http://www.w3.org/2000/svg'; + var iconUrl = controls.getIconUrl.call(this); + var iconPath = "".concat(!iconUrl.cors ? iconUrl.url : '', "#").concat(this.config.iconPrefix); // Create <svg> + + var icon = document.createElementNS(namespace, 'svg'); + setAttributes(icon, extend(attributes, { + role: 'presentation', + focusable: 'false' + })); // Create the <use> to reference sprite + + var use = document.createElementNS(namespace, 'use'); + var path = "".concat(iconPath, "-").concat(type); // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href + + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } // Always set the older attribute even though it's "deprecated" (it'll be around for ages) + + + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg> + + icon.appendChild(use); + return icon; + }, + // Create hidden text label + createLabel: function createLabel(key) { + var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var text = i18n.get(key, this.config); + var attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') + }); + return createElement('span', attributes, text); + }, + // Create a badge + createBadge: function createBadge(text) { + if (is.empty(text)) { + return null; + } + + var badge = createElement('span', { + class: this.config.classNames.menu.value + }); + badge.appendChild(createElement('span', { + class: this.config.classNames.menu.badge + }, text)); + return badge; + }, + // Create a <button> + createButton: function createButton(buttonType, attr) { + var attributes = Object.assign({}, attr); + var type = toCamelCase(buttonType); + var props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null + }; + ['element', 'icon', 'label'].forEach(function (key) { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); // Default to 'button' type to prevent form submission + + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { + attributes.type = 'button'; + } // Set class name + + + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { + attributes.class += " ".concat(this.config.classNames.control); + } + } else { + attributes.class = this.config.classNames.control; + } // Large play button + + + switch (buttonType) { + case 'play': + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; + break; + + case 'mute': + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; + break; + + case 'captions': + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; + break; + + case 'fullscreen': + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; + break; + + case 'play-large': + attributes.class += " ".concat(this.config.classNames.control, "--overlaid"); + type = 'play'; + props.label = 'play'; + props.icon = 'play'; + break; + + default: + if (is.empty(props.label)) { + props.label = type; + } + + if (is.empty(props.icon)) { + props.icon = buttonType; + } + + } + + var button = createElement(props.element); // Setup toggle icon and labels + + if (props.toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed' + })); + button.appendChild(controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed' + })); // Label/Tooltip + + button.appendChild(controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed' + })); + button.appendChild(controls.createLabel.call(this, props.label, { + class: 'label--not-pressed' + })); + } else { + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); + } // Merge and set attributes + + + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons + + if (type === 'play') { + if (!is.array(this.elements.buttons[type])) { + this.elements.buttons[type] = []; + } + + this.elements.buttons[type].push(button); + } else { + this.elements.buttons[type] = button; + } + + return button; + }, + // Create an <input type='range'> + createRange: function createRange(type, attributes) { + // Seek input + var input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + // A11y fixes for https://github.com/sampotts/plyr/issues/905 + role: 'slider', + 'aria-label': i18n.get(type, this.config), + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'aria-valuenow': 0 + }, attributes)); + this.elements.inputs[type] = input; // Set the fill for webkit now + + controls.updateRangeFill.call(this, input); + return input; + }, + // Create a <progress> + createProgress: function createProgress(type, attributes) { + var progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), { + min: 0, + max: 100, + value: 0, + role: 'presentation', + 'aria-hidden': true + }, attributes)); // Create the label inside + + if (type !== 'volume') { + progress.appendChild(createElement('span', null, '0')); + var suffixKey = { + played: 'played', + buffer: 'buffered' + }[type]; + var suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; + progress.innerText = "% ".concat(suffix.toLowerCase()); + } + + this.elements.display[type] = progress; + return progress; + }, + // Create time display + createTime: function createTime(type) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + var container = createElement('div', extend(attributes, { + class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-label': i18n.get(type, this.config) + }), '00:00'); // Reference for updates + + this.elements.display[type] = container; + return container; + }, + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { + var _this = this; + + // Navigate through menus via arrow keys and space + on(menuItem, 'keydown keyup', function (event) { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } // Prevent play / seek + + + event.preventDefault(); + event.stopPropagation(); // We're just here to prevent the keydown bubbling + + if (event.type === 'keydown') { + return; + } + + var isRadioButton = matches(menuItem, '[role="menuitemradio"]'); // Show the respective menu + + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(_this, type, true); + } else { + var target; + + if (event.which !== 32) { + if (event.which === 40 || isRadioButton && event.which === 39) { + target = menuItem.nextElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.lastElementChild; + } + } + + setFocus.call(_this, target, true); + } + } + }, false); // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here + + on(menuItem, 'keyup', function (event) { + if (event.which !== 13) { + return; + } + + controls.focusFirstMenuItem.call(_this, null, true); + }); + }, + // Create a settings menu item + createMenuItem: function createMenuItem(_ref) { + var _this2 = this; + + var value = _ref.value, + list = _ref.list, + type = _ref.type, + title = _ref.title, + _ref$badge = _ref.badge, + badge = _ref$badge === void 0 ? null : _ref$badge, + _ref$checked = _ref.checked, + checked = _ref$checked === void 0 ? false : _ref$checked; + var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + var menuItem = createElement('button', extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: "".concat(this.config.classNames.control, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-checked': checked, + value: value + })); + var flex = createElement('span'); // We have to set as HTML incase of special characters + + flex.innerHTML = title; + + if (is.element(badge)) { + flex.appendChild(badge); + } + + menuItem.appendChild(flex); // Replicate radio button behaviour + + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get: function get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set: function set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children).filter(function (node) { + return matches(node, '[role="menuitemradio"]'); + }).forEach(function (node) { + return node.setAttribute('aria-checked', 'false'); + }); + } + + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + } + }); + this.listeners.bind(menuItem, 'click keyup', function (event) { + if (is.keyboardEvent(event) && event.which !== 32) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + menuItem.checked = true; + + switch (type) { + case 'language': + _this2.currentTrack = Number(value); + break; + + case 'quality': + _this2.quality = value; + break; + + case 'speed': + _this2.speed = parseFloat(value); + break; + + default: + break; + } + + controls.showMenuPanel.call(_this2, 'home', is.keyboardEvent(event)); + }, type, false); + controls.bindMenuItemShortcuts.call(this, menuItem, type); + list.appendChild(menuItem); + }, + // Format a time for display + formatTime: function formatTime$$1() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + // Bail if the value isn't a number + if (!is.number(time)) { + return time; + } // Always display hours if duration is over an hour + + + var forceHours = getHours(this.duration) > 0; + return formatTime(time, forceHours, inverted); + }, + // Update the displayed time + updateTimeDisplay: function updateTimeDisplay() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if there's no element to display or the value isn't a number + if (!is.element(target) || !is.number(time)) { + return; + } // eslint-disable-next-line no-param-reassign + + + target.innerText = controls.formatTime(time, inverted); + }, + // Update volume UI and storage + updateVolume: function updateVolume() { + if (!this.supported.ui) { + return; + } // Update range + + + if (is.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } // Update mute state + + + if (is.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } + }, + // Update seek value and lower fill + setRange: function setRange(target) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (!is.element(target)) { + return; + } // eslint-disable-next-line + + + target.value = value; // Webkit range fill + + controls.updateRangeFill.call(this, target); + }, + // Update <progress> elements + updateProgress: function updateProgress(event) { + var _this3 = this; + + if (!this.supported.ui || !is.event(event)) { + return; + } + + var value = 0; + + var setProgress = function setProgress(target, input) { + var value = is.number(input) ? input : 0; + var progress = is.element(target) ? target : _this3.elements.display.buffer; // Update value and label + + if (is.element(progress)) { + progress.value = value; // Update text label inside + + var label = progress.getElementsByTagName('span')[0]; + + if (is.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event + + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + // Check buffer status + + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + break; + + default: + break; + } + } + }, + // Webkit polyfill for lower fill range + updateRangeFill: function updateRangeFill(target) { + // Get range from event if event passed + var range = is.event(target) ? target.target : target; // Needs to be a valid <input type='range'> + + if (!is.element(range) || range.getAttribute('type') !== 'range') { + return; + } // Set aria values for https://github.com/sampotts/plyr/issues/905 + + + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + var currentTime = controls.formatTime(this.currentTime); + var duration = controls.formatTime(this.duration); + var format$$1 = i18n.get('seekLabel', this.config); + range.setAttribute('aria-valuetext', format$$1.replace('{currentTime}', currentTime).replace('{duration}', duration)); + } else if (matches(range, this.config.selectors.inputs.volume)) { + var percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', "".concat(percent.toFixed(1), "%")); + } else { + range.setAttribute('aria-valuenow', range.value); + } // WebKit only + + + if (!browser.isWebkit) { + return; + } // Set CSS custom property + + + range.style.setProperty('--value', "".concat(range.value / range.max * 100, "%")); + }, + // Update hover tooltip for seeking + updateSeekTooltip: function updateSeekTooltip(event) { + var _this4 = this; + + // Bail if setting not true + if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) { + return; + } // Calculate percentage + + + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + var visible = "".concat(this.config.classNames.tooltip, "--visible"); + + var toggle = function toggle(_toggle) { + toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + }; // Hide on touch + + + if (this.touch) { + toggle(false); + return; + } // Determine percentage, if already visible + + + if (is.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } // Set bounds + + + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } // Display the time a click would seek to + + + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position + + this.elements.display.seekTooltip.style.left = "".concat(percent, "%"); // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds + + if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + toggle(event.type === 'mouseenter'); + } + }, + // Handle time change event + timeUpdate: function timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + var invert = !is.element(this.elements.display.duration) && this.config.invertTime; // Duration + + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking + + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } // Playing progress + + + controls.updateProgress.call(this, event); + }, + // Show the duration on metadataloaded or durationchange events + durationUpdate: function durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || !this.config.invertTime && this.currentTime) { + return; + } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 + + + if (this.duration >= Math.pow(2, 32)) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } // Update ARIA values + + + if (is.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); + } // If there's a spot to display duration + + + var hasDuration = is.element(this.elements.display.duration); // If there's only one time display, display duration there + + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } // If there's a duration element, update content + + + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } // Update the tooltip (if visible) + + + controls.updateSeekTooltip.call(this); + }, + // Hide/show a tab + toggleMenuButton: function toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); + }, + // Update the selected setting + updateSetting: function updateSetting(setting, container, input) { + var pane = this.elements.settings.panels[setting]; + var value = null; + var list = container; + + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is.empty(input) ? input : this[setting]; // Get default + + if (is.empty(value)) { + value = this.config[setting].default; + } // Unsupported value + + + if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn("Unsupported value of '".concat(value, "' for ").concat(setting)); + return; + } // Disabled value + + + if (!this.config[setting].options.includes(value)) { + this.debug.warn("Disabled value of '".concat(value, "' for ").concat(setting)); + return; + } + } // Get the list if we need to + + + if (!is.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } // If there's no list it means it's not been rendered... + + + if (!is.element(list)) { + return; + } // Update the label + + + var label = this.elements.settings.buttons[setting].querySelector(".".concat(this.config.classNames.menu.value)); + label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it + + var target = list && list.querySelector("[value=\"".concat(value, "\"]")); + + if (is.element(target)) { + target.checked = true; + } + }, + // Translate a value into a nice label + getLabel: function getLabel(setting, value) { + switch (setting) { + case 'speed': + return value === 1 ? i18n.get('normal', this.config) : "".concat(value, "×"); + + case 'quality': + if (is.number(value)) { + var label = i18n.get("qualityLabel.".concat(value), this.config); + + if (!label.length) { + return "".concat(value, "p"); + } + + return label; + } + + return toTitleCase(value); + + case 'captions': + return captions.getLabel.call(this); + + default: + return null; + } + }, + // Set the quality menu + setQualityMenu: function setQualityMenu(options) { + var _this5 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.quality)) { + return; + } + + var type = 'quality'; + var list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); // Set options if passed and filter based on uniqueness and config + + if (is.array(options)) { + this.options.quality = dedupe(options).filter(function (quality) { + return _this5.config.quality.options.includes(quality); + }); + } // Toggle the pane and tab + + + var toggle = !is.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Get the badge HTML for HD, 4K etc + + + var getBadge = function getBadge(quality) { + var label = i18n.get("qualityBadge.".concat(quality), _this5.config); + + if (!label.length) { + return null; + } + + return controls.createBadge.call(_this5, label); + }; // Sort options by the config and then render options + + + this.options.quality.sort(function (a, b) { + var sorting = _this5.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }).forEach(function (quality) { + controls.createMenuItem.call(_this5, { + value: quality, + list: list, + type: type, + title: controls.getLabel.call(_this5, 'quality', quality), + badge: getBadge(quality) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Set the looping options + + /* setLoopMenu() { + // Menu required + if (!is.element(this.elements.settings.panels.loop)) { + return; + } + const options = ['start', 'end', 'all', 'reset']; + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); + // Show the pane and tab + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); + // Toggle the pane and tab + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); + // Empty the menu + emptyElement(list); + options.forEach(option => { + const item = createElement('li'); + const button = createElement( + 'button', + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { + type: 'button', + class: this.config.classNames.control, + 'data-plyr-loop-action': option, + }), + i18n.get(option, this.config) + ); + if (['start', 'end'].includes(option)) { + const badge = controls.createBadge.call(this, '00:00'); + button.appendChild(badge); + } + item.appendChild(button); + list.appendChild(item); + }); + }, */ + // Get current selected caption language + // TODO: rework this to user the getter in the API? + // Set a list of available captions languages + setCaptionsMenu: function setCaptionsMenu() { + var _this6 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.captions)) { + return; + } // TODO: Captions or language? Currently it's mixed + + + var type = 'captions'; + var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + var tracks = captions.getTracks.call(this); + var toggle = Boolean(tracks.length); // Toggle the pane and tab + + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If there's no captions, bail + + if (!toggle) { + return; + } // Generate options data + + + var options = tracks.map(function (track, value) { + return { + value: value, + checked: _this6.captions.toggled && _this6.currentTrack === value, + title: captions.getLabel.call(_this6, track), + badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + list: list, + type: 'language' + }; + }); // Add the "Disabled" option to turn off captions + + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list: list, + type: 'language' + }); // Generate options + + options.forEach(controls.createMenuItem.bind(this)); + controls.updateSetting.call(this, type, list); + }, + // Set a list of available captions languages + setSpeedMenu: function setSpeedMenu(options) { + var _this7 = this; + + // Menu required + if (!is.element(this.elements.settings.panels.speed)) { + return; + } + + var type = 'speed'; + var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options + + if (is.array(options)) { + this.options.speed = options; + } else if (this.isHTML5 || this.isVimeo) { + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + } // Set options if passed and filter based on config + + + this.options.speed = this.options.speed.filter(function (speed) { + return _this7.config.speed.options.includes(speed); + }); // Toggle the pane and tab + + var toggle = !is.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Create items + + + this.options.speed.forEach(function (speed) { + controls.createMenuItem.call(_this7, { + value: speed, + list: list, + type: type, + title: controls.getLabel.call(_this7, 'speed', speed) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Check if we need to hide/show the settings menu + checkMenu: function checkMenu() { + var buttons = this.elements.settings.buttons; + var visible = !is.empty(buttons) && Object.values(buttons).some(function (button) { + return !button.hidden; + }); + toggleHidden(this.elements.settings.menu, !visible); + }, + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem: function focusFirstMenuItem(pane) { + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (this.elements.settings.popup.hidden) { + return; + } + + var target = pane; + + if (!is.element(target)) { + target = Object.values(this.elements.settings.panels).find(function (pane) { + return !pane.hidden; + }); + } + + var firstItem = target.querySelector('[role^="menuitem"]'); + setFocus.call(this, firstItem, tabFocus); + }, + // Show/hide menu + toggleMenu: function toggleMenu(input) { + var popup = this.elements.settings.popup; + var button = this.elements.buttons.settings; // Menu and button are required + + if (!is.element(popup) || !is.element(button)) { + return; + } // True toggle by default + + + var hidden = popup.hidden; + var show = hidden; + + if (is.boolean(input)) { + show = input; + } else if (is.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is.event(input)) { + var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) + + if (isMenuItem || !isMenuItem && input.target !== button && show) { + return; + } + } // Set button attributes + + + button.setAttribute('aria-expanded', show); // Show the actual popup + + toggleHidden(popup, !show); // Add class hook + + toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction + + if (show && is.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is.keyboardEvent(input)); + } + }, + // Get the natural size of a menu panel + getMenuSize: function getMenuSize(tab) { + var clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.removeAttribute('hidden'); // Append to parent so we get the "real" size + + tab.parentNode.appendChild(clone); // Get the sizes before we remove + + var width = clone.scrollWidth; + var height = clone.scrollHeight; // Remove from the DOM + + removeElement(clone); + return { + width: width, + height: height + }; + }, + // Show a panel in the menu + showMenuPanel: function showMenuPanel() { + var _this8 = this; + + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail + + if (!is.element(target)) { + return; + } // Hide all other panels + + + var container = target.parentNode; + var current = Array.from(container.children).find(function (node) { + return !node.hidden; + }); // If we can do fancy animations, we'll animate the height/width + + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = "".concat(current.scrollWidth, "px"); + container.style.height = "".concat(current.scrollHeight, "px"); // Get potential sizes + + var size = controls.getMenuSize.call(this, target); // Restore auto height/width + + var restore = function restore(event) { + // We're only bothered about height and width on the container + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { + return; + } // Revert back to auto + + + container.style.width = ''; + container.style.height = ''; // Only listen once + + off.call(_this8, container, transitionEndEvent, restore); + }; // Listen for the transition finishing and restore auto height/width + + + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target + + container.style.width = "".concat(size.width, "px"); + container.style.height = "".concat(size.height, "px"); + } // Set attributes on current tab + + + toggleHidden(current, true); // Set attributes on target + + toggleHidden(target, false); // Focus the first item + + controls.focusFirstMenuItem.call(this, target, tabFocus); + }, + // Set the download link + setDownloadLink: function setDownloadLink() { + var button = this.elements.buttons.download; // Bail if no button + + if (!is.element(button)) { + return; + } // Set download link + + + button.setAttribute('href', this.download); + }, + // Build the default HTML + // TODO: Set order based on order in the config.controls array? + create: function create(data) { + var _this9 = this; + + // Create the container + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button + + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } // Rewind button + + + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } // Play/Pause button + + + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + } // Fast forward button + + + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } // Progress + + + if (this.config.controls.includes('progress')) { + var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider + + progress.appendChild(controls.createRange.call(this, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress + + progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip + + if (this.config.tooltips.seek) { + var tooltip = createElement('span', { + class: this.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; + } + + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } // Media current time display + + + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } // Media duration display + + + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } // Volume controls + + + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + var volume = createElement('div', { + class: 'plyr__volume' + }); // Toggle mute button + + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } // Volume range control + + + if (this.config.controls.includes('volume')) { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: this.config.volume + }; // Create the volume range slider + + volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + this.elements.volume = volume; + } + + container.appendChild(volume); + } // Toggle captions button + + + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } // Settings button / menu + + + if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + var control = createElement('div', { + class: 'plyr__menu', + hidden: '' + }); + control.appendChild(controls.createButton.call(this, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu + + var menu = createElement('div', { + role: 'menu' + }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; // Build the menu items + + this.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + controls.showMenuPanel.call(_this9, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this9.config)); + var value = createElement('span', { + class: _this9.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this9.config))); // Screen reader label + + backButton.appendChild(createElement('span', { + class: _this9.config.classNames.hidden + }, i18n.get('menuBack', _this9.config))); // Go back via keyboard + + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek + + + event.preventDefault(); + event.stopPropagation(); // Show the respective menu + + controls.showMenuPanel.call(_this9, 'home', true); + }, false); // Go back via button click + + on(backButton, 'click', function () { + controls.showMenuPanel.call(_this9, 'home', false); + }); // Add to pane + + pane.appendChild(backButton); // Menu + + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this9.elements.settings.buttons[type] = menuItem; + _this9.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); + this.elements.settings.popup = popup; + this.elements.settings.menu = control; + } // Picture in picture button + + + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } // Airplay button + + + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } // Download button + + + if (this.config.controls.includes('download')) { + var _attributes = { + element: 'a', + href: this.download, + target: '_blank' + }; + var download = this.config.urls.download; + + if (!is.url(download) && this.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(this.provider), + label: this.provider + }); + } + + container.appendChild(controls.createButton.call(this, 'download', _attributes)); + } // Toggle fullscreen button + + + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } // Larger overlaid play button + + + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } + + this.elements.controls = container; // Set available quality levels + + if (this.isHTML5) { + controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + } + + controls.setSpeedMenu.call(this); + return container; + }, + // Insert controls + inject: function inject() { + var _this10 = this; + + // Sprite + if (this.config.loadSprite) { + var icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX + + if (icon.cors) { + loadSprite(icon.url, 'sprite-plyr'); + } + } // Create a unique ID + + + this.id = Math.floor(Math.random() * 10000); // Null by default + + var container = null; + this.elements.controls = null; // Set template properties + + var props = { + id: this.id, + seektime: this.config.seekTime, + title: this.config.title + }; + var update = true; // If function, run it and use output + + if (is.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } // Convert falsy controls to empty array (primarily for empty strings) + + + if (!this.config.controls) { + this.config.controls = []; + } + + if (is.element(this.config.controls) || is.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option + container = this.config.controls; + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: captions.getLabel.call(this) // TODO: Looping + // loop: 'None', + + }); + update = false; + } // Replace props with their value + + + var replace = function replace(input) { + var result = input; + Object.entries(props).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + value = _ref3[1]; + + result = replaceAll(result, "{".concat(key, "}"), value); + }); + return result; + }; // Update markup + + + if (update) { + if (is.string(this.config.controls)) { + container = replace(container); + } else if (is.element(container)) { + container.innerHTML = replace(container.innerHTML); + } + } // Controls container + + + var target; // Inject to custom location + + if (is.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } // Inject into the container by default + + + if (!is.element(target)) { + target = this.elements.container; + } // Inject controls HTML (needs to be before captions, hence "afterbegin") + + + var insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be + + if (!is.element(this.elements.controls)) { + controls.findElements.call(this); + } // Add pressed property to buttons + + + if (!is.empty(this.elements.buttons)) { + var addProperty = function addProperty(button) { + var className = _this10.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get: function get() { + return hasClass(button, className); + }, + set: function set() { + var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + toggleClass(button, className, pressed); + } + }); + }; // Toggle classname when pressed property is set + + + Object.values(this.elements.buttons).filter(Boolean).forEach(function (button) { + if (is.array(button) || is.nodeList(button)) { + Array.from(button).filter(Boolean).forEach(addProperty); + } else { + addProperty(button); + } + }); + } // Edge sometimes doesn't finish the paint so force a repaint + + + if (browser.isEdge) { + repaint(target); + } // Setup tooltips + + + if (this.config.tooltips.controls) { + var _this$config = this.config, + classNames = _this$config.classNames, + selectors = _this$config.selectors; + var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); + var labels = getElements.call(this, selector); + Array.from(labels).forEach(function (label) { + toggleClass(label, _this10.config.classNames.hidden, false); + toggleClass(label, _this10.config.classNames.tooltip, true); + }); + } + } +}; + +/** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ + +function parseUrl(input) { + var safe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var url = input; + + if (safe) { + var parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } + + try { + return new URL(url); + } catch (e) { + return null; + } +} // Convert object to URLSearchParams + +function buildUrlParams(input) { + var params = new URLSearchParams(); + + if (is.object(input)) { + Object.entries(input).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + params.set(key, value); + }); + } + + return params; +} + +var captions = { + // Setup captions + setup: function setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } // Only Vimeo and HTML5 video supported at this point + + + if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { + // Clear menu and hide + if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + + return; + } // Inject the container + + + if (!is.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); + insertAfter(this.elements.captions, this.elements.wrapper); + } // Fix IE captions if CORS is used + // Fetch captions and inject as blobs instead (data URIs not supported!) + + + if (browser.isIE && window.URL) { + var elements = this.media.querySelectorAll('track'); + Array.from(elements).forEach(function (track) { + var src = track.getAttribute('src'); + var url = parseUrl(src); + + if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + fetch(src, 'blob').then(function (blob) { + track.setAttribute('src', window.URL.createObjectURL(blob)); + }).catch(function () { + removeElement(track); + }); + } + }); + } // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state + + + var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + var languages = dedupe(browserLanguages.map(function (language) { + return language.split('-')[0]; + })); + var language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto' + + if (language === 'auto') { + var _languages = _slicedToArray(languages, 1); + + language = _languages[0]; + } + + var active = this.storage.get('captions'); + + if (!is.boolean(active)) { + active = this.config.captions.active; + } + + Object.assign(this.captions, { + toggled: false, + active: active, + language: language, + languages: languages + }); // Watch changes to textTracks and update captions menu + + if (this.isHTML5) { + var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); + } // Update available languages in list next tick (the event must not be triggered before the listeners) + + + setTimeout(captions.update.bind(this), 0); + }, + // Update available language options in settings based on tracks + update: function update() { + var _this = this; + + var tracks = captions.getTracks.call(this, true); // Get the wanted language + + var _this$captions = this.captions, + active = _this$captions.active, + language = _this$captions.language, + meta = _this$captions.meta, + currentTrackNode = _this$captions.currentTrackNode; + var languageExists = Boolean(tracks.find(function (track) { + return track.language === language; + })); // Handle tracks (add event listener and "pseudo"-default) + + if (this.isHTML5 && this.isVideo) { + tracks.filter(function (track) { + return !meta.get(track); + }).forEach(function (track) { + _this.debug.log('Track added', track); // Attempt to store if the original dom element was "default" + + + meta.set(track, { + default: track.mode === 'showing' + }); // Turn off native caption rendering to avoid double captions + + track.mode = 'hidden'; // Add event listener for cue changes + + on.call(_this, track, 'cuechange', function () { + return captions.updateCues.call(_this); + }); + }); + } // Update language first time it matches, or if the previous matching track was removed + + + if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } // Enable or disable captions based on track length + + + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks)); // Update available languages in list + + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + }, + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle: function toggle(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // If there's no full support + if (!this.supported.ui) { + return; + } + + var toggled = this.captions.toggled; // Current state + + var activeClass = this.config.classNames.captions.active; // Get the next state + // If the method is called without parameter, toggle based on current value + + var active = is.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event + + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ + captions: active + }); + } // Force language if the call isn't passive and there is no matching language to toggle to + + + if (!this.language && active && !passive) { + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [this.captions.language].concat(_toConsumableArray(this.captions.languages)), true); // Override user preferences to avoid switching languages if a matching track is added + + this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference + + captions.set.call(this, tracks.indexOf(track)); + return; + } // Toggle button if it's enabled + + + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } // Add class hook + + + toggleClass(this.elements.container, activeClass, active); + this.captions.toggled = active; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) + + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } + }, + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set: function set(index) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var tracks = captions.getTracks.call(this); // Disable captions if setting to -1 + + if (index === -1) { + captions.toggle.call(this, false, passive); + return; + } + + if (!is.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } + + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; + } + + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + var track = tracks[index]; + + var _ref = track || {}, + language = _ref.language; // Store reference to node for invalidation on remove + + + this.captions.currentTrackNode = track; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences + + if (!passive) { + this.captions.language = language; + this.storage.set({ + language: language + }); + } // Handle Vimeo captions + + + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } // Trigger event + + + triggerEvent.call(this, this.media, 'languagechange'); + } // Show captions + + + captions.toggle.call(this, true, passive); + + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } + }, + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage: function setLanguage(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (!is.string(input)) { + this.debug.warn('Invalid language argument', input); + return; + } // Normalize + + + var language = input.toLowerCase(); + this.captions.language = language; // Set currentTrack + + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks: function getTracks() { + var _this2 = this; + + var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + // Handle media or textTracks missing or null + var tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + + return tracks.filter(function (track) { + return !_this2.isHTML5 || update || _this2.captions.meta.has(track); + }).filter(function (track) { + return ['captions', 'subtitles'].includes(track.kind); + }); + }, + // Match tracks based on languages and get the first + findTrack: function findTrack(languages) { + var _this3 = this; + + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var tracks = captions.getTracks.call(this); + + var sortIsDefault = function sortIsDefault(track) { + return Number((_this3.captions.meta.get(track) || {}).default); + }; + + var sorted = Array.from(tracks).sort(function (a, b) { + return sortIsDefault(b) - sortIsDefault(a); + }); + var track; + languages.every(function (language) { + track = sorted.find(function (track) { + return track.language === language; + }); + return !track; // Break iteration if there is a match + }); // If no match is found but is required, get first + + return track || (force ? sorted[0] : undefined); + }, + // Get the current track + getCurrentTrack: function getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; + }, + // Get UI label for track + getLabel: function getLabel(track) { + var currentTrack = track; + + if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) { + currentTrack = captions.getCurrentTrack.call(this); + } + + if (is.track(currentTrack)) { + if (!is.empty(currentTrack.label)) { + return currentTrack.label; + } + + if (!is.empty(currentTrack.language)) { + return track.language.toUpperCase(); + } + + return i18n.get('enabled', this.config); + } + + return i18n.get('disabled', this.config); + }, + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues: function updateCues(input) { + // Requires UI + if (!this.supported.ui) { + return; + } + + if (!is.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; + } // Only accept array or empty input + + + if (!is.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); + return; + } + + var cues = input; // Get cues from track + + if (!cues) { + var track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []).map(function (cue) { + return cue.getCueAsHTML(); + }).map(getHTML); + } // Set new caption text + + + var content = cues.map(function (cueText) { + return cueText.trim(); + }).join('\n'); + var changed = content !== this.elements.captions.innerHTML; + + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + var caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); // Trigger event + + triggerEvent.call(this, this.media, 'cuechange'); + } + } +}; + +// ========================================================================== +// Plyr default config +// ========================================================================== +var defaults = { + // Disable + enabled: true, + // Custom media title + title: '', + // Logging to console + debug: false, + // Auto play (if supported) + autoplay: false, + // Only allow one media playing at once (vimeo only) + autopause: true, + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, + // Default time to skip when rewind/fast forward + seekTime: 10, + // Default volume + volume: 1, + muted: false, + // Pass a custom duration + duration: null, + // Display the media duration on load in the current time position + // If you have opted to display both duration and currentTime, this is ignored + displayDuration: true, + // Invert the current time to be a countdown + invertTime: true, + // Clicking the currentTime inverts it's value to show time left rather than elapsed + toggleInvert: true, + // Aspect ratio (for embeds) + ratio: '16:9', + // Click video container to play/pause + clickToPlay: true, + // Auto hide the controls + hideControls: true, + // Reset to start when playback ended + resetOnEnd: false, + // Disable the standard context menu + disableContextMenu: true, + // Sprite (for icons) + loadSprite: true, + iconPrefix: 'plyr', + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', + // Blank video (used to prevent errors on source change) + blankVideo: 'https://cdn.plyr.io/static/blank.mp4', + // Quality default + quality: { + default: 576, + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] + }, + // Set loops + loop: { + active: false // start: null, + // end: null, + + }, + // Speed default and options to display + speed: { + selected: 1, + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] + }, + // Keyboard shortcut settings + keyboard: { + focused: true, + global: false + }, + // Display tooltips + tooltips: { + controls: false, + seek: true + }, + // Captions settings + captions: { + active: false, + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false + }, + // Fullscreen settings + fullscreen: { + enabled: true, + // Allow fullscreen? + fallback: true, + // Fallback using full viewport/window + iosNative: false // Use the native fullscreen in iOS (disables custom controls) + + }, + // Local storage + storage: { + enabled: true, + key: 'plyr' + }, + // Default controls + controls: ['play-large', // 'restart', + // 'rewind', + 'play', // 'fast-forward', + 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download', + 'fullscreen'], + settings: ['captions', 'quality', 'speed'], + // Localisation + i18n: { + restart: 'Restart', + rewind: 'Rewind {seektime}s', + play: 'Play', + pause: 'Pause', + fastForward: 'Forward {seektime}s', + seek: 'Seek', + seekLabel: '{currentTime} of {duration}', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + download: 'Download', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + menuBack: 'Go back to previous menu', + speed: 'Speed', + normal: 'Normal', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + disabled: 'Disabled', + enabled: 'Enabled', + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } + }, + // URLs + urls: { + download: null, + vimeo: { + sdk: 'https://player.vimeo.com/api/player.js', + iframe: 'https://player.vimeo.com/video/{0}?{1}', + api: 'https://vimeo.com/api/v2/video/{0}.json' + }, + youtube: { + sdk: 'https://www.youtube.com/iframe_api', + api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + }, + googleIMA: { + sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' + } + }, + // Custom control listeners + listeners: { + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + fastForward: null, + mute: null, + volume: null, + captions: null, + download: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null + }, + // Events to watch and bubble + events: [// Events to watch on HTML5 media elements and bubble + // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events + 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube + 'statechange', // Quality + 'qualitychange', // Ads + 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], + // Selectors + // Change these to match your template if using custom HTML + selectors: { + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls' + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + fastForward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]' + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]' + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', + // Used later + volume: '.plyr__volume--display' + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + caption: '.plyr__caption', + menu: { + quality: '.js-plyr__menu__list--quality' + } + }, + // Class hooks added to the player in different states + classNames: { + type: 'plyr--{0}', + provider: 'plyr--{0}', + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + embedContainer: 'plyr__video-embed__container', + poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', + ads: 'plyr__ads', + control: 'plyr__control', + controlPressed: 'plyr__control--pressed', + playing: 'plyr--playing', + paused: 'plyr--paused', + stopped: 'plyr--stopped', + loading: 'plyr--loading', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + cues: 'plyr__cues', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time' + }, + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open' + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active' + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback' + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active' + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active' + }, + tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' + } + }, + // Embed attributes + attributes: { + embed: { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id' + } + }, + // API keys + keys: { + google: null + }, + // Advertisements plugin + // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio + ads: { + enabled: false, + publisherId: '', + tagUrl: '' + }, + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '' + }, + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false + }, + // YouTube plugin + youtube: { + noCookie: false, + // Whether to use an alternative version of YouTube without cookies + rel: 0, + // No related vids + showinfo: 0, + // Hide info + iv_load_policy: 3, + // Hide annotations + modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) + + } +}; + +// ========================================================================== +// Plyr states +// ========================================================================== +var pip = { + active: 'picture-in-picture', + inactive: 'inline' +}; + +// ========================================================================== +// Plyr supported types and providers +// ========================================================================== +var providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo' +}; +var types = { + audio: 'audio', + video: 'video' +}; +/** + * Get provider by URL + * @param {String} url + */ + +function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } // Vimeo + + + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; + } + + return null; +} + +// ========================================================================== +// Console wrapper +// ========================================================================== +var noop = function noop() {}; + +var Console = +/*#__PURE__*/ +function () { + function Console() { + var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + _classCallCheck(this, Console); + + this.enabled = window.console && enabled; + + if (this.enabled) { + this.log('Debugging enabled'); + } + } + + _createClass(Console, [{ + key: "log", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + }, { + key: "warn", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + }, { + key: "error", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } + }]); + + return Console; +}(); + +function onChange() { + if (!this.enabled) { + return; + } // Update toggle button + + + var button = this.player.elements.buttons.fullscreen; + + if (is.element(button)) { + button.pressed = this.active; + } // Trigger an event + + + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container + + if (!browser.isIos) { + trapFocus.call(this.player, this.target, this.active); + } +} + +function toggleFallback() { + var _this = this; + + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + // Store or restore scroll position + if (toggle) { + this.scrollPosition = { + x: window.scrollX || 0, + y: window.scrollY || 0 + }; + } else { + window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + } // Toggle scroll + + + document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook + + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+ + + if (browser.isIos) { + var viewport = document.head.querySelector('meta[name="viewport"]'); + var property = 'viewport-fit=cover'; // Inject the viewport meta if required + + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } // Check if the property already exists + + + var hasProperty = is.string(viewport.content) && viewport.content.includes(property); + + if (toggle) { + this.cleanupViewport = !hasProperty; + + if (!hasProperty) { + viewport.content += ",".concat(property); + } + } else if (this.cleanupViewport) { + viewport.content = viewport.content.split(',').filter(function (part) { + return part.trim() !== property; + }).join(','); + } // Force a repaint as sometimes Safari doesn't want to fill the screen + + + setTimeout(function () { + return repaint(_this.target); + }, 100); + } // Toggle button and fire events + + + onChange.call(this); +} + +var Fullscreen = +/*#__PURE__*/ +function () { + function Fullscreen(player) { + var _this2 = this; + + _classCallCheck(this, Fullscreen); + + // Keep reference to parent + this.player = player; // Get prefix + + this.prefix = Fullscreen.prefix; + this.property = Fullscreen.property; // Scroll position + + this.scrollPosition = { + x: 0, + y: 0 + }; // Force the use of 'full window/browser' rather than fullscreen + + this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners + // Handle event (incase user presses escape etc) + + on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { + // TODO: Filter for target?? + onChange.call(_this2); + }); // Fullscreen toggle on double click + + on.call(this.player, this.player.elements.container, 'dblclick', function (event) { + // Ignore double click in controls + if (is.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) { + return; + } + + _this2.toggle(); + }); // Update the UI + + this.update(); + } // Determine if native supported + + + _createClass(Fullscreen, [{ + key: "update", + // Update UI + value: function update() { + if (this.enabled) { + var mode; + + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } + + this.player.debug.log("".concat(mode, " fullscreen enabled")); + } else { + this.player.debug.log('Fullscreen not supported and fallback disabled'); + } // Add styling hook to show button + + + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + } // Make an element fullscreen + + }, { + key: "enter", + value: function enter() { + if (!this.enabled) { + return; + } // iOS native fullscreen doesn't need the request step + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, true); + } else if (!this.prefix) { + this.target.requestFullscreen(); + } else if (!is.empty(this.prefix)) { + this.target["".concat(this.prefix, "Request").concat(this.property)](); + } + } // Bail from fullscreen + + }, { + key: "exit", + value: function exit() { + if (!this.enabled) { + return; + } // iOS native fullscreen + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitExitFullscreen(); + this.player.play(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, false); + } else if (!this.prefix) { + (document.cancelFullScreen || document.exitFullscreen).call(document); + } else if (!is.empty(this.prefix)) { + var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; + document["".concat(this.prefix).concat(action).concat(this.property)](); + } + } // Toggle state + + }, { + key: "toggle", + value: function toggle() { + if (!this.active) { + this.enter(); + } else { + this.exit(); + } + } + }, { + key: "usingNative", + // If we're actually using native + get: function get() { + return Fullscreen.native && !this.forceFallback; + } // Get the prefix for handlers + + }, { + key: "enabled", + // Determine if fullscreen is enabled + get: function get() { + return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + } // Get active state + + }, { + key: "active", + get: function get() { + if (!this.enabled) { + return false; + } // Fallback using classname + + + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + } + + var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; + return element === this.target; + } // Get target element + + }, { + key: "target", + get: function get() { + return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + } + }], [{ + key: "native", + get: function get() { + return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + } + }, { + key: "prefix", + get: function get() { + // No prefix + if (is.function(document.exitFullscreen)) { + return ''; + } // Check for fullscreen support by vendor prefix + + + var value = ''; + var prefixes = ['webkit', 'moz', 'ms']; + prefixes.some(function (pre) { + if (is.function(document["".concat(pre, "ExitFullscreen")]) || is.function(document["".concat(pre, "CancelFullScreen")])) { + value = pre; + return true; + } + + return false; + }); + return value; + } + }, { + key: "property", + get: function get() { + return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + } + }]); + + return Fullscreen; +}(); + +// ========================================================================== +// Load image avoiding xhr/fetch CORS issues +// Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded +// By default it checks if it is at least 1px, but you can add a second argument to change this +// ========================================================================== +function loadImage(src) { + var minWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return new Promise(function (resolve, reject) { + var image = new Image(); + + var handler = function handler() { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { + onload: handler, + onerror: handler, + src: src + }); + }); +} + +// ========================================================================== +var ui = { + addStyleHook: function addStyleHook() { + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + }, + // Toggle native HTML5 media controls + toggleNativeControls: function toggleNativeControls() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + // Setup the UI + build: function build() { + var _this = this; + + // Re-attach media element listeners + // TODO: Use event bubbling? + this.listeners.media(); // Don't setup interface if no support + + if (!this.supported.ui) { + this.debug.warn("Basic support only for ".concat(this.provider, " ").concat(this.type)); // Restore native controls + + ui.toggleNativeControls.call(this, true); // Bail + + return; + } // Inject custom controls if not present + + + if (!is.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); // Re-attach control listeners + + this.listeners.controls(); + } // Remove native controls + + + ui.toggleNativeControls.call(this); // Setup captions for HTML5 + + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume + + + this.volume = null; // Reset mute state + + this.muted = null; // Reset speed + + this.speed = null; // Reset loop state + + this.loop = null; // Reset quality setting + + this.quality = null; // Reset volume display + + controls.updateVolume.call(this); // Reset time display + + controls.timeUpdate.call(this); // Update the UI + + ui.checkPlaying.call(this); // Check for picture-in-picture support + + toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support + + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class + + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class + + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls + + this.ready = true; // Ready event at end of execution stack + + setTimeout(function () { + triggerEvent.call(_this, _this.media, 'ready'); + }, 0); // Set the title + + ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created + + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(function () {}); + } // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + + + if (this.config.duration) { + controls.durationUpdate.call(this); + } + }, + // Setup aria attribute for play and iframe title + setTitle: function setTitle() { + // Find the current text + var label = i18n.get('play', this.config); // If there's a media title set, use that for the label + + if (is.string(this.config.title) && !is.empty(this.config.title)) { + label += ", ".concat(this.config.title); + } // If there's a play button, set label + + + Array.from(this.elements.buttons.play || []).forEach(function (button) { + button.setAttribute('aria-label', label); + }); // Set iframe title + // https://github.com/sampotts/plyr/issues/124 + + if (this.isEmbed) { + var iframe = getElement.call(this, 'iframe'); + + if (!is.element(iframe)) { + return; + } // Default to media type + + + var title = !is.empty(this.config.title) ? this.config.title : 'video'; + var format = i18n.get('frameTitle', this.config); + iframe.setAttribute('title', format.replace('{title}', title)); + } + }, + // Toggle poster + togglePoster: function togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster: function setPoster(poster) { + var _this2 = this; + + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); + } // Set property synchronously to respect the call order + + + this.media.setAttribute('poster', poster); // Wait until ui is ready + + return ready.call(this) // Load image + .then(function () { + return loadImage(poster); + }).catch(function (err) { + // Hide poster on error unless it's been set by another call + if (poster === _this2.poster) { + ui.togglePoster.call(_this2, false); + } // Rethrow + + + throw err; + }).then(function () { + // Prevent race conditions + if (poster !== _this2.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }).then(function () { + Object.assign(_this2.elements.poster.style, { + backgroundImage: "url('".concat(poster, "')"), + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '' + }); + ui.togglePoster.call(_this2, true); + return poster; + }); + }, + // Check playing state + checkPlaying: function checkPlaying(event) { + var _this3 = this; + + // Class hooks + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state + + Array.from(this.elements.buttons.play || []).forEach(function (target) { + target.pressed = _this3.playing; + }); // Only update controls on non timeupdate events + + if (is.event(event) && event.type === 'timeupdate') { + return; + } // Toggle controls + + + ui.toggleControls.call(this); + }, + // Check if media is loading + checkLoading: function checkLoading(event) { + var _this4 = this; + + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer + + clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking + + this.timers.loading = setTimeout(function () { + // Update progress bar loading class state + toggleClass(_this4.elements.container, _this4.config.classNames.loading, _this4.loading); // Update controls visibility + + ui.toggleControls.call(_this4); + }, this.loading ? 250 : 0); + }, + // Toggle controls based on state and `force` argument + toggleControls: function toggleControls(force) { + var controls$$1 = this.elements.controls; + + if (controls$$1 && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide + + this.toggleControls(Boolean(force || this.loading || this.paused || controls$$1.pressed || controls$$1.hover || recentTouchSeek)); + } + } +}; + +/* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; +} */ +// Set aspect ratio for responsive container + +function setAspectRatio(input) { + var ratio = input; + + if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { + ratio = this.embed.ratio; + } + + if (!is.string(ratio)) { + ratio = this.config.ratio; + } + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + x = _ratio$split$map2[0], + y = _ratio$split$map2[1]; + + var padding = 100 / x * y; + this.elements.wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI + + if (this.isVimeo && this.supported.ui) { + var height = 240; + var offset = (height - padding) / (height / 50); + this.media.style.transform = "translateY(-".concat(offset, "%)"); + } + + return { + padding: padding, + ratio: ratio + }; +} + +var Listeners = +/*#__PURE__*/ +function () { + function Listeners(player) { + _classCallCheck(this, Listeners); + + this.player = player; + this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; + this.handleKey = this.handleKey.bind(this); + this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); + this.firstTouch = this.firstTouch.bind(this); + } // Handle key presses + + + _createClass(Listeners, [{ + key: "handleKey", + value: function handleKey(event) { + var player = this.player; + var elements = player.elements; + var code = event.keyCode ? event.keyCode : event.which; + var pressed = event.type === 'keydown'; + var repeat = pressed && code === this.lastKey; // Bail if a modifier key is set + + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason + + + if (!is.number(code)) { + return; + } // Seek by the number keys + + + var seekByKey = function seekByKey() { + // Divide the max duration into 10th's and times by the number value + player.currentTime = player.duration / 10 * (code - 48); + }; // Handle the key on keydown + // Reset on keyup + + + if (pressed) { + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + var focused = document.activeElement; + + if (is.element(focused)) { + var editable = player.config.selectors.editable; + var seek = elements.inputs.seek; + + if (focused !== seek && matches(focused, editable)) { + return; + } + + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } + } // Which keycodes should we prevent default + + + var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows) + + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } + + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + player.togglePlay(); + } + + break; + + case 38: + // Arrow up + player.increaseVolume(0.1); + break; + + case 40: + // Arrow down + player.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + player.muted = !player.muted; + } + + break; + + case 39: + // Arrow forward + player.forward(); + break; + + case 37: + // Arrow back + player.rewind(); + break; + + case 70: + // F key + player.fullscreen.toggle(); + break; + + case 67: + // C key + if (!repeat) { + player.toggleCaptions(); + } + + break; + + case 76: + // L key + player.loop = !player.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ + + default: + break; + } // Escape is handle natively when in full screen + // So we only need to worry about non native + + + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); + } // Store last code for next cycle + + + this.lastKey = code; + } else { + this.lastKey = null; + } + } // Toggle menu + + }, { + key: "toggleMenu", + value: function toggleMenu(event) { + controls.toggleMenu.call(this.player, event); + } // Device is touch enabled + + }, { + key: "firstTouch", + value: function firstTouch() { + var player = this.player; + var elements = player.elements; + player.touch = true; // Add touch class + + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + }, { + key: "setTabFocus", + value: function setTabFocus(event) { + var player = this.player; + var elements = player.elements; + clearTimeout(this.focusTimer); // Ignore any key other than tab + + if (event.type === 'keydown' && event.which !== 9) { + return; + } // Store reference to event timeStamp + + + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } // Remove current classes + + + var removeCurrent = function removeCurrent() { + var className = player.config.classNames.tabFocus; + var current = getElements.call(player, ".".concat(className)); + toggleClass(current, className, false); + }; // Determine if a key was pressed to trigger this event + + + var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior + + if (event.type === 'focus' && !wasKeyDown) { + return; + } // Remove all current + + + removeCurrent(); // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + + this.focusTimer = setTimeout(function () { + var focused = document.activeElement; // Ignore if current focus element isn't inside the player + + if (!elements.container.contains(focused)) { + return; + } + + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); + } // Global window & document listeners + + }, { + key: "global", + value: function global() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var player = this.player; // Keyboard shortcuts + + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); + } // Click anywhere closes menu + + + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events + + once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection + + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); + } // Container listeners + + }, { + key: "container", + value: function container() { + var player = this.player; + var config = player.config, + elements = player.elements, + timers = player.timers; // Keyboard shortcuts + + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); + } // Toggle controls on mouse events and entering fullscreen + + + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen + + if (controls$$1 && event.type === 'enterfullscreen') { + controls$$1.pressed = false; + controls$$1.hover = false; + } // Show, then hide after a timeout unless another control event occurs + + + var show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + var delay = 0; + + if (show) { + ui.toggleControls.call(player, true); // Use longer timeout for touch devices + + delay = player.touch ? 3000 : 2000; + } // Clear timer + + + clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen + + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); + }); + } */ + // Set a gutter for Vimeo + + var setGutter = function setGutter(ratio, padding, toggle) { + if (!player.isVimeo) { + return; + } + + var target = player.elements.wrapper.firstChild; + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + height = _ratio$split$map2[1]; + + var _player$embed$ratio$s = player.embed.ratio.split(':').map(Number), + _player$embed$ratio$s2 = _slicedToArray(_player$embed$ratio$s, 2), + videoWidth = _player$embed$ratio$s2[0], + videoHeight = _player$embed$ratio$s2[1]; + + target.style.maxWidth = toggle ? "".concat(height / videoHeight * videoWidth, "px") : null; + target.style.margin = toggle ? '0 auto' : null; + }; // Resize on fullscreen change + + + var setPlayerSize = function setPlayerSize(measure) { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } + + var rect = elements.container.getBoundingClientRect(); + var width = rect.width, + height = rect.height; + return setAspectRatio.call(player, "".concat(width, ":").concat(height)); + }; + + var resized = function resized() { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; + + on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) { + var _player$fullscreen = player.fullscreen, + target = _player$fullscreen.target, + usingNative = _player$fullscreen.usingNative; // Ignore for iOS native + + if (!player.isEmbed || target !== elements.container) { + return; + } + + var isEnter = event.type === 'enterfullscreen'; // Set the player size when entering fullscreen to viewport size + + var _setPlayerSize = setPlayerSize(isEnter), + padding = _setPlayerSize.padding, + ratio = _setPlayerSize.ratio; // Set Vimeo gutter + + + setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport + + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); + } + } + }); + } // Listen for media events + + }, { + key: "media", + value: function media() { + var _this = this; + + var player = this.player; + var elements = player.elements; // Time change on media + + on.call(player, player.media, 'timeupdate seeking seeked', function (event) { + return controls.timeUpdate.call(player, event); + }); // Display duration + + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) { + return controls.durationUpdate.call(player, event); + }); // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point + + on.call(player, player.media, 'canplay loadeddata', function () { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); + }); // Handle the media finishing + + on.call(player, player.media, 'ended', function () { + // Show poster on end + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { + // Restart + player.restart(); + } + }); // Check for buffer progress + + on.call(player, player.media, 'progress playing seeking seeked', function (event) { + return controls.updateProgress.call(player, event); + }); // Handle volume changes + + on.call(player, player.media, 'volumechange', function (event) { + return controls.updateVolume.call(player, event); + }); // Handle play/pause + + on.call(player, player.media, 'playing play pause ended emptied timeupdate', function (event) { + return ui.checkPlaying.call(player, event); + }); // Loading state + + on.call(player, player.media, 'waiting canplay seeked playing', function (event) { + return ui.checkLoading.call(player, event); + }); // If autoplay, then load advertisement if required + // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows + + on.call(player, player.media, 'playing', function () { + if (!player.ads) { + return; + } // If ads are enabled, wait for them first + + + if (player.ads.enabled && !player.ads.initialized) { + // Wait for manager response + player.ads.managerPromise.then(function () { + return player.ads.play(); + }).catch(function () { + return player.play(); + }); + } + }); // Click video + + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { + // Re-fetch the wrapper + var wrapper = getElement.call(player, ".".concat(player.config.classNames.video)); // Bail if there's no wrapper (this should never happen) + + if (!is.element(wrapper)) { + return; + } // On click play, pause or restart + + + on.call(player, elements.container, 'click', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper + + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } // Touch devices will just show controls (if hidden) + + + if (player.touch && player.config.hideControls) { + return; + } + + if (player.ended) { + _this.proxy(event, player.restart, 'restart'); + + _this.proxy(event, player.play, 'play'); + } else { + _this.proxy(event, player.togglePlay, 'play'); + } + }); + } // Disable right click + + + if (player.supported.ui && player.config.disableContextMenu) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { + event.preventDefault(); + }, false); + } // Volume change + + + on.call(player, player.media, 'volumechange', function () { + // Save to storage + player.storage.set({ + volume: player.volume, + muted: player.muted + }); + }); // Speed change + + on.call(player, player.media, 'ratechange', function () { + // Update UI + controls.updateSetting.call(player, 'speed'); // Save to storage + + + player.storage.set({ + speed: player.speed + }); + }); // Quality change + + on.call(player, player.media, 'qualitychange', function (event) { + // Update UI + controls.updateSetting.call(player, 'quality', null, event.detail.quality); + }); // Update download link when ready and if quality changes + + on.call(player, player.media, 'ready qualitychange', function () { + controls.setDownloadLink.call(player); + }); // Proxy events to container + // Bubble up key events for Edge + + var proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + on.call(player, player.media, proxyEvents, function (event) { + var _event$detail = event.detail, + detail = _event$detail === void 0 ? {} : _event$detail; // Get error details from media + + if (event.type === 'error') { + detail = player.media.error; + } + + triggerEvent.call(player, elements.container, event.type, true, detail); + }); + } // Run default and custom handlers + + }, { + key: "proxy", + value: function proxy(event, defaultHandler, customHandlerKey) { + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + var returned = true; // Execute custom handler + + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } // Only call default handler if not prevented in custom handler + + + if (returned && is.function(defaultHandler)) { + defaultHandler.call(player, event); + } + } // Trigger custom and default handlers + + }, { + key: "bind", + value: function bind(element, type, defaultHandler, customHandlerKey) { + var _this2 = this; + + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is.function(customHandler); + on.call(player, element, type, function (event) { + return _this2.proxy(event, defaultHandler, customHandlerKey); + }, passive && !hasCustomHandler); + } // Listen for control events + + }, { + key: "controls", + value: function controls$$1() { + var _this3 = this; + + var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change + + var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle + + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { + _this3.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause + + + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind + + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind + + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle + + this.bind(elements.buttons.mute, 'click', function () { + player.muted = !player.muted; + }, 'mute'); // Captions toggle + + this.bind(elements.buttons.captions, 'click', function () { + return player.toggleCaptions(); + }); // Download + + this.bind(elements.buttons.download, 'click', function () { + triggerEvent.call(player, player.media, 'download'); + }, 'download'); // Fullscreen toggle + + this.bind(elements.buttons.fullscreen, 'click', function () { + player.fullscreen.toggle(); + }, 'fullscreen'); // Picture-in-Picture + + this.bind(elements.buttons.pip, 'click', function () { + player.pip = 'toggle'; + }, 'pip'); // Airplay + + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle + + this.bind(elements.buttons.settings, 'click', function (event) { + // Prevent the document click listener closing the menu + event.stopPropagation(); + + controls.toggleMenu.call(player, event); + }); // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + + this.bind(elements.buttons.settings, 'keyup', function (event) { + var code = event.which; // We only care about space and return + + if (![13, 32].includes(code)) { + return; + } // Because return triggers a click anyway, all we need to do is set focus + + + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); + + return; + } // Prevent scroll + + + event.preventDefault(); // Prevent playing video (Firefox) + + event.stopPropagation(); // Toggle menu + + controls.toggleMenu.call(player, event); + }, null, false // Can't be passive as we're preventing default + ); // Escape closes menu + + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); // Set range input alternative "value", which matches the tooltip time (#954) + + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); + var percent = 100 / rect.width * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); // Pause while seeking + + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var attribute = 'play-on-seeked'; + + if (is.keyboardEvent(event) && code !== 39 && code !== 37) { + return; + } // Record seek time so we can prevent hiding controls for a few seconds after seek + + + player.lastSeekTime = Date.now(); // Was playing before? + + var play = seek.hasAttribute(attribute); // Done seeking + + var done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback + + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); + } + }); // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + + if (browser.isIos) { + var inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(function (input) { + return _this3.bind(input, inputEvent, function (event) { + return repaint(event.target); + }); + }); + } // Seek + + + this.bind(elements.inputs.seek, inputEvent, function (event) { + var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) + + var seekTo = seek.getAttribute('seek-value'); + + if (is.empty(seekTo)) { + seekTo = seek.value; + } + + seek.removeAttribute('seek-value'); + player.currentTime = seekTo / seek.max * player.duration; + }, 'seek'); // Seek tooltip + + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this + + this.bind(elements.progress, 'mousemove touchmove', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + + this.bind(elements.progress, 'mouseleave click', function () { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); // Show scrubbing preview + + this.bind(elements.progress, 'mousedown touchstart', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } + }); + this.bind(elements.progress, 'mouseup touchend', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); // Polyfill for lower fill in <input type="range"> for webkit + + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this3.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); + }); + }); + } // Current time invert + // Only if one time element is used for both currentTime and duration + + + if (player.config.toggleInvert && !is.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { + // Do nothing if we're at the start + if (player.currentTime === 0) { + return; + } + + player.config.invertTime = !player.config.invertTime; + + controls.timeUpdate.call(player); + }); + } // Volume + + + this.bind(elements.inputs.volume, inputEvent, function (event) { + player.volume = event.target.value; + }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); // Show controls when they receive focus (e.g., when using keyboard tab key) + + this.bind(elements.controls, 'focusin', function () { + var config = player.config, + elements = player.elements, + timers = player.timers; // Skip transition to prevent focus from scrolling the parent element + + toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle + + ui.toggleControls.call(player, true); // Restore transition + + setTimeout(function () { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); // Delay a little more for mouse users + + var delay = _this3.touch ? 3000 : 4000; // Clear timer + + clearTimeout(timers.controls); // Hide again after delay + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Mouse wheel for volume + + this.bind(elements.inputs.volume, 'wheel', function (event) { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + var inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true + + var _map = [event.deltaX, -event.deltaY].map(function (value) { + return inverted ? -value : value; + }), + _map2 = _slicedToArray(_map, 2), + x = _map2[0], + y = _map2[1]; // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) + + + var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2% + + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min + + var volume = player.media.volume; + + if (direction === 1 && volume < 1 || direction === -1 && volume > 0) { + event.preventDefault(); + } + }, 'volume', false); + } + }]); + + return Listeners; +}(); + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var loadjs_umd = createCommonjsModule(function (module, exports) { +(function(root, factory) { + { + module.exports = factory(); + } +}(commonjsGlobal, function() { +/** + * Global dependencies. + * @global {Object} document - DOM + */ + +var devnull = function() {}, + bundleIdCache = {}, + bundleResultCache = {}, + bundleCallbackQueue = {}; + + +/** + * Subscribe to bundle load event. + * @param {string[]} bundleIds - Bundle ids + * @param {Function} callbackFn - The callback function + */ +function subscribe(bundleIds, callbackFn) { + // listify + bundleIds = bundleIds.push ? bundleIds : [bundleIds]; + + var depsNotFound = [], + i = bundleIds.length, + numWaiting = i, + fn, + bundleId, + r, + q; + + // define callback function + fn = function (bundleId, pathsNotFound) { + if (pathsNotFound.length) depsNotFound.push(bundleId); + + numWaiting--; + if (!numWaiting) callbackFn(depsNotFound); + }; + + // register callback + while (i--) { + bundleId = bundleIds[i]; + + // execute callback if in result cache + r = bundleResultCache[bundleId]; + if (r) { + fn(bundleId, r); + continue; + } + + // add to callback queue + q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; + q.push(fn); + } +} + + +/** + * Publish bundle load event. + * @param {string} bundleId - Bundle id + * @param {string[]} pathsNotFound - List of files not found + */ +function publish(bundleId, pathsNotFound) { + // exit if id isn't defined + if (!bundleId) return; + + var q = bundleCallbackQueue[bundleId]; + + // cache result + bundleResultCache[bundleId] = pathsNotFound; + + // exit if queue is empty + if (!q) return; + + // empty callback queue + while (q.length) { + q[0](bundleId, pathsNotFound); + q.splice(0, 1); + } +} + + +/** + * Execute callbacks. + * @param {Object or Function} args - The callback args + * @param {string[]} depsNotFound - List of dependencies not found + */ +function executeCallbacks(args, depsNotFound) { + // accept function as argument + if (args.call) args = {success: args}; + + // success and error callbacks + if (depsNotFound.length) (args.error || devnull)(depsNotFound); + else (args.success || devnull)(args); +} + + +/** + * Load individual file. + * @param {string} path - The file path + * @param {Function} callbackFn - The callback function + */ +function loadFile(path, callbackFn, args, numTries) { + var doc = document, + async = args.async, + maxTries = (args.numRetries || 0) + 1, + beforeCallbackFn = args.before || devnull, + pathStripped = path.replace(/^(css|img)!/, ''), + isCss, + e; + + numTries = numTries || 0; + + if (/(^css!|\.css$)/.test(path)) { + isCss = true; + + // css + e = doc.createElement('link'); + e.rel = 'stylesheet'; + e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix + } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { + // image + e = doc.createElement('img'); + e.src = pathStripped; + } else { + // javascript + e = doc.createElement('script'); + e.src = path; + e.async = async === undefined ? true : async; + } + + e.onload = e.onerror = e.onbeforeload = function (ev) { + var result = ev.type[0]; + + // Note: The following code isolates IE using `hideFocus` and treats empty + // stylesheets as failures to get around lack of onerror support + if (isCss && 'hideFocus' in e) { + try { + if (!e.sheet.cssText.length) result = 'e'; + } catch (x) { + // sheets objects created from load errors don't allow access to + // `cssText` (unless error is Code:18 SecurityError) + if (x.code != 18) result = 'e'; + } + } + + // handle retries in case of load failure + if (result == 'e') { + // increment counter + numTries += 1; + + // exit function and try again + if (numTries < maxTries) { + return loadFile(path, callbackFn, args, numTries); + } + } + + // execute callback + callbackFn(path, result, ev.defaultPrevented); + }; + + // add to document (unless callback returns `false`) + if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); +} + + +/** + * Load multiple files. + * @param {string[]} paths - The file paths + * @param {Function} callbackFn - The callback function + */ +function loadFiles(paths, callbackFn, args) { + // listify paths + paths = paths.push ? paths : [paths]; + + var numWaiting = paths.length, + x = numWaiting, + pathsNotFound = [], + fn, + i; + + // define callback function + fn = function(path, result, defaultPrevented) { + // handle error + if (result == 'e') pathsNotFound.push(path); + + // handle beforeload event. If defaultPrevented then that means the load + // will be blocked (ex. Ghostery/ABP on Safari) + if (result == 'b') { + if (defaultPrevented) pathsNotFound.push(path); + else return; + } + + numWaiting--; + if (!numWaiting) callbackFn(pathsNotFound); + }; + + // load scripts + for (i=0; i < x; i++) loadFile(paths[i], fn, args); +} + + +/** + * Initiate script load and register bundle. + * @param {(string|string[])} paths - The file paths + * @param {(string|Function)} [arg1] - The bundleId or success callback + * @param {Function} [arg2] - The success or error callback + * @param {Function} [arg3] - The error callback + */ +function loadjs(paths, arg1, arg2) { + var bundleId, + args; + + // bundleId (if string) + if (arg1 && arg1.trim) bundleId = arg1; + + // args (default is {}) + args = (bundleId ? arg2 : arg1) || {}; + + // throw error if bundle is already defined + if (bundleId) { + if (bundleId in bundleIdCache) { + throw "LoadJS"; + } else { + bundleIdCache[bundleId] = true; + } + } + + // load scripts + loadFiles(paths, function (pathsNotFound) { + // execute callbacks + executeCallbacks(args, pathsNotFound); + + // publish bundle load event + publish(bundleId, pathsNotFound); + }, args); +} + + +/** + * Execute callbacks when dependencies have been satisfied. + * @param {(string|string[])} deps - List of bundle ids + * @param {Object} args - success/error arguments + */ +loadjs.ready = function ready(deps, args) { + // subscribe to bundle load event + subscribe(deps, function (depsNotFound) { + // execute callbacks + executeCallbacks(args, depsNotFound); + }); + + return loadjs; +}; + + +/** + * Manually satisfy bundle dependencies. + * @param {string} bundleId - The bundle id + */ +loadjs.done = function done(bundleId) { + publish(bundleId, []); +}; + + +/** + * Reset loadjs dependencies statuses + */ +loadjs.reset = function reset() { + bundleIdCache = {}; + bundleResultCache = {}; + bundleCallbackQueue = {}; +}; + + +/** + * Determine if bundle has already been defined + * @param String} bundleId - The bundle id + */ +loadjs.isDefined = function isDefined(bundleId) { + return bundleId in bundleIdCache; +}; + + +// export +return loadjs; + +})); +}); + +// ========================================================================== +function loadScript(url) { + return new Promise(function (resolve, reject) { + loadjs_umd(url, { + success: resolve, + error: reject + }); + }); +} + +function parseId(url) { + if (is.empty(url)) { + return null; + } + + if (is.number(Number(url))) { + return url; + } + + var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; +} // Set playback state and trigger change (only on actual change) + + +function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } +} + +var vimeo = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio + + setAspectRatio.call(this); // Load the API if not already + + if (!is.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk).then(function () { + vimeo.ready.call(_this); + }).catch(function (error) { + _this.debug.warn('Vimeo API failed to load', error); + }); + } else { + vimeo.ready.call(this); + } + }, + // API Ready + ready: function ready$$1() { + var _this2 = this; + + var player = this; + var config = player.config.vimeo; // Get Vimeo params for the iframe + + var params = buildUrlParams(extend({}, { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative + }, config)); // Get the source URL or ID + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is.empty(source)) { + source = player.media.getAttribute(player.config.attributes.embed.id); + } + + var id = parseId(source); // Build an iframe + + var iframe = createElement('iframe'); + var src = format(player.config.urls.vimeo.iframe, id, params); + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + iframe.setAttribute('allowtransparency', ''); + iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set + + var poster = player.poster; // Inject the package + + var wrapper = createElement('div', { + poster: poster, + class: player.config.classNames.embedContainer + }); + wrapper.appendChild(iframe); + player.media = replaceElement(wrapper, player.media); // Get poster image + + fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { + if (is.empty(response)) { + return; + } // Get the URL for thumbnail + + + var url = new URL(response[0].thumbnail_large); // Get original image + + url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster + + ui.setPoster.call(player, url.href).catch(function () {}); + }); // Setup instance + // https://github.com/vimeo/player.js + + player.embed = new window.Vimeo.Player(iframe, { + autopause: player.config.autopause, + muted: player.muted + }); + player.media.paused = true; + player.media.currentTime = 0; // Disable native text track rendering + + if (player.supported.ui) { + player.embed.disableTextTrack(); + } // Create a faux HTML5 API using the Vimeo API + + + player.media.play = function () { + assurePlaybackState.call(player, true); + return player.embed.play(); + }; + + player.media.pause = function () { + assurePlaybackState.call(player, false); + return player.embed.pause(); + }; + + player.media.stop = function () { + player.pause(); + player.currentTime = 0; + }; // Seeking + + + var currentTime = player.media.currentTime; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return currentTime; + }, + set: function set(time) { + // Vimeo will automatically play on seek if the video hasn't been played before + // Get current paused state and volume etc + var embed = player.embed, + media = player.media, + paused = player.paused, + volume = player.volume; + var restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event + + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete + + Promise.resolve(restorePause && embed.setVolume(0)) // Seek + .then(function () { + return embed.setCurrentTime(time); + }) // Restore paused + .then(function () { + return restorePause && embed.pause(); + }) // Restore volume + .then(function () { + return restorePause && embed.setVolume(volume); + }).catch(function () {// Do nothing + }); + } + }); // Playback speed + + var speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return speed; + }, + set: function set(input) { + player.embed.setPlaybackRate(input).then(function () { + speed = input; + triggerEvent.call(player, player.media, 'ratechange'); + }).catch(function (error) { + // Hide menu item (and menu if empty) + if (error.name === 'Error') { + controls.setSpeedMenu.call(player, []); + } + }); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + player.embed.setVolume(input).then(function () { + volume = input; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : false; + player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { + muted = toggle; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Loop + + var loop = player.config.loop; + Object.defineProperty(player.media, 'loop', { + get: function get() { + return loop; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : player.config.loop.active; + player.embed.setLoop(toggle).then(function () { + loop = toggle; + }); + } + }); // Source + + var currentSrc; + player.embed.getVideoUrl().then(function (value) { + currentSrc = value; + controls.setDownloadLink.call(player); + }).catch(function (error) { + _this2.debug.warn(error); + }); + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return currentSrc; + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Set aspect ratio based on video size + + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { + var _dimensions = _slicedToArray(dimensions, 2), + width = _dimensions[0], + height = _dimensions[1]; + + player.embed.ratio = "".concat(width, ":").concat(height); + setAspectRatio.call(_this2, player.embed.ratio); + }); // Set autopause + + player.embed.setAutopause(player.config.autopause).then(function (state) { + player.config.autopause = state; + }); // Get title + + player.embed.getVideoTitle().then(function (title) { + player.config.title = title; + ui.setTitle.call(_this2); + }); // Get current time + + player.embed.getCurrentTime().then(function (value) { + currentTime = value; + triggerEvent.call(player, player.media, 'timeupdate'); + }); // Get duration + + player.embed.getDuration().then(function (value) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + }); // Get captions + + player.embed.getTextTracks().then(function (tracks) { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + player.embed.on('cuechange', function (_ref) { + var _ref$cues = _ref.cues, + cues = _ref$cues === void 0 ? [] : _ref$cues; + var strippedCues = cues.map(function (cue) { + return stripHTML(cue.text); + }); + captions.updateCues.call(player, strippedCues); + }); + player.embed.on('loaded', function () { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(function (paused) { + assurePlaybackState.call(player, !paused); + + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); + + if (is.element(player.embed.element) && player.supported.ui) { + var frame = player.embed.element; // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 + + frame.setAttribute('tabindex', -1); + } + }); + player.embed.on('play', function () { + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); + }); + player.embed.on('pause', function () { + assurePlaybackState.call(player, false); + }); + player.embed.on('timeupdate', function (data) { + player.media.seeking = false; + currentTime = data.seconds; + triggerEvent.call(player, player.media, 'timeupdate'); + }); + player.embed.on('progress', function (data) { + player.media.buffered = data.percent; + triggerEvent.call(player, player.media, 'progress'); // Check all loaded + + if (parseInt(data.percent, 10) === 1) { + triggerEvent.call(player, player.media, 'canplaythrough'); + } // Get duration as if we do it before load, it gives an incorrect value + // https://github.com/sampotts/plyr/issues/891 + + + player.embed.getDuration().then(function (value) { + if (value !== player.media.duration) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + } + }); + }); + player.embed.on('seeked', function () { + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + }); + player.embed.on('ended', function () { + player.media.paused = true; + triggerEvent.call(player, player.media, 'ended'); + }); + player.embed.on('error', function (detail) { + player.media.error = detail; + triggerEvent.call(player, player.media, 'error'); + }); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 0); + } +}; + +// ========================================================================== + +function parseId$1(url) { + if (is.empty(url)) { + return null; + } + + var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; +} // Set playback state and trigger change (only on actual change) + + +function assurePlaybackState$1(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } +} + +var youtube = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio + + setAspectRatio.call(this); // Setup API + + if (is.object(window.YT) && is.function(window.YT.Player)) { + youtube.ready.call(this); + } else { + // Load the API + loadScript(this.config.urls.youtube.sdk).catch(function (error) { + _this.debug.warn('YouTube API failed to load', error); + }); // Setup callback for the API + // YouTube has it's own system of course... + + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue + + window.onYouTubeReadyCallbacks.push(function () { + youtube.ready.call(_this); + }); // Set callback to process queue + + window.onYouTubeIframeAPIReady = function () { + window.onYouTubeReadyCallbacks.forEach(function (callback) { + callback(); + }); + }; + } + }, + // Get the media title + getTitle: function getTitle(videoId) { + var _this2 = this; + + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (is.function(this.embed.getVideoData)) { + var _this$embed$getVideoD = this.embed.getVideoData(), + title = _this$embed$getVideoD.title; + + if (is.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; + } + } // Or via Google API + + + var key = this.config.keys.google; + + if (is.string(key) && !is.empty(key)) { + var url = format(this.config.urls.youtube.api, videoId, key); + fetch(url).then(function (result) { + if (is.object(result)) { + _this2.config.title = result.items[0].snippet.title; + ui.setTitle.call(_this2); + } + }).catch(function () {}); + } + }, + // API ready + ready: function ready$$1() { + var player = this; // Ignore already setup (race condition) + + var currentId = player.media.getAttribute('id'); + + if (!is.empty(currentId) && currentId.startsWith('youtube-')) { + return; + } // Get the source URL or ID + + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is.empty(source)) { + source = player.media.getAttribute(this.config.attributes.embed.id); + } // Replace the <iframe> with a <div> due to YouTube API issues + + + var videoId = parseId$1(source); + var id = generateId(player.provider); // Get poster, if already set + + var poster = player.poster; // Replace media element + + var container = createElement('div', { + id: id, + poster: poster + }); + player.media = replaceElement(container, player.media); // Id to poster wrapper + + var posterSrc = function posterSrc(format$$1) { + return "https://img.youtube.com/vi/".concat(videoId, "/").concat(format$$1, "default.jpg"); + }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + + + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(function () { + return loadImage(posterSrc('sd'), 121); + }) // 480p padded 4:3 + .catch(function () { + return loadImage(posterSrc('hq')); + }) // 360p padded 4:3. Always exists + .then(function (image) { + return ui.setPoster.call(player, image.src); + }).then(function (posterSrc) { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }).catch(function () {}); + var config = player.config.youtube; // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + + player.embed = new window.YT.Player(id, { + videoId: videoId, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend({}, { + autoplay: player.config.autoplay ? 1 : 0, + // Autoplay + hl: player.config.hl, + // iframe interface language + controls: player.supported.ui ? 0 : 1, + // Only show controls if not fully supported + disablekb: 1, + // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, + // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null + }, config), + events: { + onError: function onError(event) { + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + var code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + + var message = { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.' + }[code] || 'An unknown error occured'; + player.media.error = { + code: code, + message: message + }; + triggerEvent.call(player, player.media, 'error'); + } + }, + onPlaybackRateChange: function onPlaybackRateChange(event) { + // Get the instance + var instance = event.target; // Get current speed + + player.media.playbackRate = instance.getPlaybackRate(); + triggerEvent.call(player, player.media, 'ratechange'); + }, + onReady: function onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is.function(player.media.play)) { + return; + } // Get the instance + + + var instance = event.target; // Get the title + + youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API + + player.media.play = function () { + assurePlaybackState$1.call(player, true); + instance.playVideo(); + }; + + player.media.pause = function () { + assurePlaybackState$1.call(player, false); + instance.pauseVideo(); + }; + + player.media.stop = function () { + instance.stopVideo(); + }; + + player.media.duration = instance.getDuration(); + player.media.paused = true; // Seeking + + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return Number(instance.getCurrentTime()); + }, + set: function set(time) { + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } // Set seeking state and trigger event + + + player.media.seeking = true; + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent + + instance.seekTo(time); + } + }); // Playback speed + + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return instance.getPlaybackRate(); + }, + set: function set(input) { + instance.setPlaybackRate(input); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + volume = input; + instance.setVolume(volume * 100); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Source + + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return instance.getVideoUrl(); + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Get available speeds + + player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe + + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } + + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer + + clearInterval(player.timers.buffering); // Setup buffering + + player.timers.buffering = setInterval(function () { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something + + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + triggerEvent.call(player, player.media, 'progress'); + } // Set last buffer point + + + player.media.lastBuffered = player.media.buffered; // Bail if we're at 100% + + if (player.media.buffered === 1) { + clearInterval(player.timers.buffering); // Trigger event + + triggerEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 50); + }, + onStateChange: function onStateChange(event) { + // Get the instance + var instance = event.target; // Reset timer + + clearInterval(player.timers.playing); + var seeked = player.media.seeking && [1, 2].includes(event.data); + + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued + + + switch (event.data) { + case -1: + // Update scrubber + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube + + player.media.buffered = instance.getVideoLoadedFraction(); + triggerEvent.call(player, player.media, 'progress'); + break; + + case 0: + assurePlaybackState$1.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. + + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + triggerEvent.call(player, player.media, 'ended'); + } + + break; + + case 1: + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState$1.call(player, true); + triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress + + player.timers.playing = setInterval(function () { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + triggerEvent.call(player, player.media, 'durationchange'); + } + } + + break; + + case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } + + assurePlaybackState$1.call(player, false); + break; + + default: + break; + } + + triggerEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data + }); + } + } + }); + } +}; + +// ========================================================================== +var media = { + // Setup media + setup: function setup() { + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } // Add type class + + + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class + + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds + // This will require changes if audio embeds are added + + if (this.isEmbed) { + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } // Inject the player wrapper + + + if (this.isVideo) { + // Create the wrapper div + this.elements.wrapper = createElement('div', { + class: this.config.classNames.video + }); // Wrap the video in a container + + wrap(this.media, this.elements.wrapper); // Faux poster container + + this.elements.poster = createElement('div', { + class: this.config.classNames.poster + }); + this.elements.wrapper.appendChild(this.elements.poster); + } + + if (this.isHTML5) { + html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); + } + } +}; + +var Ads = +/*#__PURE__*/ +function () { + /** + * Ads constructor. + * @param {object} player + * @return {Ads} + */ + function Ads(player) { + var _this = this; + + _classCallCheck(this, Ads); + + this.player = player; + this.config = player.config.ads; + this.playing = false; + this.initialized = false; + this.elements = { + container: null, + displayContainer: null + }; + this.manager = null; + this.loader = null; + this.cuePoints = null; + this.events = {}; + this.safetyTimer = null; + this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready + + this.managerPromise = new Promise(function (resolve, reject) { + // The ad is loaded and ready + _this.on('loaded', resolve); // Ads failed + + + _this.on('error', reject); + }); + this.load(); + } + + _createClass(Ads, [{ + key: "load", + + /** + * Load the IMA SDK + */ + value: function load() { + var _this2 = this; + + if (this.enabled) { + // Check if the Google IMA3 SDK is loaded or load it ourselves + if (!is.object(window.google) || !is.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); + } + } + } + /** + * Get the ads instance ready + */ + + }, { + key: "ready", + value: function ready$$1() { + var _this3 = this; + + // Start ticking our safety timer. If the whole advertisement + // thing doesn't resolve within our set time; we bail + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer + + this.managerPromise.then(function () { + _this3.clearSafetyTimer('onAdsManagerLoaded()'); + }); // Set listeners on the Plyr instance + + this.listeners(); // Setup the IMA SDK + + this.setupIMA(); + } // Build the tag URL + + }, { + key: "setupIMA", + + /** + * In order for the SDK to display ads for our video, we need to tell it where to put them, + * so here we define our ad container. This div is set up to render on top of the video player. + * Using the code below, we tell the SDK to render ads within that div. We also provide a + * handle to the content video player - the SDK will poll the current time of our player to + * properly place mid-rolls. After we create the ad display container, we initialize it. On + * mobile devices, this initialization is done as the result of a user action. + */ + value: function setupIMA() { + // Create the container for our advertisements + this.elements.container = createElement('div', { + class: this.player.config.classNames.ads + }); + this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2 + + google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language + + google.ima.settings.setLocale(this.player.config.ads.language); // We assume the adContainer is the video container of the plyr element + // that will house the ads + + this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); // Request video ads to be pre-loaded + + this.requestAds(); + } + /** + * Request advertisements + */ + + }, { + key: "requestAds", + value: function requestAds() { + var _this4 = this; + + var container = this.player.elements.container; + + try { + // Create ads loader + this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events + + this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { + return _this4.onAdsManagerLoaded(event); + }, false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this4.onAdError(error); + }, false); // Request video ads + + var request = new google.ima.AdsRequest(); + request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK + // to select the correct creative if multiple are returned + + request.linearAdSlotWidth = container.offsetWidth; + request.linearAdSlotHeight = container.offsetHeight; + request.nonLinearAdSlotWidth = container.offsetWidth; + request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video. + + request.forceNonLinearFullSlot = false; // Mute based on current state + + request.setAdWillPlayMuted(!this.player.muted); + this.loader.requestAds(request); + } catch (e) { + this.onAdError(e); + } + } + /** + * Update the ad countdown + * @param {boolean} start + */ + + }, { + key: "pollCountdown", + value: function pollCountdown() { + var _this5 = this; + + var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (!start) { + clearInterval(this.countdownTimer); + this.elements.container.removeAttribute('data-badge-text'); + return; + } + + var update = function update() { + var time = formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); + var label = "".concat(i18n.get('advertisement', _this5.player.config), " - ").concat(time); + + _this5.elements.container.setAttribute('data-badge-text', label); + }; + + this.countdownTimer = setInterval(update, 100); + } + /** + * This method is called whenever the ads are ready inside the AdDisplayContainer + * @param {Event} adsManagerLoadedEvent + */ + + }, { + key: "onAdsManagerLoaded", + value: function onAdsManagerLoaded(event) { + var _this6 = this; + + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } // Get the ads manager + + + var settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf + + settings.restoreCustomPlaybackStateOnAdBreakComplete = true; + settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration + // so it can determine when to start the mid- and post-roll + + this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll + + this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available + + if (!is.empty(this.cuePoints)) { + this.cuePoints.forEach(function (cuePoint) { + if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { + var seekElement = _this6.player.elements.progress; + + if (is.element(seekElement)) { + var cuePercentage = 100 / _this6.player.duration * cuePoint; + var cue = createElement('span', { + class: _this6.player.config.classNames.cues + }); + cue.style.left = "".concat(cuePercentage.toString(), "%"); + seekElement.appendChild(cue); + } + } + }); + } // Set volume to match player + + + this.manager.setVolume(this.player.volume); // Add listeners to the required events + // Advertisement error events + + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this6.onAdError(error); + }); // Advertisement regular events + + Object.keys(google.ima.AdEvent.Type).forEach(function (type) { + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { + return _this6.onAdEvent(event); + }); + }); // Resolve our adsManager + + this.trigger('loaded'); + } + /** + * This is where all the event handling takes place. Retrieve the ad from the event. Some + * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated + * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type + * @param {Event} event + */ + + }, { + key: "onAdEvent", + value: function onAdEvent(event) { + var _this7 = this; + + var container = this.player.elements.container; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) + // don't have ad object associated + + var ad = event.getAd(); + var adData = event.getAdData(); // Proxy event + + var dispatchEvent = function dispatchEvent(type) { + var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); + triggerEvent.call(_this7.player, _this7.player.media, event); + }; + + switch (event.type) { + case google.ima.AdEvent.Type.LOADED: + // This is the first event sent for an ad - it is possible to determine whether the + // ad is a video ad or an overlay + this.trigger('loaded'); // Bubble event + + dispatchEvent(event.type); // Start countdown + + this.pollCountdown(true); + + if (!ad.isLinear()) { + // Position AdDisplayContainer correctly for overlay + ad.width = container.offsetWidth; + ad.height = container.offsetHeight; + } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); + // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); + + + break; + + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: + // All ads for the current videos are done. We can now request new advertisements + // in case the video is re-played + // Fire event + dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // So here we load a new video when all ads are done. + // Then we load new ads within a new adsManager. When the video + // Is started - after - the ads are loaded, then we get ads. + // You can also easily test cancelling and reloading by running + // player.ads.cancel() and player.ads.play from the console I guess. + // this.player.source = { + // type: 'video', + // title: 'View From A Blue Moon', + // sources: [{ + // src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: + // 'video/mp4', }], poster: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: + // [ { kind: 'captions', label: 'English', srclang: 'en', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], + // }; + // TODO: So there is still this thing where a video should only be allowed to start + // playing when the IMA SDK is ready or has failed + + this.loadAds(); + break; + + case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: + // This event indicates the ad has started - the video player can adjust the UI, + // for example display a pause button and remaining time. Fired when content should + // be paused. This usually happens right before an ad is about to cover the content + dispatchEvent(event.type); + this.pauseContent(); + break; + + case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: + // This event indicates the ad has finished - the video player can perform + // appropriate UI actions, such as removing the timer for remaining time detection. + // Fired when content should be resumed. This usually happens when an ad finishes + // or collapses + dispatchEvent(event.type); + this.pollCountdown(); + this.resumeContent(); + break; + + case google.ima.AdEvent.Type.STARTED: + case google.ima.AdEvent.Type.MIDPOINT: + case google.ima.AdEvent.Type.COMPLETE: + case google.ima.AdEvent.Type.IMPRESSION: + case google.ima.AdEvent.Type.CLICK: + dispatchEvent(event.type); + break; + + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); + } + + break; + + default: + break; + } + } + /** + * Any ad error handling comes through here + * @param {Event} event + */ + + }, { + key: "onAdError", + value: function onAdError(event) { + this.cancel(); + this.player.debug.warn('Ads error', event); + } + /** + * Setup hooks for Plyr and window events. This ensures + * the mid- and post-roll launch at the correct time. And + * resize the advertisement when the player resizes + */ + + }, { + key: "listeners", + value: function listeners() { + var _this8 = this; + + var container = this.player.elements.container; + var time; // Add listeners to the required events + + this.player.on('ended', function () { + _this8.loader.contentComplete(); + }); + this.player.on('timeupdate', function () { + time = _this8.player.currentTime; + }); + this.player.on('seeked', function () { + var seekedTime = _this8.player.currentTime; + + if (is.empty(_this8.cuePoints)) { + return; + } + + _this8.cuePoints.forEach(function (cuePoint, index) { + if (time < cuePoint && cuePoint < seekedTime) { + _this8.manager.discardAdBreak(); + + _this8.cuePoints.splice(index, 1); + } + }); + }); // Listen to the resizing of the window. And resize ad accordingly + // TODO: eventually implement ResizeObserver + + window.addEventListener('resize', function () { + if (_this8.manager) { + _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); + } + }); + } + /** + * Initialize the adsManager and start playing advertisements + */ + + }, { + key: "play", + value: function play() { + var _this9 = this; + + var container = this.player.elements.container; + + if (!this.managerPromise) { + this.resumeContent(); + } // Play the requested advertisement whenever the adsManager is ready + + + this.managerPromise.then(function () { + // Initialize the container. Must be done via a user action on mobile devices + _this9.elements.displayContainer.initialize(); + + try { + if (!_this9.initialized) { + // Initialize the ads manager. Ad rules playlist will start at this time + _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will + // start at this time; the call will be ignored for ad rules + + + _this9.manager.start(); + } + + _this9.initialized = true; + } catch (adError) { + // An error may be thrown if there was a problem with the + // VAST response + _this9.onAdError(adError); + } + }).catch(function () {}); + } + /** + * Resume our video + */ + + }, { + key: "resumeContent", + value: function resumeContent() { + // Hide the advertisement container + this.elements.container.style.zIndex = ''; // Ad is stopped + + this.playing = false; // Play our video + + if (this.player.currentTime < this.player.duration) { + this.player.play(); + } + } + /** + * Pause our video + */ + + }, { + key: "pauseContent", + value: function pauseContent() { + // Show the advertisement container + this.elements.container.style.zIndex = 3; // Ad is playing. + + this.playing = true; // Pause our video. + + this.player.pause(); + } + /** + * Destroy the adsManager so we can grab new ads after this. If we don't then we're not + * allowed to call new ads based on google policies, as they interpret this as an accidental + * video requests. https://developers.google.com/interactive- + * media-ads/docs/sdks/android/faq#8 + */ + + }, { + key: "cancel", + value: function cancel() { + // Pause our video + if (this.initialized) { + this.resumeContent(); + } // Tell our instance that we're done for now + + + this.trigger('error'); // Re-create our adsManager + + this.loadAds(); + } + /** + * Re-create our adsManager + */ + + }, { + key: "loadAds", + value: function loadAds() { + var _this10 = this; + + // Tell our adsManager to go bye bye + this.managerPromise.then(function () { + // Destroy our adsManager + if (_this10.manager) { + _this10.manager.destroy(); + } // Re-set our adsManager promises + + + _this10.managerPromise = new Promise(function (resolve) { + _this10.on('loaded', resolve); + + _this10.player.debug.log(_this10.manager); + }); // Now request some new advertisements + + _this10.requestAds(); + }).catch(function () {}); + } + /** + * Handles callbacks after an ad event was invoked + * @param {string} event - Event type + */ + + }, { + key: "trigger", + value: function trigger(event) { + var _this11 = this; + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var handlers = this.events[event]; + + if (is.array(handlers)) { + handlers.forEach(function (handler) { + if (is.function(handler)) { + handler.apply(_this11, args); + } + }); + } + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + * @return {Ads} + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + if (!is.array(this.events[event])) { + this.events[event] = []; + } + + this.events[event].push(callback); + return this; + } + /** + * Setup a safety timer for when the ad network doesn't respond for whatever reason. + * The advertisement has 12 seconds to get its things together. We stop this timer when the + * advertisement is playing, or when a user action is required to start, then we clear the + * timer on ad ready + * @param {number} time + * @param {string} from + */ + + }, { + key: "startSafetyTimer", + value: function startSafetyTimer(time, from) { + var _this12 = this; + + this.player.debug.log("Safety timer invoked from: ".concat(from)); + this.safetyTimer = setTimeout(function () { + _this12.cancel(); + + _this12.clearSafetyTimer('startSafetyTimer()'); + }, time); + } + /** + * Clear our safety timer(s) + * @param {string} from + */ + + }, { + key: "clearSafetyTimer", + value: function clearSafetyTimer(from) { + if (!is.nullOrUndefined(this.safetyTimer)) { + this.player.debug.log("Safety timer cleared from: ".concat(from)); + clearTimeout(this.safetyTimer); + this.safetyTimer = null; + } + } + }, { + key: "enabled", + get: function get() { + var config = this.config; + return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl)); + } + }, { + key: "tagUrl", + get: function get() { + var config = this.config; + + if (is.url(config.tagUrl)) { + return config.tagUrl; + } + + var params = { + AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', + AV_CHANNELID: '5a0458dc28a06145e4519d21', + AV_URL: window.location.hostname, + cb: Date.now(), + AV_WIDTH: 640, + AV_HEIGHT: 480, + AV_CDIM2: this.publisherId + }; + var base = 'https://go.aniview.com/api/adserver6/vast/'; + return "".concat(base, "?").concat(buildUrlParams(params)); + } + }]); + + return Ads; +}(); + +var parseVtt = function parseVtt(vttDataString) { + var processedList = []; + var frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + frames.forEach(function (frame) { + var result = {}; + var lines = frame.split(/\r\n|\n|\r/); + lines.forEach(function (line) { + if (!is.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + var matchTimes = line.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = Number(matchTimes[1]) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number("0.".concat(matchTimes[4])); + result.endTime = Number(matchTimes[6]) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number("0.".concat(matchTimes[9])); + } + } else if (!is.empty(line.trim()) && is.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + var lineSplit = line.trim().split('#xywh='); + + var _lineSplit = _slicedToArray(lineSplit, 1); + + result.text = _lineSplit[0]; + + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + var _lineSplit$1$split = lineSplit[1].split(','); + + var _lineSplit$1$split2 = _slicedToArray(_lineSplit$1$split, 4); + + result.x = _lineSplit$1$split2[0]; + result.y = _lineSplit$1$split2[1]; + result.w = _lineSplit$1$split2[2]; + result.h = _lineSplit$1$split2[3]; + } + } + }); + + if (result.text) { + processedList.push(result); + } + }); + return processedList; +}; +/** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + + +var PreviewThumbnails = +/*#__PURE__*/ +function () { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + function PreviewThumbnails(player) { + _classCallCheck(this, PreviewThumbnails); + + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + this.elements = { + thumb: {}, + scrubbing: {} + }; + this.load(); + } + + _createClass(PreviewThumbnails, [{ + key: "load", + value: function load() { + var _this = this; + + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; + } + + if (!this.enabled) { + return; + } + + this.getThumbnails().then(function () { + // Render DOM elements + _this.render(); // Check to see if thumb container size was specified manually in CSS + + + _this.determineContainerAutoSizing(); + + _this.loaded = true; + }); + } // Download VTT files and parse them + + }, { + key: "getThumbnails", + value: function getThumbnails() { + var _this2 = this; + + return new Promise(function (resolve) { + var src = _this2.player.config.previewThumbnails.src; + + if (is.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } // If string, convert into single-element list + + + var urls = is.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails + + var promises = urls.map(function (u) { + return _this2.getThumbnail(u); + }); + Promise.all(promises).then(function () { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + _this2.thumbnails.sort(function (x, y) { + return x.height - y.height; + }); + + _this2.player.debug.log('Preview thumbnails', _this2.thumbnails); + + resolve(); + }); + }); + } // Process individual VTT file + + }, { + key: "getThumbnail", + value: function getThumbnail(url) { + var _this3 = this; + + return new Promise(function (resolve) { + fetch(url).then(function (response) { + var thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '' + }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank + + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } // Download the first frame, so that we can determine/set the height of this thumbnailsDef + + + var tempImage = new Image(); + + tempImage.onload = function () { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; + + _this3.thumbnails.push(thumbnail); + + resolve(); + }; + + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } + }, { + key: "startMove", + value: function startMove(event) { + if (!this.loaded) { + return; + } + + if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } // Wait until media has a duration + + + if (!this.player.media.duration) { + return; + } + + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + var clientRect = this.player.elements.progress.getBoundingClientRect(); + var percentage = 100 / clientRect.width * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); + + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } + + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } + + this.mousePosX = event.pageX; // Set time text inside image container + + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } // Download and show image + + + this.showImageAtCurrentTime(); + } + }, { + key: "endMove", + value: function endMove() { + this.toggleThumbContainer(false, true); + } + }, { + key: "startScrubbing", + value: function startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; // Wait until media has a duration + + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); // Download and show image + + this.showImageAtCurrentTime(); + } + } + } + }, { + key: "finishScrubbing", + value: function finishScrubbing() { + var _this4 = this; + + this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview + + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', function () { + // Re-check mousedown - we might have already started scrubbing again + if (!_this4.mouseDown) { + _this4.toggleScrubbingContainer(false); + } + }); + } + } + /** + * Setup hooks for Plyr and window events + */ + + }, { + key: "listeners", + value: function listeners() { + var _this5 = this; + + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', function () { + _this5.toggleThumbContainer(false, true); + }); + this.player.on('seeked', function () { + _this5.toggleThumbContainer(false); + }); + this.player.on('timeupdate', function () { + _this5.lastTime = _this5.player.media.currentTime; + }); + } + /** + * Create HTML elements for image containers + */ + + }, { + key: "render", + value: function render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer + }); // Wrapper for the image for styling + + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00) + + var timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer + }); + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb + + this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container + + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer + }); + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + }, { + key: "showImageAtCurrentTime", + value: function showImageAtCurrentTime() { + var _this6 = this; + + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null + + + var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) { + return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime; + }); + var hasThumb = thumbNum >= 0; + var qualityIndex = 0; + this.toggleThumbContainer(hasThumb); // No matching thumb found + + if (!hasThumb) { + return; + } // Check to see if we've already downloaded higher quality versions of this image + + + this.thumbnails.forEach(function (thumbnail, index) { + if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); // Only proceed if either thumbnum or thumbfilename has changed + + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); + } + } // Show the image that's currently specified in this.showingThumb + + }, { + key: "loadImage", + value: function loadImage() { + var _this7 = this; + + var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var thumbNum = this.showingThumb; + var thumbnail = this.thumbnails[qualityIndex]; + var urlPrefix = thumbnail.urlPrefix; + var frame = thumbnail.frames[thumbNum]; + var thumbFilename = thumbnail.frames[thumbNum].text; + var thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + + + var previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + + previewImage.onload = function () { + return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + }; + + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); + } + } + }, { + key: "showImage", + value: function showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename) { + var newImage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this.player.debug.log("Showing thumb: ".concat(thumbFilename, ". num: ").concat(thumbNum, ". qual: ").concat(qualityIndex, ". newimg: ").concat(newImage)); + this.setImageSizeAndOffset(previewImage, frame); + + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; + + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading + + + this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } // Remove all preview images that aren't the designated current image + + }, { + key: "removeOldImages", + value: function removeOldImages(currentImage) { + var _this8 = this; + + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(function (image) { + if (image.tagName.toLowerCase() !== 'img') { + return; + } + + var removeDelay = _this8.usingSprites ? 500 : 1000; + + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub + + var currentImageContainer = _this8.currentImageContainer; + setTimeout(function () { + currentImageContainer.removeChild(image); + + _this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename)); + }, removeDelay); + } + }); + } // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality + + }, { + key: "preloadNearby", + value: function preloadNearby(thumbNum) { + var _this9 = this; + + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return new Promise(function (resolve) { + setTimeout(function () { + var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text; + + if (_this9.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + var thumbnailsClone; + + if (forward) { + thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } + + var foundOne = false; + thumbnailsClone.forEach(function (frame) { + var newThumbFilename = frame.text; + + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!_this9.loadedImages.includes(newThumbFilename)) { + foundOne = true; + + _this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename)); + + var urlPrefix = _this9.thumbnails[0].urlPrefix; + var thumbURL = urlPrefix + newThumbFilename; + var previewImage = new Image(); + previewImage.src = thumbURL; + + previewImage.onload = function () { + _this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename)); + + if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded + + resolve(); + }; + } + } + }); // If there are none to preload then we want to resolve immediately + + if (!foundOne) { + resolve(); + } + } + }, 300); + }); + } // If user has been hovering current image for half a second, look for a higher quality one + + }, { + key: "getHigherQuality", + value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + var _this10 = this; + + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + var previewImageHeight = previewImage.naturalHeight; + + if (this.usingSprites) { + previewImageHeight = frame.h; + } + + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(function () { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (_this10.showingThumbFilename === thumbFilename) { + _this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename)); + + _this10.loadImage(currentQualityIndex + 1); + } + }, 300); + } + } + } + }, { + key: "toggleThumbContainer", + value: function toggleThumbContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var clearShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); + + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "toggleScrubbingContainer", + value: function toggleScrubbingContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); + + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "determineContainerAutoSizing", + value: function determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS + + }, { + key: "setThumbContainerSizeAndPos", + value: function setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px"); + this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px"); + } + + this.setThumbContainerPos(); + } + }, { + key: "setThumbContainerPos", + value: function setThumbContainerPos() { + var seekbarRect = this.player.elements.progress.getBoundingClientRect(); + var plyrRect = this.player.elements.container.getBoundingClientRect(); + var container = this.elements.thumb.container; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container + + var minVal = plyrRect.left - seekbarRect.left + 10; + var maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth + + var previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; + + if (previewPos < minVal) { + previewPos = minVal; + } + + if (previewPos > maxVal) { + previewPos = maxVal; + } + + container.style.left = "".concat(previewPos, "px"); + } // Can't use 100% width, in case the video is a different aspect ratio to the video container + + }, { + key: "setScrubbingContainerSize", + value: function setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below + + this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px"); + } // Sprites need to be offset to the correct location + + }, { + key: "setImageSizeAndOffset", + value: function setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } // Find difference between height and preview container height + + + var multiplier = this.thumbContainerHeight / frame.h; + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); + } + }, { + key: "enabled", + get: function get() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + }, { + key: "currentImageContainer", + get: function get() { + if (this.mouseDown) { + return this.elements.scrubbing.container; + } + + return this.elements.thumb.imageContainer; + } + }, { + key: "usingSprites", + get: function get() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } + }, { + key: "thumbAspectRatio", + get: function get() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; + } + + return this.thumbnails[0].width / this.thumbnails[0].height; + } + }, { + key: "thumbContainerHeight", + get: function get() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); + } + + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + }, { + key: "currentImageElement", + get: function get() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } + + return this.currentThumbnailImageElement; + }, + set: function set(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; + } + } + }]); + + return PreviewThumbnails; +}(); + +var source = { + // Add elements to HTML5 media (source, tracks, etc) + insertElements: function insertElements(type, attributes) { + var _this = this; + + if (is.string(attributes)) { + insertElement(type, this.media, { + src: attributes + }); + } else if (is.array(attributes)) { + attributes.forEach(function (attribute) { + insertElement(type, _this.media, attribute); + }); + } + }, + // Update source + // Sources are not checked for support so be careful + change: function change(input) { + var _this2 = this; + + if (!getDeep(input, 'sources.length')) { + this.debug.warn('Invalid source format'); + return; + } // Cancel current network requests + + + html5.cancelRequests.call(this); // Destroy instance and re-setup + + this.destroy.call(this, function () { + // Reset quality options + _this2.options.quality = []; // Remove elements + + removeElement(_this2.media); + _this2.media = null; // Reset class name + + if (is.element(_this2.elements.container)) { + _this2.elements.container.removeAttribute('class'); + } // Set the type and provider + + + var sources = input.sources, + type = input.type; + + var _sources = _slicedToArray(sources, 1), + _sources$ = _sources[0], + _sources$$provider = _sources$.provider, + provider = _sources$$provider === void 0 ? providers.html5 : _sources$$provider, + src = _sources$.src; + + var tagName = provider === 'html5' ? type : 'div'; + var attributes = provider === 'html5' ? {} : { + src: src + }; + Object.assign(_this2, { + provider: provider, + type: type, + // Check for support + supported: support.check(type, provider, _this2.config.playsinline), + // Create new element + media: createElement(tagName, attributes) + }); // Inject the new element + + _this2.elements.container.appendChild(_this2.media); // Autoplay the new source? + + + if (is.boolean(input.autoplay)) { + _this2.config.autoplay = input.autoplay; + } // Set attributes for audio and video + + + if (_this2.isHTML5) { + if (_this2.config.crossorigin) { + _this2.media.setAttribute('crossorigin', ''); + } + + if (_this2.config.autoplay) { + _this2.media.setAttribute('autoplay', ''); + } + + if (!is.empty(input.poster)) { + _this2.poster = input.poster; + } + + if (_this2.config.loop.active) { + _this2.media.setAttribute('loop', ''); + } + + if (_this2.config.muted) { + _this2.media.setAttribute('muted', ''); + } + + if (_this2.config.playsinline) { + _this2.media.setAttribute('playsinline', ''); + } + } // Restore class hook + + + ui.addStyleHook.call(_this2); // Set new sources for html5 + + if (_this2.isHTML5) { + source.insertElements.call(_this2, 'source', sources); + } // Set video title + + + _this2.config.title = input.title; // Set up from scratch + + media.setup.call(_this2); // HTML5 stuff + + if (_this2.isHTML5) { + // Setup captions + if (Object.keys(input).includes('tracks')) { + source.insertElements.call(_this2, 'track', input.tracks); + } + } // If HTML5 or embed but not fully supported, setupInterface and call ready now + + + if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { + // Setup interface + ui.build.call(_this2); + } // Load HTML5 sources + + + if (_this2.isHTML5) { + _this2.media.load(); + } // Reload thumbnails + + + if (_this2.previewThumbnails) { + _this2.previewThumbnails.load(); + } // Update the fullscreen support + + + _this2.fullscreen.update(); + }, true); + } +}; + +// TODO: Use a WeakMap for private globals +// const globals = new WeakMap(); +// Plyr instance + +var Plyr = +/*#__PURE__*/ +function () { + function Plyr(target, options) { + var _this = this; + + _classCallCheck(this, Plyr); + + this.timers = {}; // State + + this.ready = false; + this.loading = false; + this.failed = false; // Touch device + + this.touch = support.touch; // Set the media element + + this.media = target; // String selector passed + + if (is.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } // jQuery, NodeList or Array passed, use first element + + + if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } // Set config + + + this.config = extend({}, defaults, Plyr.defaults, options || {}, function () { + try { + return JSON.parse(_this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; + } + }()); // Elements cache + + this.elements = { + container: null, + captions: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + popup: null, + menu: null, + panels: {}, + buttons: {} + } + }; // Captions + + this.captions = { + active: null, + currentTrack: -1, + meta: new WeakMap() + }; // Fullscreen + + this.fullscreen = { + active: false + }; // Options + + this.options = { + speed: [], + quality: [] + }; // Debugging + // TODO: move to globals + + this.debug = new Console(this.config.debug); // Log config options and support + + this.debug.log('Config', this.config); + this.debug.log('Support', support); // We need an element to setup + + if (is.nullOrUndefined(this.media) || !is.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); + return; + } // Bail if the element is initialized + + + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; + } // Bail if not enabled + + + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; + } // Bail if disabled or no basic support + // You may want to disable certain UAs etc + + + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; + } // Cache original element state for .destroy() + + + var clone = this.media.cloneNode(true); + clone.autoplay = false; + this.elements.original = clone; // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube + + var type = this.media.tagName.toLowerCase(); // Embed properties + + var iframe = null; + var url = null; // Different setup based on type + + switch (type) { + case 'div': + // Find the frame + iframe = this.media.querySelector('iframe'); // <iframe> type + + if (is.element(iframe)) { + // Detect provider + url = parseUrl(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements + + this.elements.container = this.media; + this.media = iframe; // Reset classname + + this.elements.container.className = ''; // Get attributes from URL and set config + + if (url.search.length) { + var truthy = ['1', 'true']; + + if (truthy.includes(url.searchParams.get('autoplay'))) { + this.config.autoplay = true; + } + + if (truthy.includes(url.searchParams.get('loop'))) { + this.config.loop.active = true; + } // TODO: replace fullscreen.iosNative with this playsinline config option + // YouTube requires the playsinline in the URL + + + if (this.isYouTube) { + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? + } else { + this.config.playsinline = true; + } + } + } else { + // <div> with attributes + this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute + + this.media.removeAttribute(this.config.attributes.embed.provider); + } // Unsupported or missing provider + + + if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } // Audio will come later for external providers + + + this.type = types.video; + break; + + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; // Get config from attributes + + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } + + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } + + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { + this.config.playsinline = true; + } + + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } + + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } + + break; + + default: + this.debug.error('Setup failed: unsupported type'); + return; + } // Check for support again but with type + + + this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail + + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); + return; + } + + this.eventListeners = []; // Create listeners + + this.listeners = new Listeners(this); // Setup local storage for user settings + + this.storage = new Storage(this); // Store reference + + this.media.plyr = this; // Wrap media + + if (!is.element(this.elements.container)) { + this.elements.container = createElement('div', { + tabindex: 0 + }); + wrap(this.media, this.elements.container); + } // Add style hook + + + ui.addStyleHook.call(this); // Setup media + + media.setup.call(this); // Listen for events if debugging + + if (this.config.debug) { + on.call(this, this.elements.container, this.config.events.join(' '), function (event) { + _this.debug.log("event: ".concat(event.type)); + }); + } // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls + + + if (this.isHTML5 || this.isEmbed && !this.supported.ui) { + ui.build.call(this); + } // Container listeners + + + this.listeners.container(); // Global listeners + + this.listeners.global(); // Setup fullscreen + + this.fullscreen = new Fullscreen(this); // Setup ads if provided + + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required + + + if (this.config.autoplay) { + this.play(); + } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek + + + this.lastSeekTime = 0; // Setup preview thumbnails if enabled + + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } + } // --------------------------------------- + // API + // --------------------------------------- + + /** + * Types and provider helpers + */ + + + _createClass(Plyr, [{ + key: "play", + + /** + * Play the media, or play the advertisement (if they are not blocked) + */ + value: function play() { + if (!is.function(this.media.play)) { + return null; + } // Return the promise (for HTML5) + + + return this.media.play(); + } + /** + * Pause the media + */ + + }, { + key: "pause", + value: function pause() { + if (!this.playing || !is.function(this.media.pause)) { + return; + } + + this.media.pause(); + } + /** + * Get playing state + */ + + }, { + key: "togglePlay", + + /** + * Toggle playback based on current status + * @param {boolean} input + */ + value: function togglePlay(input) { + // Toggle based on current state if nothing passed + var toggle = is.boolean(input) ? input : !this.playing; + + if (toggle) { + this.play(); + } else { + this.pause(); + } + } + /** + * Stop playback + */ + + }, { + key: "stop", + value: function stop() { + if (this.isHTML5) { + this.pause(); + this.restart(); + } else if (is.function(this.media.stop)) { + this.media.stop(); + } + } + /** + * Restart playback + */ + + }, { + key: "restart", + value: function restart() { + this.currentTime = 0; + } + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ + + }, { + key: "rewind", + value: function rewind(seekTime) { + this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ + + }, { + key: "forward", + value: function forward(seekTime) { + this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ + + }, { + key: "increaseVolume", + + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + value: function increaseVolume(step) { + var volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (is.number(step) ? step : 0); + } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + + }, { + key: "decreaseVolume", + value: function decreaseVolume(step) { + this.increaseVolume(-step); + } + /** + * Set muted state + * @param {boolean} mute + */ + + }, { + key: "toggleCaptions", + + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + value: function toggleCaptions(input) { + captions.toggle.call(this, input, false); + } + /** + * Set the caption track by index + * @param {number} - Caption index + */ + + }, { + key: "airplay", + + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + value: function airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); + } + } + /** + * Toggle the player controls + * @param {boolean} [toggle] - Whether to show the controls + */ + + }, { + key: "toggleControls", + value: function toggleControls(toggle) { + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + var isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls + + var force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state + + var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu + + if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); + } // Trigger event on change + + + if (hiding !== isHidden) { + var eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); + } + + return !hiding; + } + + return false; + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + on.call(this, this.elements.container, event, callback); + } + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "once", + value: function once$$1(event, callback) { + once.call(this, this.elements.container, event, callback); + } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "off", + value: function off$$1(event, callback) { + off(this.elements.container, event, callback); + } + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ + + }, { + key: "destroy", + value: function destroy(callback) { + var _this2 = this; + + var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!this.ready) { + return; + } + + var done = function done() { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; // GC for embed + + _this2.embed = null; // If it's a soft destroy, make minimal changes + + if (soft) { + if (Object.keys(_this2.elements).length) { + // Remove elements + removeElement(_this2.elements.buttons.play); + removeElement(_this2.elements.captions); + removeElement(_this2.elements.controls); + removeElement(_this2.elements.wrapper); // Clear for GC + + _this2.elements.buttons.play = null; + _this2.elements.captions = null; + _this2.elements.controls = null; + _this2.elements.wrapper = null; + } // Callback + + + if (is.function(callback)) { + callback(); + } + } else { + // Unbind listeners + unbindListeners.call(_this2); // Replace the container with the original element provided + + replaceElement(_this2.elements.original, _this2.elements.container); // Event + + triggerEvent.call(_this2, _this2.elements.original, 'destroyed', true); // Callback + + if (is.function(callback)) { + callback.call(_this2.elements.original); + } // Reset state + + + _this2.ready = false; // Clear for garbage collection + + setTimeout(function () { + _this2.elements = null; + _this2.media = null; + }, 200); + } + }; // Stop playback + + + this.stop(); // Provider specific stuff + + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); // Restore native video controls + + ui.toggleNativeControls.call(this, true); // Clean up + + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); // Destroy YouTube API + + if (this.embed !== null && is.function(this.embed.destroy)) { + this.embed.destroy(); + } // Clean up + + + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } // Vimeo does not always return + + + setTimeout(done, 200); + } + } + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ + + }, { + key: "supports", + value: function supports(type) { + return support.mime.call(this, type); + } + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ + + }, { + key: "isHTML5", + get: function get() { + return Boolean(this.provider === providers.html5); + } + }, { + key: "isEmbed", + get: function get() { + return Boolean(this.isYouTube || this.isVimeo); + } + }, { + key: "isYouTube", + get: function get() { + return Boolean(this.provider === providers.youtube); + } + }, { + key: "isVimeo", + get: function get() { + return Boolean(this.provider === providers.vimeo); + } + }, { + key: "isVideo", + get: function get() { + return Boolean(this.type === types.video); + } + }, { + key: "isAudio", + get: function get() { + return Boolean(this.type === types.audio); + } + }, { + key: "playing", + get: function get() { + return Boolean(this.ready && !this.paused && !this.ended); + } + /** + * Get paused state + */ + + }, { + key: "paused", + get: function get() { + return Boolean(this.media.paused); + } + /** + * Get stopped state + */ + + }, { + key: "stopped", + get: function get() { + return Boolean(this.paused && this.currentTime === 0); + } + /** + * Get ended state + */ + + }, { + key: "ended", + get: function get() { + return Boolean(this.media.ended); + } + }, { + key: "currentTime", + set: function set(input) { + // Bail if media duration isn't available yet + if (!this.duration) { + return; + } // Validate input + + + var inputIsValid = is.number(input) && input > 0; // Set + + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging + + this.debug.log("Seeking to ".concat(this.currentTime, " seconds")); + } + /** + * Get current time + */ + , + get: function get() { + return Number(this.media.currentTime); + } + /** + * Get buffered + */ + + }, { + key: "buffered", + get: function get() { + var buffered = this.media.buffered; // YouTube / Vimeo return a float between 0-1 + + if (is.number(buffered)) { + return buffered; + } // HTML5 + // TODO: Handle buffered chunks of the media + // (i.e. seek to another section buffers only that section) + + + if (buffered && buffered.length && this.duration > 0) { + return buffered.end(0) / this.duration; + } + + return 0; + } + /** + * Get seeking status + */ + + }, { + key: "seeking", + get: function get() { + return Boolean(this.media.seeking); + } + /** + * Get the duration of the current media + */ + + }, { + key: "duration", + get: function get() { + // Faux duration set via config + var fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded + + var realDuration = (this.media || {}).duration; + var duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration + + return fauxDuration || duration; + } + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ + + }, { + key: "volume", + set: function set(value) { + var volume = value; + var max = 1; + var min = 0; + + if (is.string(volume)) { + volume = Number(volume); + } // Load volume from storage if no value specified + + + if (!is.number(volume)) { + volume = this.storage.get('volume'); + } // Use config if all else fails + + + if (!is.number(volume)) { + volume = this.config.volume; + } // Maximum is volumeMax + + + if (volume > max) { + volume = max; + } // Minimum is volumeMin + + + if (volume < min) { + volume = min; + } // Update config + + + this.config.volume = volume; // Set the player volume + + this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state + + if (!is.empty(value) && this.muted && volume > 0) { + this.muted = false; + } + } + /** + * Get the current player volume + */ + , + get: function get() { + return Number(this.media.volume); + } + }, { + key: "muted", + set: function set(mute) { + var toggle = mute; // Load muted state from storage + + if (!is.boolean(toggle)) { + toggle = this.storage.get('muted'); + } // Use config if all else fails + + + if (!is.boolean(toggle)) { + toggle = this.config.muted; + } // Update config + + + this.config.muted = toggle; // Set mute on the player + + this.media.muted = toggle; + } + /** + * Get current muted state + */ + , + get: function get() { + return Boolean(this.media.muted); + } + /** + * Check if the media has audio + */ + + }, { + key: "hasAudio", + get: function get() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; + } + + if (this.isAudio) { + return true; + } // Get audio tracks + + + return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } + /** + * Set playback speed + * @param {number} speed - the speed of playback (0.5-2.0) + */ + + }, { + key: "speed", + set: function set(input) { + var speed = null; + + if (is.number(input)) { + speed = input; + } + + if (!is.number(speed)) { + speed = this.storage.get('speed'); + } + + if (!is.number(speed)) { + speed = this.config.speed.selected; + } // Set min/max + + + if (speed < 0.1) { + speed = 0.1; + } + + if (speed > 2.0) { + speed = 2.0; + } + + if (!this.config.speed.options.includes(speed)) { + this.debug.warn("Unsupported speed (".concat(speed, ")")); + return; + } // Update config + + + this.config.speed.selected = speed; // Set media speed + + this.media.playbackRate = speed; + } + /** + * Get current playback speed + */ + , + get: function get() { + return Number(this.media.playbackRate); + } + /** + * Set playback quality + * Currently HTML5 & YouTube only + * @param {number} input - Quality level + */ + + }, { + key: "quality", + set: function set(input) { + var config = this.config.quality; + var options = this.options.quality; + + if (!options.length) { + return; + } + + var quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number); + var updateStorage = true; + + if (!options.includes(quality)) { + var value = closest(options, quality); + this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); + quality = value; // Don't update storage if quality is not supported + + updateStorage = false; + } // Update config + + + config.selected = quality; // Set quality + + this.media.quality = quality; // Save to storage + + if (updateStorage) { + this.storage.set({ + quality: quality + }); + } + } + /** + * Get current quality level + */ + , + get: function get() { + return this.media.quality; + } + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ + + }, { + key: "loop", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; // Set default to be a true toggle + + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; + } + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; + } + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; + case 'toggle': + if (this.config.loop.active) { + this.config.loop.start = 0; + this.config.loop.end = null; + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } + /** + * Get current loop state + */ + , + get: function get() { + return Boolean(this.media.loop); + } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ + + }, { + key: "source", + set: function set(input) { + source.change.call(this, input); + } + /** + * Get current source + */ + , + get: function get() { + return this.media.currentSrc; + } + /** + * Get a download URL (either source or custom) + */ + + }, { + key: "download", + get: function get() { + var download = this.config.urls.download; + return is.url(download) ? download : this.source; + } + /** + * Set the poster image for a video + * @param {input} - the URL for the new poster image + */ + + }, { + key: "poster", + set: function set(input) { + if (!this.isVideo) { + this.debug.warn('Poster can only be set for video'); + return; + } + + ui.setPoster.call(this, input, false).catch(function () {}); + } + /** + * Get the current poster image + */ + , + get: function get() { + if (!this.isVideo) { + return null; + } + + return this.media.getAttribute('poster'); + } + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ + + }, { + key: "autoplay", + set: function set(input) { + var toggle = is.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } + /** + * Get the current autoplay state + */ + , + get: function get() { + return Boolean(this.config.autoplay); + } + }, { + key: "currentTrack", + set: function set(input) { + captions.set.call(this, input, false); + } + /** + * Get the current caption track index (-1 if disabled) + */ + , + get: function get() { + var _this$captions = this.captions, + toggled = _this$captions.toggled, + currentTrack = _this$captions.currentTrack; + return toggled ? currentTrack : -1; + } + /** + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ + + }, { + key: "language", + set: function set(input) { + captions.setLanguage.call(this, input, false); + } + /** + * Get the current track's language + */ + , + get: function get() { + return (captions.getCurrentTrack.call(this) || {}).language; + } + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ + + }, { + key: "pip", + set: function set(input) { + // Bail if no support + if (!support.pip) { + return; + } // Toggle based on current state if not passed + + + var toggle = is.boolean(input) ? input : !this.pip; // Toggle based on current state + // Safari + + if (is.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } // Chrome + + + if (is.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } + } + } + /** + * Get the current picture-in-picture state + */ + , + get: function get() { + if (!support.pip) { + return null; + } // Safari + + + if (!is.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } // Chrome + + + return this.media === document.pictureInPictureElement; + } + }], [{ + key: "supported", + value: function supported(type, provider, inline) { + return support.check(type, provider, inline); + } + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ + + }, { + key: "loadSprite", + value: function loadSprite$$1(url, id) { + return loadSprite(url, id); + } + /** + * Setup multiple instances + * @param {*} selector + * @param {object} options + */ + + }, { + key: "setup", + value: function setup(selector) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var targets = null; + + if (is.string(selector)) { + targets = Array.from(document.querySelectorAll(selector)); + } else if (is.nodeList(selector)) { + targets = Array.from(selector); + } else if (is.array(selector)) { + targets = selector.filter(is.element); + } + + if (is.empty(targets)) { + return null; + } + + return targets.map(function (t) { + return new Plyr(t, options); + }); + } + }]); + + return Plyr; +}(); + +Plyr.defaults = cloneDeep(defaults); + +export default Plyr; diff --git a/dist/plyr.polyfilled.js b/dist/plyr.polyfilled.js index b3c11364..f23fac5f 100644 --- a/dist/plyr.polyfilled.js +++ b/dist/plyr.polyfilled.js @@ -1,13125 +1,11731 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('Plyr', factory) : - (global.Plyr = factory()); +typeof navigator === "object" && (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('Plyr', factory) : + (global.Plyr = factory()); }(this, (function () { 'use strict'; -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var _global = createCommonjsModule(function (module) { -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self - // eslint-disable-next-line no-new-func - : Function('return this')(); -if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef -}); - -var _core = createCommonjsModule(function (module) { -var core = module.exports = { version: '2.5.3' }; -if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef -}); -var _core_1 = _core.version; - -var _isObject = function (it) { - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; - -var _anObject = function (it) { - if (!_isObject(it)) throw TypeError(it + ' is not an object!'); - return it; -}; - -var _fails = function (exec) { - try { - return !!exec(); - } catch (e) { - return true; - } -}; - -// Thank's IE8 for his funny defineProperty -var _descriptors = !_fails(function () { - return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; -}); - -var document$1 = _global.document; -// typeof document.createElement is 'object' in old IE -var is = _isObject(document$1) && _isObject(document$1.createElement); -var _domCreate = function (it) { - return is ? document$1.createElement(it) : {}; -}; - -var _ie8DomDefine = !_descriptors && !_fails(function () { - return Object.defineProperty(_domCreate('div'), 'a', { get: function () { return 7; } }).a != 7; -}); - -// 7.1.1 ToPrimitive(input [, PreferredType]) - -// instead of the ES6 spec version, we didn't implement @@toPrimitive case -// and the second argument - flag - preferred type is a string -var _toPrimitive = function (it, S) { - if (!_isObject(it)) return it; - var fn, val; - if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; - if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val; - if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; - throw TypeError("Can't convert object to primitive value"); -}; - -var dP = Object.defineProperty; - -var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) { - _anObject(O); - P = _toPrimitive(P, true); - _anObject(Attributes); - if (_ie8DomDefine) try { - return dP(O, P, Attributes); - } catch (e) { /* empty */ } - if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); - if ('value' in Attributes) O[P] = Attributes.value; - return O; -}; - -var _objectDp = { - f: f -}; - -var _propertyDesc = function (bitmap, value) { - return { - enumerable: !(bitmap & 1), - configurable: !(bitmap & 2), - writable: !(bitmap & 4), - value: value - }; -}; - -var _hide = _descriptors ? function (object, key, value) { - return _objectDp.f(object, key, _propertyDesc(1, value)); -} : function (object, key, value) { - object[key] = value; - return object; -}; - -var hasOwnProperty = {}.hasOwnProperty; -var _has = function (it, key) { - return hasOwnProperty.call(it, key); -}; - -var id = 0; -var px = Math.random(); -var _uid = function (key) { - return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); -}; - -var _redefine = createCommonjsModule(function (module) { -var SRC = _uid('src'); -var TO_STRING = 'toString'; -var $toString = Function[TO_STRING]; -var TPL = ('' + $toString).split(TO_STRING); - -_core.inspectSource = function (it) { - return $toString.call(it); -}; - -(module.exports = function (O, key, val, safe) { - var isFunction = typeof val == 'function'; - if (isFunction) _has(val, 'name') || _hide(val, 'name', key); - if (O[key] === val) return; - if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); - if (O === _global) { - O[key] = val; - } else if (!safe) { - delete O[key]; - _hide(O, key, val); - } else if (O[key]) { - O[key] = val; - } else { - _hide(O, key, val); - } -// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative -})(Function.prototype, TO_STRING, function toString() { - return typeof this == 'function' && this[SRC] || $toString.call(this); -}); -}); - -var _aFunction = function (it) { - if (typeof it != 'function') throw TypeError(it + ' is not a function!'); - return it; -}; - -// optional / simple context binding - -var _ctx = function (fn, that, length) { - _aFunction(fn); - if (that === undefined) return fn; - switch (length) { - case 1: return function (a) { - return fn.call(that, a); - }; - case 2: return function (a, b) { - return fn.call(that, a, b); - }; - case 3: return function (a, b, c) { - return fn.call(that, a, b, c); - }; - } - return function (/* ...args */) { - return fn.apply(that, arguments); - }; -}; - -var PROTOTYPE = 'prototype'; - -var $export = function (type, name, source) { - var IS_FORCED = type & $export.F; - var IS_GLOBAL = type & $export.G; - var IS_STATIC = type & $export.S; - var IS_PROTO = type & $export.P; - var IS_BIND = type & $export.B; - var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE]; - var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {}); - var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); - var key, own, out, exp; - if (IS_GLOBAL) source = name; - for (key in source) { - // contains in native - own = !IS_FORCED && target && target[key] !== undefined; - // export native or passed - out = (own ? target : source)[key]; - // bind timers to global for call from export context - exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out; - // extend global - if (target) _redefine(target, key, out, type & $export.U); - // export - if (exports[key] != out) _hide(exports, key, exp); - if (IS_PROTO && expProto[key] != out) expProto[key] = out; - } -}; -_global.core = _core; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -$export.U = 64; // safe -$export.R = 128; // real proto method for `library` -var _export = $export; - -var TYPED = _uid('typed_array'); -var VIEW = _uid('view'); -var ABV = !!(_global.ArrayBuffer && _global.DataView); -var CONSTR = ABV; -var i = 0; -var l = 9; -var Typed; - -var TypedArrayConstructors = ( - 'Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array' -).split(','); - -while (i < l) { - if (Typed = _global[TypedArrayConstructors[i++]]) { - _hide(Typed.prototype, TYPED, true); - _hide(Typed.prototype, VIEW, true); - } else CONSTR = false; -} - -var _typed = { - ABV: ABV, - CONSTR: CONSTR, - TYPED: TYPED, - VIEW: VIEW -}; - -var _library = false; - -var _redefineAll = function (target, src, safe) { - for (var key in src) _redefine(target, key, src[key], safe); - return target; -}; - -var _anInstance = function (it, Constructor, name, forbiddenField) { - if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { - throw TypeError(name + ': incorrect invocation!'); - } return it; -}; - -// 7.1.4 ToInteger -var ceil = Math.ceil; -var floor = Math.floor; -var _toInteger = function (it) { - return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); -}; - -// 7.1.15 ToLength - -var min = Math.min; -var _toLength = function (it) { - return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 -}; - -// https://tc39.github.io/ecma262/#sec-toindex - - -var _toIndex = function (it) { - if (it === undefined) return 0; - var number = _toInteger(it); - var length = _toLength(number); - if (number !== length) throw RangeError('Wrong length!'); - return length; -}; - -var toString = {}.toString; - -var _cof = function (it) { - return toString.call(it).slice(8, -1); -}; - -// fallback for non-array-like ES3 and non-enumerable old V8 strings - -// eslint-disable-next-line no-prototype-builtins -var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) { - return _cof(it) == 'String' ? it.split('') : Object(it); -}; - -// 7.2.1 RequireObjectCoercible(argument) -var _defined = function (it) { - if (it == undefined) throw TypeError("Can't call method on " + it); - return it; -}; - -// to indexed object, toObject with fallback for non-array-like ES3 strings - - -var _toIobject = function (it) { - return _iobject(_defined(it)); -}; - -var max = Math.max; -var min$1 = Math.min; -var _toAbsoluteIndex = function (index, length) { - index = _toInteger(index); - return index < 0 ? max(index + length, 0) : min$1(index, length); -}; - -// false -> Array#indexOf -// true -> Array#includes - - - -var _arrayIncludes = function (IS_INCLUDES) { - return function ($this, el, fromIndex) { - var O = _toIobject($this); - var length = _toLength(O.length); - var index = _toAbsoluteIndex(fromIndex, length); - var value; - // Array#includes uses SameValueZero equality algorithm - // eslint-disable-next-line no-self-compare - if (IS_INCLUDES && el != el) while (length > index) { - value = O[index++]; - // eslint-disable-next-line no-self-compare - if (value != value) return true; - // Array#indexOf ignores holes, Array#includes - not - } else for (;length > index; index++) if (IS_INCLUDES || index in O) { - if (O[index] === el) return IS_INCLUDES || index || 0; - } return !IS_INCLUDES && -1; - }; -}; - -var SHARED = '__core-js_shared__'; -var store = _global[SHARED] || (_global[SHARED] = {}); -var _shared = function (key) { - return store[key] || (store[key] = {}); -}; - -var shared = _shared('keys'); - -var _sharedKey = function (key) { - return shared[key] || (shared[key] = _uid(key)); -}; - -var arrayIndexOf = _arrayIncludes(false); -var IE_PROTO = _sharedKey('IE_PROTO'); - -var _objectKeysInternal = function (object, names) { - var O = _toIobject(object); - var i = 0; - var result = []; - var key; - for (key in O) if (key != IE_PROTO) _has(O, key) && result.push(key); - // Don't enum bug & hidden keys - while (names.length > i) if (_has(O, key = names[i++])) { - ~arrayIndexOf(result, key) || result.push(key); - } - return result; -}; - -// IE 8- don't enum bug keys -var _enumBugKeys = ( - 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' -).split(','); - -// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) + // Polyfill for creating CustomEvents on IE9/10/11 -var hiddenKeys = _enumBugKeys.concat('length', 'prototype'); + // code pulled from: + // https://github.com/d4tocchini/customevent-polyfill + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill -var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { - return _objectKeysInternal(O, hiddenKeys); -}; + (function() { + if (typeof window === 'undefined') { + return; + } -var _objectGopn = { - f: f$1 -}; + try { + var ce = new window.CustomEvent('test', { cancelable: true }); + ce.preventDefault(); + if (ce.defaultPrevented !== true) { + // IE has problems with .preventDefault() on custom events + // http://stackoverflow.com/questions/23349191 + throw new Error('Could not prevent default'); + } + } catch (e) { + var CustomEvent = function(event, params) { + var evt, origPrevent; + params = params || { + bubbles: false, + cancelable: false, + detail: undefined + }; -// 7.1.13 ToObject(argument) + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent( + event, + params.bubbles, + params.cancelable, + params.detail + ); + origPrevent = evt.preventDefault; + evt.preventDefault = function() { + origPrevent.call(this); + try { + Object.defineProperty(this, 'defaultPrevented', { + get: function() { + return true; + } + }); + } catch (e) { + this.defaultPrevented = true; + } + }; + return evt; + }; -var _toObject = function (it) { - return Object(_defined(it)); -}; + CustomEvent.prototype = window.Event.prototype; + window.CustomEvent = CustomEvent; // expose definition to window + } + })(); -var _arrayFill = function fill(value /* , start = 0, end = @length */) { - var O = _toObject(this); - var length = _toLength(O.length); - var aLen = arguments.length; - var index = _toAbsoluteIndex(aLen > 1 ? arguments[1] : undefined, length); - var end = aLen > 2 ? arguments[2] : undefined; - var endPos = end === undefined ? length : _toAbsoluteIndex(end, length); - while (endPos > index) O[index++] = value; - return O; -}; + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; -var _wks = createCommonjsModule(function (module) { -var store = _shared('wks'); + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } -var Symbol = _global.Symbol; -var USE_SYMBOL = typeof Symbol == 'function'; + (function(global) {
+ /**
+ * Polyfill URLSearchParams
+ *
+ * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js
+ */
+
+ var checkIfIteratorIsSupported = function() {
+ try {
+ return !!Symbol.iterator;
+ } catch (error) {
+ return false;
+ }
+ };
+
+
+ var iteratorSupported = checkIfIteratorIsSupported();
+
+ var createIterator = function(items) {
+ var iterator = {
+ next: function() {
+ var value = items.shift();
+ return { done: value === void 0, value: value };
+ }
+ };
+
+ if (iteratorSupported) {
+ iterator[Symbol.iterator] = function() {
+ return iterator;
+ };
+ }
+
+ return iterator;
+ };
+
+ /**
+ * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing
+ * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.
+ */
+ var serializeParam = function(value) {
+ return encodeURIComponent(value).replace(/%20/g, '+');
+ };
+
+ var deserializeParam = function(value) {
+ return decodeURIComponent(value).replace(/\+/g, ' ');
+ };
+
+ var polyfillURLSearchParams = function() {
+
+ var URLSearchParams = function(searchString) {
+ Object.defineProperty(this, '_entries', { writable: true, value: {} });
+ var typeofSearchString = typeof searchString;
+
+ if (typeofSearchString === 'undefined') ; else if (typeofSearchString === 'string') {
+ if (searchString !== '') {
+ this._fromString(searchString);
+ }
+ } else if (searchString instanceof URLSearchParams) {
+ var _this = this;
+ searchString.forEach(function(value, name) {
+ _this.append(name, value);
+ });
+ } else if ((searchString !== null) && (typeofSearchString === 'object')) {
+ if (Object.prototype.toString.call(searchString) === '[object Array]') {
+ for (var i = 0; i < searchString.length; i++) {
+ var entry = searchString[i];
+ if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {
+ this.append(entry[0], entry[1]);
+ } else {
+ throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\'s input');
+ }
+ }
+ } else {
+ for (var key in searchString) {
+ if (searchString.hasOwnProperty(key)) {
+ this.append(key, searchString[key]);
+ }
+ }
+ }
+ } else {
+ throw new TypeError('Unsupported input\'s type for URLSearchParams');
+ }
+ };
+
+ var proto = URLSearchParams.prototype;
+
+ proto.append = function(name, value) {
+ if (name in this._entries) {
+ this._entries[name].push(String(value));
+ } else {
+ this._entries[name] = [String(value)];
+ }
+ };
+
+ proto.delete = function(name) {
+ delete this._entries[name];
+ };
+
+ proto.get = function(name) {
+ return (name in this._entries) ? this._entries[name][0] : null;
+ };
+
+ proto.getAll = function(name) {
+ return (name in this._entries) ? this._entries[name].slice(0) : [];
+ };
+
+ proto.has = function(name) {
+ return (name in this._entries);
+ };
+
+ proto.set = function(name, value) {
+ this._entries[name] = [String(value)];
+ };
+
+ proto.forEach = function(callback, thisArg) {
+ var entries;
+ for (var name in this._entries) {
+ if (this._entries.hasOwnProperty(name)) {
+ entries = this._entries[name];
+ for (var i = 0; i < entries.length; i++) {
+ callback.call(thisArg, entries[i], name, this);
+ }
+ }
+ }
+ };
+
+ proto.keys = function() {
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push(name);
+ });
+ return createIterator(items);
+ };
+
+ proto.values = function() {
+ var items = [];
+ this.forEach(function(value) {
+ items.push(value);
+ });
+ return createIterator(items);
+ };
+
+ proto.entries = function() {
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push([name, value]);
+ });
+ return createIterator(items);
+ };
+
+ if (iteratorSupported) {
+ proto[Symbol.iterator] = proto.entries;
+ }
+
+ proto.toString = function() {
+ var searchArray = [];
+ this.forEach(function(value, name) {
+ searchArray.push(serializeParam(name) + '=' + serializeParam(value));
+ });
+ return searchArray.join('&');
+ };
+
+
+ global.URLSearchParams = URLSearchParams;
+ };
+
+ if (!('URLSearchParams' in global) || (new URLSearchParams('?a=1').toString() !== 'a=1')) {
+ polyfillURLSearchParams();
+ }
+
+ var proto = URLSearchParams.prototype;
+
+ if (typeof proto.sort !== 'function') {
+ proto.sort = function() {
+ var _this = this;
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push([name, value]);
+ if (!_this._entries) {
+ _this.delete(name);
+ }
+ });
+ items.sort(function(a, b) {
+ if (a[0] < b[0]) {
+ return -1;
+ } else if (a[0] > b[0]) {
+ return +1;
+ } else {
+ return 0;
+ }
+ });
+ if (_this._entries) { // force reset because IE keeps keys index
+ _this._entries = {};
+ }
+ for (var i = 0; i < items.length; i++) {
+ this.append(items[i][0], items[i][1]);
+ }
+ };
+ }
+
+ if (typeof proto._fromString !== 'function') {
+ Object.defineProperty(proto, '_fromString', {
+ enumerable: false,
+ configurable: false,
+ writable: false,
+ value: function(searchString) {
+ if (this._entries) {
+ this._entries = {};
+ } else {
+ var keys = [];
+ this.forEach(function(value, name) {
+ keys.push(name);
+ });
+ for (var i = 0; i < keys.length; i++) {
+ this.delete(keys[i]);
+ }
+ }
+
+ searchString = searchString.replace(/^\?/, '');
+ var attributes = searchString.split('&');
+ var attribute;
+ for (var i = 0; i < attributes.length; i++) {
+ attribute = attributes[i].split('=');
+ this.append(
+ deserializeParam(attribute[0]),
+ (attribute.length > 1) ? deserializeParam(attribute[1]) : ''
+ );
+ }
+ }
+ });
+ }
+
+ // HTMLAnchorElement
+
+ })(
+ (typeof commonjsGlobal !== 'undefined') ? commonjsGlobal
+ : ((typeof window !== 'undefined') ? window
+ : ((typeof self !== 'undefined') ? self : commonjsGlobal))
+ );
+
+ (function(global) {
+ /**
+ * Polyfill URL
+ *
+ * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js
+ */
+
+ var checkIfURLIsSupported = function() {
+ try {
+ var u = new URL('b', 'http://a');
+ u.pathname = 'c%20d';
+ return (u.href === 'http://a/c%20d') && u.searchParams;
+ } catch (e) {
+ return false;
+ }
+ };
+
+
+ var polyfillURL = function() {
+ var _URL = global.URL;
+
+ var URL = function(url, base) {
+ if (typeof url !== 'string') url = String(url);
+
+ // Only create another document if the base is different from current location.
+ var doc = document, baseElement;
+ if (base && (global.location === void 0 || base !== global.location.href)) {
+ doc = document.implementation.createHTMLDocument('');
+ baseElement = doc.createElement('base');
+ baseElement.href = base;
+ doc.head.appendChild(baseElement);
+ try {
+ if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);
+ } catch (err) {
+ throw new Error('URL unable to set base ' + base + ' due to ' + err);
+ }
+ }
+
+ var anchorElement = doc.createElement('a');
+ anchorElement.href = url;
+ if (baseElement) {
+ doc.body.appendChild(anchorElement);
+ anchorElement.href = anchorElement.href; // force href to refresh
+ }
+
+ if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
+ throw new TypeError('Invalid URL');
+ }
+
+ Object.defineProperty(this, '_anchorElement', {
+ value: anchorElement
+ });
+
+
+ // create a linked searchParams which reflect its changes on URL
+ var searchParams = new URLSearchParams(this.search);
+ var enableSearchUpdate = true;
+ var enableSearchParamsUpdate = true;
+ var _this = this;
+ ['append', 'delete', 'set'].forEach(function(methodName) {
+ var method = searchParams[methodName];
+ searchParams[methodName] = function() {
+ method.apply(searchParams, arguments);
+ if (enableSearchUpdate) {
+ enableSearchParamsUpdate = false;
+ _this.search = searchParams.toString();
+ enableSearchParamsUpdate = true;
+ }
+ };
+ });
+
+ Object.defineProperty(this, 'searchParams', {
+ value: searchParams,
+ enumerable: true
+ });
+
+ var search = void 0;
+ Object.defineProperty(this, '_updateSearchParams', {
+ enumerable: false,
+ configurable: false,
+ writable: false,
+ value: function() {
+ if (this.search !== search) {
+ search = this.search;
+ if (enableSearchParamsUpdate) {
+ enableSearchUpdate = false;
+ this.searchParams._fromString(this.search);
+ enableSearchUpdate = true;
+ }
+ }
+ }
+ });
+ };
+
+ var proto = URL.prototype;
+
+ var linkURLWithAnchorAttribute = function(attributeName) {
+ Object.defineProperty(proto, attributeName, {
+ get: function() {
+ return this._anchorElement[attributeName];
+ },
+ set: function(value) {
+ this._anchorElement[attributeName] = value;
+ },
+ enumerable: true
+ });
+ };
+
+ ['hash', 'host', 'hostname', 'port', 'protocol']
+ .forEach(function(attributeName) {
+ linkURLWithAnchorAttribute(attributeName);
+ });
+
+ Object.defineProperty(proto, 'search', {
+ get: function() {
+ return this._anchorElement['search'];
+ },
+ set: function(value) {
+ this._anchorElement['search'] = value;
+ this._updateSearchParams();
+ },
+ enumerable: true
+ });
+
+ Object.defineProperties(proto, {
+
+ 'toString': {
+ get: function() {
+ var _this = this;
+ return function() {
+ return _this.href;
+ };
+ }
+ },
+
+ 'href': {
+ get: function() {
+ return this._anchorElement.href.replace(/\?$/, '');
+ },
+ set: function(value) {
+ this._anchorElement.href = value;
+ this._updateSearchParams();
+ },
+ enumerable: true
+ },
+
+ 'pathname': {
+ get: function() {
+ return this._anchorElement.pathname.replace(/(^\/?)/, '/');
+ },
+ set: function(value) {
+ this._anchorElement.pathname = value;
+ },
+ enumerable: true
+ },
+
+ 'origin': {
+ get: function() {
+ // get expected port from protocol
+ var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];
+ // add port to origin if, expected port is different than actual port
+ // and it is not empty f.e http://foo:8080
+ // 8080 != 80 && 8080 != ''
+ var addPortToOrigin = this._anchorElement.port != expectedPort &&
+ this._anchorElement.port !== '';
+
+ return this._anchorElement.protocol +
+ '//' +
+ this._anchorElement.hostname +
+ (addPortToOrigin ? (':' + this._anchorElement.port) : '');
+ },
+ enumerable: true
+ },
+
+ 'password': { // TODO
+ get: function() {
+ return '';
+ },
+ set: function(value) {
+ },
+ enumerable: true
+ },
+
+ 'username': { // TODO
+ get: function() {
+ return '';
+ },
+ set: function(value) {
+ },
+ enumerable: true
+ },
+ });
+
+ URL.createObjectURL = function(blob) {
+ return _URL.createObjectURL.apply(_URL, arguments);
+ };
+
+ URL.revokeObjectURL = function(url) {
+ return _URL.revokeObjectURL.apply(_URL, arguments);
+ };
+
+ global.URL = URL;
+
+ };
+
+ if (!checkIfURLIsSupported()) {
+ polyfillURL();
+ }
+
+ if ((global.location !== void 0) && !('origin' in global.location)) {
+ var getOrigin = function() {
+ return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');
+ };
+
+ try {
+ Object.defineProperty(global.location, 'origin', {
+ get: getOrigin,
+ enumerable: true
+ });
+ } catch (e) {
+ setInterval(function() {
+ global.location.origin = getOrigin();
+ }, 100);
+ }
+ }
+
+ })(
+ (typeof commonjsGlobal !== 'undefined') ? commonjsGlobal
+ : ((typeof window !== 'undefined') ? window
+ : ((typeof self !== 'undefined') ? self : commonjsGlobal))
+ ); + + var _aFunction = function (it) { + if (typeof it != 'function') throw TypeError(it + ' is not a function!'); + return it; + }; -var $exports = module.exports = function (name) { - return store[name] || (store[name] = - USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : _uid)('Symbol.' + name)); -}; + // optional / simple context binding -$exports.store = store; -}); + var _ctx = function (fn, that, length) { + _aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; + }; -var def = _objectDp.f; + var _global = createCommonjsModule(function (module) { + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); + if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + }); -var TAG = _wks('toStringTag'); + var _core = createCommonjsModule(function (module) { + var core = module.exports = { version: '2.6.3' }; + if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + }); + var _core_1 = _core.version; -var _setToStringTag = function (it, tag, stat) { - if (it && !_has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); -}; + var _isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; -var _typedBuffer = createCommonjsModule(function (module, exports) { + var _anObject = function (it) { + if (!_isObject(it)) throw TypeError(it + ' is not an object!'); + return it; + }; + var _fails = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; + } + }; + // Thank's IE8 for his funny defineProperty + var _descriptors = !_fails(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; + }); + var document$1 = _global.document; + // typeof document.createElement is 'object' in old IE + var is = _isObject(document$1) && _isObject(document$1.createElement); + var _domCreate = function (it) { + return is ? document$1.createElement(it) : {}; + }; + var _ie8DomDefine = !_descriptors && !_fails(function () { + return Object.defineProperty(_domCreate('div'), 'a', { get: function () { return 7; } }).a != 7; + }); + // 7.1.1 ToPrimitive(input [, PreferredType]) + + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + var _toPrimitive = function (it, S) { + if (!_isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); + }; + var dP = Object.defineProperty; + + var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) { + _anObject(O); + P = _toPrimitive(P, true); + _anObject(Attributes); + if (_ie8DomDefine) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + var _objectDp = { + f: f + }; + var _propertyDesc = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + var _hide = _descriptors ? function (object, key, value) { + return _objectDp.f(object, key, _propertyDesc(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + var hasOwnProperty = {}.hasOwnProperty; + var _has = function (it, key) { + return hasOwnProperty.call(it, key); + }; -var gOPN = _objectGopn.f; -var dP = _objectDp.f; + var id = 0; + var px = Math.random(); + var _uid = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); + }; + var _redefine = createCommonjsModule(function (module) { + var SRC = _uid('src'); + var TO_STRING = 'toString'; + var $toString = Function[TO_STRING]; + var TPL = ('' + $toString).split(TO_STRING); -var ARRAY_BUFFER = 'ArrayBuffer'; -var DATA_VIEW = 'DataView'; -var PROTOTYPE = 'prototype'; -var WRONG_LENGTH = 'Wrong length!'; -var WRONG_INDEX = 'Wrong index!'; -var $ArrayBuffer = _global[ARRAY_BUFFER]; -var $DataView = _global[DATA_VIEW]; -var Math = _global.Math; -var RangeError = _global.RangeError; -// eslint-disable-next-line no-shadow-restricted-names -var Infinity = _global.Infinity; -var BaseBuffer = $ArrayBuffer; -var abs = Math.abs; -var pow = Math.pow; -var floor = Math.floor; -var log = Math.log; -var LN2 = Math.LN2; -var BUFFER = 'buffer'; -var BYTE_LENGTH = 'byteLength'; -var BYTE_OFFSET = 'byteOffset'; -var $BUFFER = _descriptors ? '_b' : BUFFER; -var $LENGTH = _descriptors ? '_l' : BYTE_LENGTH; -var $OFFSET = _descriptors ? '_o' : BYTE_OFFSET; + _core.inspectSource = function (it) { + return $toString.call(it); + }; -// IEEE754 conversions based on https://github.com/feross/ieee754 -function packIEEE754(value, mLen, nBytes) { - var buffer = new Array(nBytes); - var eLen = nBytes * 8 - mLen - 1; - var eMax = (1 << eLen) - 1; - var eBias = eMax >> 1; - var rt = mLen === 23 ? pow(2, -24) - pow(2, -77) : 0; - var i = 0; - var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0; - var e, m, c; - value = abs(value); - // eslint-disable-next-line no-self-compare - if (value != value || value === Infinity) { - // eslint-disable-next-line no-self-compare - m = value != value ? 1 : 0; - e = eMax; - } else { - e = floor(log(value) / LN2); - if (value * (c = pow(2, -e)) < 1) { - e--; - c *= 2; - } - if (e + eBias >= 1) { - value += rt / c; - } else { - value += rt * pow(2, 1 - eBias); - } - if (value * c >= 2) { - e++; - c /= 2; - } - if (e + eBias >= eMax) { - m = 0; - e = eMax; - } else if (e + eBias >= 1) { - m = (value * c - 1) * pow(2, mLen); - e = e + eBias; + (module.exports = function (O, key, val, safe) { + var isFunction = typeof val == 'function'; + if (isFunction) _has(val, 'name') || _hide(val, 'name', key); + if (O[key] === val) return; + if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); + if (O === _global) { + O[key] = val; + } else if (!safe) { + delete O[key]; + _hide(O, key, val); + } else if (O[key]) { + O[key] = val; } else { - m = value * pow(2, eBias - 1) * pow(2, mLen); - e = 0; - } - } - for (; mLen >= 8; buffer[i++] = m & 255, m /= 256, mLen -= 8); - e = e << mLen | m; - eLen += mLen; - for (; eLen > 0; buffer[i++] = e & 255, e /= 256, eLen -= 8); - buffer[--i] |= s * 128; - return buffer; -} -function unpackIEEE754(buffer, mLen, nBytes) { - var eLen = nBytes * 8 - mLen - 1; - var eMax = (1 << eLen) - 1; - var eBias = eMax >> 1; - var nBits = eLen - 7; - var i = nBytes - 1; - var s = buffer[i--]; - var e = s & 127; - var m; - s >>= 7; - for (; nBits > 0; e = e * 256 + buffer[i], i--, nBits -= 8); - m = e & (1 << -nBits) - 1; - e >>= -nBits; - nBits += mLen; - for (; nBits > 0; m = m * 256 + buffer[i], i--, nBits -= 8); - if (e === 0) { - e = 1 - eBias; - } else if (e === eMax) { - return m ? NaN : s ? -Infinity : Infinity; - } else { - m = m + pow(2, mLen); - e = e - eBias; - } return (s ? -1 : 1) * m * pow(2, e - mLen); -} - -function unpackI32(bytes) { - return bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; -} -function packI8(it) { - return [it & 0xff]; -} -function packI16(it) { - return [it & 0xff, it >> 8 & 0xff]; -} -function packI32(it) { - return [it & 0xff, it >> 8 & 0xff, it >> 16 & 0xff, it >> 24 & 0xff]; -} -function packF64(it) { - return packIEEE754(it, 52, 8); -} -function packF32(it) { - return packIEEE754(it, 23, 4); -} - -function addGetter(C, key, internal) { - dP(C[PROTOTYPE], key, { get: function () { return this[internal]; } }); -} - -function get(view, bytes, index, isLittleEndian) { - var numIndex = +index; - var intIndex = _toIndex(numIndex); - if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX); - var store = view[$BUFFER]._b; - var start = intIndex + view[$OFFSET]; - var pack = store.slice(start, start + bytes); - return isLittleEndian ? pack : pack.reverse(); -} -function set(view, bytes, index, conversion, value, isLittleEndian) { - var numIndex = +index; - var intIndex = _toIndex(numIndex); - if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX); - var store = view[$BUFFER]._b; - var start = intIndex + view[$OFFSET]; - var pack = conversion(+value); - for (var i = 0; i < bytes; i++) store[start + i] = pack[isLittleEndian ? i : bytes - i - 1]; -} - -if (!_typed.ABV) { - $ArrayBuffer = function ArrayBuffer(length) { - _anInstance(this, $ArrayBuffer, ARRAY_BUFFER); - var byteLength = _toIndex(length); - this._b = _arrayFill.call(new Array(byteLength), 0); - this[$LENGTH] = byteLength; - }; - - $DataView = function DataView(buffer, byteOffset, byteLength) { - _anInstance(this, $DataView, DATA_VIEW); - _anInstance(buffer, $ArrayBuffer, DATA_VIEW); - var bufferLength = buffer[$LENGTH]; - var offset = _toInteger(byteOffset); - if (offset < 0 || offset > bufferLength) throw RangeError('Wrong offset!'); - byteLength = byteLength === undefined ? bufferLength - offset : _toLength(byteLength); - if (offset + byteLength > bufferLength) throw RangeError(WRONG_LENGTH); - this[$BUFFER] = buffer; - this[$OFFSET] = offset; - this[$LENGTH] = byteLength; - }; - - if (_descriptors) { - addGetter($ArrayBuffer, BYTE_LENGTH, '_l'); - addGetter($DataView, BUFFER, '_b'); - addGetter($DataView, BYTE_LENGTH, '_l'); - addGetter($DataView, BYTE_OFFSET, '_o'); - } - - _redefineAll($DataView[PROTOTYPE], { - getInt8: function getInt8(byteOffset) { - return get(this, 1, byteOffset)[0] << 24 >> 24; - }, - getUint8: function getUint8(byteOffset) { - return get(this, 1, byteOffset)[0]; - }, - getInt16: function getInt16(byteOffset /* , littleEndian */) { - var bytes = get(this, 2, byteOffset, arguments[1]); - return (bytes[1] << 8 | bytes[0]) << 16 >> 16; - }, - getUint16: function getUint16(byteOffset /* , littleEndian */) { - var bytes = get(this, 2, byteOffset, arguments[1]); - return bytes[1] << 8 | bytes[0]; - }, - getInt32: function getInt32(byteOffset /* , littleEndian */) { - return unpackI32(get(this, 4, byteOffset, arguments[1])); - }, - getUint32: function getUint32(byteOffset /* , littleEndian */) { - return unpackI32(get(this, 4, byteOffset, arguments[1])) >>> 0; - }, - getFloat32: function getFloat32(byteOffset /* , littleEndian */) { - return unpackIEEE754(get(this, 4, byteOffset, arguments[1]), 23, 4); - }, - getFloat64: function getFloat64(byteOffset /* , littleEndian */) { - return unpackIEEE754(get(this, 8, byteOffset, arguments[1]), 52, 8); - }, - setInt8: function setInt8(byteOffset, value) { - set(this, 1, byteOffset, packI8, value); - }, - setUint8: function setUint8(byteOffset, value) { - set(this, 1, byteOffset, packI8, value); - }, - setInt16: function setInt16(byteOffset, value /* , littleEndian */) { - set(this, 2, byteOffset, packI16, value, arguments[2]); - }, - setUint16: function setUint16(byteOffset, value /* , littleEndian */) { - set(this, 2, byteOffset, packI16, value, arguments[2]); - }, - setInt32: function setInt32(byteOffset, value /* , littleEndian */) { - set(this, 4, byteOffset, packI32, value, arguments[2]); - }, - setUint32: function setUint32(byteOffset, value /* , littleEndian */) { - set(this, 4, byteOffset, packI32, value, arguments[2]); - }, - setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) { - set(this, 4, byteOffset, packF32, value, arguments[2]); - }, - setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) { - set(this, 8, byteOffset, packF64, value, arguments[2]); + _hide(O, key, val); } + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + })(Function.prototype, TO_STRING, function toString() { + return typeof this == 'function' && this[SRC] || $toString.call(this); }); -} else { - if (!_fails(function () { - $ArrayBuffer(1); - }) || !_fails(function () { - new $ArrayBuffer(-1); // eslint-disable-line no-new - }) || _fails(function () { - new $ArrayBuffer(); // eslint-disable-line no-new - new $ArrayBuffer(1.5); // eslint-disable-line no-new - new $ArrayBuffer(NaN); // eslint-disable-line no-new - return $ArrayBuffer.name != ARRAY_BUFFER; - })) { - $ArrayBuffer = function ArrayBuffer(length) { - _anInstance(this, $ArrayBuffer); - return new BaseBuffer(_toIndex(length)); - }; - var ArrayBufferProto = $ArrayBuffer[PROTOTYPE] = BaseBuffer[PROTOTYPE]; - for (var keys = gOPN(BaseBuffer), j = 0, key; keys.length > j;) { - if (!((key = keys[j++]) in $ArrayBuffer)) _hide($ArrayBuffer, key, BaseBuffer[key]); - } - if (!_library) ArrayBufferProto.constructor = $ArrayBuffer; - } - // iOS Safari 7.x bug - var view = new $DataView(new $ArrayBuffer(2)); - var $setInt8 = $DataView[PROTOTYPE].setInt8; - view.setInt8(0, 2147483648); - view.setInt8(1, 2147483649); - if (view.getInt8(0) || !view.getInt8(1)) _redefineAll($DataView[PROTOTYPE], { - setInt8: function setInt8(byteOffset, value) { - $setInt8.call(this, byteOffset, value << 24 >> 24); - }, - setUint8: function setUint8(byteOffset, value) { - $setInt8.call(this, byteOffset, value << 24 >> 24); - } - }, true); -} -_setToStringTag($ArrayBuffer, ARRAY_BUFFER); -_setToStringTag($DataView, DATA_VIEW); -_hide($DataView[PROTOTYPE], _typed.VIEW, true); -exports[ARRAY_BUFFER] = $ArrayBuffer; -exports[DATA_VIEW] = $DataView; -}); - -// 7.3.20 SpeciesConstructor(O, defaultConstructor) - - -var SPECIES = _wks('species'); -var _speciesConstructor = function (O, D) { - var C = _anObject(O).constructor; - var S; - return C === undefined || (S = _anObject(C)[SPECIES]) == undefined ? D : _aFunction(S); -}; - -var SPECIES$1 = _wks('species'); - -var _setSpecies = function (KEY) { - var C = _global[KEY]; - if (_descriptors && C && !C[SPECIES$1]) _objectDp.f(C, SPECIES$1, { - configurable: true, - get: function () { return this; } }); -}; - -var ArrayBuffer = _global.ArrayBuffer; -var $ArrayBuffer = _typedBuffer.ArrayBuffer; -var $DataView = _typedBuffer.DataView; -var $isView = _typed.ABV && ArrayBuffer.isView; -var $slice = $ArrayBuffer.prototype.slice; -var VIEW$1 = _typed.VIEW; -var ARRAY_BUFFER = 'ArrayBuffer'; - -_export(_export.G + _export.W + _export.F * (ArrayBuffer !== $ArrayBuffer), { ArrayBuffer: $ArrayBuffer }); + var PROTOTYPE = 'prototype'; -_export(_export.S + _export.F * !_typed.CONSTR, ARRAY_BUFFER, { - // 24.1.3.1 ArrayBuffer.isView(arg) - isView: function isView(it) { - return $isView && $isView(it) || _isObject(it) && VIEW$1 in it; - } -}); - -_export(_export.P + _export.U + _export.F * _fails(function () { - return !new $ArrayBuffer(2).slice(1, undefined).byteLength; -}), ARRAY_BUFFER, { - // 24.1.4.3 ArrayBuffer.prototype.slice(start, end) - slice: function slice(start, end) { - if ($slice !== undefined && end === undefined) return $slice.call(_anObject(this), start); // FF fix - var len = _anObject(this).byteLength; - var first = _toAbsoluteIndex(start, len); - var final = _toAbsoluteIndex(end === undefined ? len : end, len); - var result = new (_speciesConstructor(this, $ArrayBuffer))(_toLength(final - first)); - var viewS = new $DataView(this); - var viewT = new $DataView(result); - var index = 0; - while (first < final) { - viewT.setUint8(index++, viewS.getUint8(first++)); - } return result; - } -}); + var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE]; + var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {}); + var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); + var key, own, out, exp; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out; + // extend global + if (target) _redefine(target, key, out, type & $export.U); + // export + if (exports[key] != out) _hide(exports, key, exp); + if (IS_PROTO && expProto[key] != out) expProto[key] = out; + } + }; + _global.core = _core; + // type bitmap + $export.F = 1; // forced + $export.G = 2; // global + $export.S = 4; // static + $export.P = 8; // proto + $export.B = 16; // bind + $export.W = 32; // wrap + $export.U = 64; // safe + $export.R = 128; // real proto method for `library` + var _export = $export; + + // 7.2.1 RequireObjectCoercible(argument) + var _defined = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; + }; -_setSpecies(ARRAY_BUFFER); + // 7.1.13 ToObject(argument) -// getting tag from 19.1.3.6 Object.prototype.toString() + var _toObject = function (it) { + return Object(_defined(it)); + }; -var TAG$1 = _wks('toStringTag'); -// ES3 wrong here -var ARG = _cof(function () { return arguments; }()) == 'Arguments'; + // call something on iterator step with safe closing on error -// fallback for IE11 Script Access Denied error -var tryGet = function (it, key) { - try { - return it[key]; - } catch (e) { /* empty */ } -}; - -var _classof = function (it) { - var O, T, B; - return it === undefined ? 'Undefined' : it === null ? 'Null' - // @@toStringTag case - : typeof (T = tryGet(O = Object(it), TAG$1)) == 'string' ? T - // builtinTag case - : ARG ? _cof(O) - // ES3 arguments fallback - : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; -}; - -var _iterators = {}; - -// check on default Array iterator - -var ITERATOR = _wks('iterator'); -var ArrayProto = Array.prototype; - -var _isArrayIter = function (it) { - return it !== undefined && (_iterators.Array === it || ArrayProto[ITERATOR] === it); -}; - -// 19.1.2.14 / 15.2.3.14 Object.keys(O) - - - -var _objectKeys = Object.keys || function keys(O) { - return _objectKeysInternal(O, _enumBugKeys); -}; - -var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) { - _anObject(O); - var keys = _objectKeys(Properties); - var length = keys.length; - var i = 0; - var P; - while (length > i) _objectDp.f(O, P = keys[i++], Properties[P]); - return O; -}; - -var document$2 = _global.document; -var _html = document$2 && document$2.documentElement; - -// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) - - - -var IE_PROTO$1 = _sharedKey('IE_PROTO'); -var Empty = function () { /* empty */ }; -var PROTOTYPE$1 = 'prototype'; - -// Create object with fake `null` prototype: use iframe Object with cleared prototype -var createDict = function () { - // Thrash, waste and sodomy: IE GC bug - var iframe = _domCreate('iframe'); - var i = _enumBugKeys.length; - var lt = '<'; - var gt = '>'; - var iframeDocument; - iframe.style.display = 'none'; - _html.appendChild(iframe); - iframe.src = 'javascript:'; // eslint-disable-line no-script-url - // createDict = iframe.contentWindow.Object; - // html.removeChild(iframe); - iframeDocument = iframe.contentWindow.document; - iframeDocument.open(); - iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); - iframeDocument.close(); - createDict = iframeDocument.F; - while (i--) delete createDict[PROTOTYPE$1][_enumBugKeys[i]]; - return createDict(); -}; - -var _objectCreate = Object.create || function create(O, Properties) { - var result; - if (O !== null) { - Empty[PROTOTYPE$1] = _anObject(O); - result = new Empty(); - Empty[PROTOTYPE$1] = null; - // add "__proto__" for Object.getPrototypeOf polyfill - result[IE_PROTO$1] = O; - } else result = createDict(); - return Properties === undefined ? result : _objectDps(result, Properties); -}; - -// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) - - -var IE_PROTO$2 = _sharedKey('IE_PROTO'); -var ObjectProto = Object.prototype; - -var _objectGpo = Object.getPrototypeOf || function (O) { - O = _toObject(O); - if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2]; - if (typeof O.constructor == 'function' && O instanceof O.constructor) { - return O.constructor.prototype; - } return O instanceof Object ? ObjectProto : null; -}; - -var ITERATOR$1 = _wks('iterator'); - -var core_getIteratorMethod = _core.getIteratorMethod = function (it) { - if (it != undefined) return it[ITERATOR$1] - || it['@@iterator'] - || _iterators[_classof(it)]; -}; - -// 7.2.2 IsArray(argument) - -var _isArray = Array.isArray || function isArray(arg) { - return _cof(arg) == 'Array'; -}; - -var SPECIES$2 = _wks('species'); - -var _arraySpeciesConstructor = function (original) { - var C; - if (_isArray(original)) { - C = original.constructor; - // cross-realm fallback - if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) C = undefined; - if (_isObject(C)) { - C = C[SPECIES$2]; - if (C === null) C = undefined; + var _iterCall = function (iterator, fn, value, entries) { + try { + return entries ? fn(_anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch (e) { + var ret = iterator['return']; + if (ret !== undefined) _anObject(ret.call(iterator)); + throw e; } - } return C === undefined ? Array : C; -}; + }; -// 9.4.2.3 ArraySpeciesCreate(originalArray, length) + var _iterators = {}; + var _library = false; -var _arraySpeciesCreate = function (original, length) { - return new (_arraySpeciesConstructor(original))(length); -}; + var _shared = createCommonjsModule(function (module) { + var SHARED = '__core-js_shared__'; + var store = _global[SHARED] || (_global[SHARED] = {}); -// 0 -> Array#forEach -// 1 -> Array#map -// 2 -> Array#filter -// 3 -> Array#some -// 4 -> Array#every -// 5 -> Array#find -// 6 -> Array#findIndex + (module.exports = function (key, value) { + return store[key] || (store[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: _core.version, + mode: 'global', + copyright: '© 2019 Denis Pushkarev (zloirock.ru)' + }); + }); + var _wks = createCommonjsModule(function (module) { + var store = _shared('wks'); + var Symbol = _global.Symbol; + var USE_SYMBOL = typeof Symbol == 'function'; + var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : _uid)('Symbol.' + name)); + }; + $exports.store = store; + }); -var _arrayMethods = function (TYPE, $create) { - var IS_MAP = TYPE == 1; - var IS_FILTER = TYPE == 2; - var IS_SOME = TYPE == 3; - var IS_EVERY = TYPE == 4; - var IS_FIND_INDEX = TYPE == 6; - var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; - var create = $create || _arraySpeciesCreate; - return function ($this, callbackfn, that) { - var O = _toObject($this); - var self = _iobject(O); - var f = _ctx(callbackfn, that, 3); - var length = _toLength(self.length); - var index = 0; - var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined; - var val, res; - for (;length > index; index++) if (NO_HOLES || index in self) { - val = self[index]; - res = f(val, index, O); - if (TYPE) { - if (IS_MAP) result[index] = res; // map - else if (res) switch (TYPE) { - case 3: return true; // some - case 5: return val; // find - case 6: return index; // findIndex - case 2: result.push(val); // filter - } else if (IS_EVERY) return false; // every - } - } - return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; - }; -}; - -// 22.1.3.31 Array.prototype[@@unscopables] -var UNSCOPABLES = _wks('unscopables'); -var ArrayProto$1 = Array.prototype; -if (ArrayProto$1[UNSCOPABLES] == undefined) _hide(ArrayProto$1, UNSCOPABLES, {}); -var _addToUnscopables = function (key) { - ArrayProto$1[UNSCOPABLES][key] = true; -}; - -var _iterStep = function (done, value) { - return { value: value, done: !!done }; -}; - -var IteratorPrototype = {}; - -// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() -_hide(IteratorPrototype, _wks('iterator'), function () { return this; }); - -var _iterCreate = function (Constructor, NAME, next) { - Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) }); - _setToStringTag(Constructor, NAME + ' Iterator'); -}; - -var ITERATOR$2 = _wks('iterator'); -var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` -var FF_ITERATOR = '@@iterator'; -var KEYS = 'keys'; -var VALUES = 'values'; - -var returnThis = function () { return this; }; - -var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { - _iterCreate(Constructor, NAME, next); - var getMethod = function (kind) { - if (!BUGGY && kind in proto) return proto[kind]; - switch (kind) { - case KEYS: return function keys() { return new Constructor(this, kind); }; - case VALUES: return function values() { return new Constructor(this, kind); }; - } return function entries() { return new Constructor(this, kind); }; - }; - var TAG = NAME + ' Iterator'; - var DEF_VALUES = DEFAULT == VALUES; - var VALUES_BUG = false; - var proto = Base.prototype; - var $native = proto[ITERATOR$2] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; - var $default = (!BUGGY && $native) || getMethod(DEFAULT); - var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; - var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; - var methods, key, IteratorPrototype; - // Fix native - if ($anyNative) { - IteratorPrototype = _objectGpo($anyNative.call(new Base())); - if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { - // Set @@toStringTag to native iterators - _setToStringTag(IteratorPrototype, TAG, true); - // fix for some old engines - if (!_library && !_has(IteratorPrototype, ITERATOR$2)) _hide(IteratorPrototype, ITERATOR$2, returnThis); - } - } - // fix Array#{values, @@iterator}.name in V8 / FF - if (DEF_VALUES && $native && $native.name !== VALUES) { - VALUES_BUG = true; - $default = function values() { return $native.call(this); }; - } - // Define iterator - if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR$2])) { - _hide(proto, ITERATOR$2, $default); - } - // Plug for library - _iterators[NAME] = $default; - _iterators[TAG] = returnThis; - if (DEFAULT) { - methods = { - values: DEF_VALUES ? $default : getMethod(VALUES), - keys: IS_SET ? $default : getMethod(KEYS), - entries: $entries - }; - if (FORCED) for (key in methods) { - if (!(key in proto)) _redefine(proto, key, methods[key]); - } else _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods); - } - return methods; -}; - -// 22.1.3.4 Array.prototype.entries() -// 22.1.3.13 Array.prototype.keys() -// 22.1.3.29 Array.prototype.values() -// 22.1.3.30 Array.prototype[@@iterator]() -var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) { - this._t = _toIobject(iterated); // target - this._i = 0; // next index - this._k = kind; // kind -// 22.1.5.2.1 %ArrayIteratorPrototype%.next() -}, function () { - var O = this._t; - var kind = this._k; - var index = this._i++; - if (!O || index >= O.length) { - this._t = undefined; - return _iterStep(1); - } - if (kind == 'keys') return _iterStep(0, index); - if (kind == 'values') return _iterStep(0, O[index]); - return _iterStep(0, [index, O[index]]); -}, 'values'); + // check on default Array iterator -// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) -_iterators.Arguments = _iterators.Array; + var ITERATOR = _wks('iterator'); + var ArrayProto = Array.prototype; -_addToUnscopables('keys'); -_addToUnscopables('values'); -_addToUnscopables('entries'); + var _isArrayIter = function (it) { + return it !== undefined && (_iterators.Array === it || ArrayProto[ITERATOR] === it); + }; -var ITERATOR$3 = _wks('iterator'); -var SAFE_CLOSING = false; + // 7.1.4 ToInteger + var ceil = Math.ceil; + var floor = Math.floor; + var _toInteger = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); + }; -try { - var riter = [7][ITERATOR$3](); - riter['return'] = function () { SAFE_CLOSING = true; }; -} catch (e) { /* empty */ } + // 7.1.15 ToLength -var _iterDetect = function (exec, skipClosing) { - if (!skipClosing && !SAFE_CLOSING) return false; - var safe = false; - try { - var arr = [7]; - var iter = arr[ITERATOR$3](); - iter.next = function () { return { done: safe = true }; }; - arr[ITERATOR$3] = function () { return iter; }; - exec(arr); - } catch (e) { /* empty */ } - return safe; -}; - -var _arrayCopyWithin = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) { - var O = _toObject(this); - var len = _toLength(O.length); - var to = _toAbsoluteIndex(target, len); - var from = _toAbsoluteIndex(start, len); - var end = arguments.length > 2 ? arguments[2] : undefined; - var count = Math.min((end === undefined ? len : _toAbsoluteIndex(end, len)) - from, len - to); - var inc = 1; - if (from < to && to < from + count) { - inc = -1; - from += count - 1; - to += count - 1; - } - while (count-- > 0) { - if (from in O) O[to] = O[from]; - else delete O[to]; - to += inc; - from += inc; - } return O; -}; - -var f$2 = {}.propertyIsEnumerable; - -var _objectPie = { - f: f$2 -}; - -var gOPD = Object.getOwnPropertyDescriptor; - -var f$3 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) { - O = _toIobject(O); - P = _toPrimitive(P, true); - if (_ie8DomDefine) try { - return gOPD(O, P); - } catch (e) { /* empty */ } - if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]); -}; - -var _objectGopd = { - f: f$3 -}; - -var _typedArray = createCommonjsModule(function (module) { -if (_descriptors) { - var LIBRARY = _library; - var global = _global; - var fails = _fails; - var $export = _export; - var $typed = _typed; - var $buffer = _typedBuffer; - var ctx = _ctx; - var anInstance = _anInstance; - var propertyDesc = _propertyDesc; - var hide = _hide; - var redefineAll = _redefineAll; - var toInteger = _toInteger; - var toLength = _toLength; - var toIndex = _toIndex; - var toAbsoluteIndex = _toAbsoluteIndex; - var toPrimitive = _toPrimitive; - var has = _has; - var classof = _classof; - var isObject = _isObject; - var toObject = _toObject; - var isArrayIter = _isArrayIter; - var create = _objectCreate; - var getPrototypeOf = _objectGpo; - var gOPN = _objectGopn.f; - var getIterFn = core_getIteratorMethod; - var uid = _uid; - var wks = _wks; - var createArrayMethod = _arrayMethods; - var createArrayIncludes = _arrayIncludes; - var speciesConstructor = _speciesConstructor; - var ArrayIterators = es6_array_iterator; - var Iterators = _iterators; - var $iterDetect = _iterDetect; - var setSpecies = _setSpecies; - var arrayFill = _arrayFill; - var arrayCopyWithin = _arrayCopyWithin; - var $DP = _objectDp; - var $GOPD = _objectGopd; - var dP = $DP.f; - var gOPD = $GOPD.f; - var RangeError = global.RangeError; - var TypeError = global.TypeError; - var Uint8Array = global.Uint8Array; - var ARRAY_BUFFER = 'ArrayBuffer'; - var SHARED_BUFFER = 'Shared' + ARRAY_BUFFER; - var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT'; - var PROTOTYPE = 'prototype'; - var ArrayProto = Array[PROTOTYPE]; - var $ArrayBuffer = $buffer.ArrayBuffer; - var $DataView = $buffer.DataView; - var arrayForEach = createArrayMethod(0); - var arrayFilter = createArrayMethod(2); - var arraySome = createArrayMethod(3); - var arrayEvery = createArrayMethod(4); - var arrayFind = createArrayMethod(5); - var arrayFindIndex = createArrayMethod(6); - var arrayIncludes = createArrayIncludes(true); - var arrayIndexOf = createArrayIncludes(false); - var arrayValues = ArrayIterators.values; - var arrayKeys = ArrayIterators.keys; - var arrayEntries = ArrayIterators.entries; - var arrayLastIndexOf = ArrayProto.lastIndexOf; - var arrayReduce = ArrayProto.reduce; - var arrayReduceRight = ArrayProto.reduceRight; - var arrayJoin = ArrayProto.join; - var arraySort = ArrayProto.sort; - var arraySlice = ArrayProto.slice; - var arrayToString = ArrayProto.toString; - var arrayToLocaleString = ArrayProto.toLocaleString; - var ITERATOR = wks('iterator'); - var TAG = wks('toStringTag'); - var TYPED_CONSTRUCTOR = uid('typed_constructor'); - var DEF_CONSTRUCTOR = uid('def_constructor'); - var ALL_CONSTRUCTORS = $typed.CONSTR; - var TYPED_ARRAY = $typed.TYPED; - var VIEW = $typed.VIEW; - var WRONG_LENGTH = 'Wrong length!'; - - var $map = createArrayMethod(1, function (O, length) { - return allocate(speciesConstructor(O, O[DEF_CONSTRUCTOR]), length); - }); + var min = Math.min; + var _toLength = function (it) { + return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 + }; - var LITTLE_ENDIAN = fails(function () { - // eslint-disable-next-line no-undef - return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1; - }); + var _createProperty = function (object, index, value) { + if (index in object) _objectDp.f(object, index, _propertyDesc(0, value)); + else object[index] = value; + }; - var FORCED_SET = !!Uint8Array && !!Uint8Array[PROTOTYPE].set && fails(function () { - new Uint8Array(1).set({}); - }); + var toString = {}.toString; - var toOffset = function (it, BYTES) { - var offset = toInteger(it); - if (offset < 0 || offset % BYTES) throw RangeError('Wrong offset!'); - return offset; + var _cof = function (it) { + return toString.call(it).slice(8, -1); }; - var validate = function (it) { - if (isObject(it) && TYPED_ARRAY in it) return it; - throw TypeError(it + ' is not a typed array!'); - }; + // getting tag from 19.1.3.6 Object.prototype.toString() - var allocate = function (C, length) { - if (!(isObject(C) && TYPED_CONSTRUCTOR in C)) { - throw TypeError('It is not a typed array constructor!'); - } return new C(length); - }; + var TAG = _wks('toStringTag'); + // ES3 wrong here + var ARG = _cof(function () { return arguments; }()) == 'Arguments'; - var speciesFromList = function (O, list) { - return fromList(speciesConstructor(O, O[DEF_CONSTRUCTOR]), list); + // fallback for IE11 Script Access Denied error + var tryGet = function (it, key) { + try { + return it[key]; + } catch (e) { /* empty */ } }; - var fromList = function (C, list) { - var index = 0; - var length = list.length; - var result = allocate(C, length); - while (length > index) result[index] = list[index++]; - return result; + var _classof = function (it) { + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? _cof(O) + // ES3 arguments fallback + : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; }; - var addGetter = function (it, key, internal) { - dP(it, key, { get: function () { return this._d[internal]; } }); - }; + var ITERATOR$1 = _wks('iterator'); - var $from = function from(source /* , mapfn, thisArg */) { - var O = toObject(source); - var aLen = arguments.length; - var mapfn = aLen > 1 ? arguments[1] : undefined; - var mapping = mapfn !== undefined; - var iterFn = getIterFn(O); - var i, length, values, result, step, iterator; - if (iterFn != undefined && !isArrayIter(iterFn)) { - for (iterator = iterFn.call(O), values = [], i = 0; !(step = iterator.next()).done; i++) { - values.push(step.value); - } O = values; - } - if (mapping && aLen > 2) mapfn = ctx(mapfn, arguments[2], 2); - for (i = 0, length = toLength(O.length), result = allocate(this, length); length > i; i++) { - result[i] = mapping ? mapfn(O[i], i) : O[i]; - } - return result; + var core_getIteratorMethod = _core.getIteratorMethod = function (it) { + if (it != undefined) return it[ITERATOR$1] + || it['@@iterator'] + || _iterators[_classof(it)]; }; - var $of = function of(/* ...items */) { - var index = 0; - var length = arguments.length; - var result = allocate(this, length); - while (length > index) result[index] = arguments[index++]; - return result; - }; + var ITERATOR$2 = _wks('iterator'); + var SAFE_CLOSING = false; - // iOS Safari 6.x fails here - var TO_LOCALE_BUG = !!Uint8Array && fails(function () { arrayToLocaleString.call(new Uint8Array(1)); }); + try { + var riter = [7][ITERATOR$2](); + riter['return'] = function () { SAFE_CLOSING = true; }; + } catch (e) { /* empty */ } - var $toLocaleString = function toLocaleString() { - return arrayToLocaleString.apply(TO_LOCALE_BUG ? arraySlice.call(validate(this)) : validate(this), arguments); + var _iterDetect = function (exec, skipClosing) { + if (!skipClosing && !SAFE_CLOSING) return false; + var safe = false; + try { + var arr = [7]; + var iter = arr[ITERATOR$2](); + iter.next = function () { return { done: safe = true }; }; + arr[ITERATOR$2] = function () { return iter; }; + exec(arr); + } catch (e) { /* empty */ } + return safe; }; - var proto = { - copyWithin: function copyWithin(target, start /* , end */) { - return arrayCopyWithin.call(validate(this), target, start, arguments.length > 2 ? arguments[2] : undefined); - }, - every: function every(callbackfn /* , thisArg */) { - return arrayEvery(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); - }, - fill: function fill(value /* , start, end */) { // eslint-disable-line no-unused-vars - return arrayFill.apply(validate(this), arguments); - }, - filter: function filter(callbackfn /* , thisArg */) { - return speciesFromList(this, arrayFilter(validate(this), callbackfn, - arguments.length > 1 ? arguments[1] : undefined)); - }, - find: function find(predicate /* , thisArg */) { - return arrayFind(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined); - }, - findIndex: function findIndex(predicate /* , thisArg */) { - return arrayFindIndex(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined); - }, - forEach: function forEach(callbackfn /* , thisArg */) { - arrayForEach(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); - }, - indexOf: function indexOf(searchElement /* , fromIndex */) { - return arrayIndexOf(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); - }, - includes: function includes(searchElement /* , fromIndex */) { - return arrayIncludes(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); - }, - join: function join(separator) { // eslint-disable-line no-unused-vars - return arrayJoin.apply(validate(this), arguments); - }, - lastIndexOf: function lastIndexOf(searchElement /* , fromIndex */) { // eslint-disable-line no-unused-vars - return arrayLastIndexOf.apply(validate(this), arguments); - }, - map: function map(mapfn /* , thisArg */) { - return $map(validate(this), mapfn, arguments.length > 1 ? arguments[1] : undefined); - }, - reduce: function reduce(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars - return arrayReduce.apply(validate(this), arguments); - }, - reduceRight: function reduceRight(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars - return arrayReduceRight.apply(validate(this), arguments); - }, - reverse: function reverse() { - var that = this; - var length = validate(that).length; - var middle = Math.floor(length / 2); + _export(_export.S + _export.F * !_iterDetect(function (iter) { }), 'Array', { + // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) + from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { + var O = _toObject(arrayLike); + var C = typeof this == 'function' ? this : Array; + var aLen = arguments.length; + var mapfn = aLen > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; var index = 0; - var value; - while (index < middle) { - value = that[index]; - that[index++] = that[--length]; - that[length] = value; - } return that; - }, - some: function some(callbackfn /* , thisArg */) { - return arraySome(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); - }, - sort: function sort(comparefn) { - return arraySort.call(validate(this), comparefn); - }, - subarray: function subarray(begin, end) { - var O = validate(this); - var length = O.length; - var $begin = toAbsoluteIndex(begin, length); - return new (speciesConstructor(O, O[DEF_CONSTRUCTOR]))( - O.buffer, - O.byteOffset + $begin * O.BYTES_PER_ELEMENT, - toLength((end === undefined ? length : toAbsoluteIndex(end, length)) - $begin) - ); + var iterFn = core_getIteratorMethod(O); + var length, result, step, iterator; + if (mapping) mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); + // if object isn't iterable or it's array with default iterator - use simple case + if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) { + for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) { + _createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value); + } + } else { + length = _toLength(O.length); + for (result = new C(length); length > index; index++) { + _createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); + } + } + result.length = index; + return result; } - }; + }); - var $slice = function slice(start, end) { - return speciesFromList(this, arraySlice.call(validate(this), start, end)); - }; + // fallback for non-array-like ES3 and non-enumerable old V8 strings - var $set = function set(arrayLike /* , offset */) { - validate(this); - var offset = toOffset(arguments[1], 1); - var length = this.length; - var src = toObject(arrayLike); - var len = toLength(src.length); - var index = 0; - if (len + offset > length) throw RangeError(WRONG_LENGTH); - while (index < len) this[offset + index] = src[index++]; + // eslint-disable-next-line no-prototype-builtins + var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return _cof(it) == 'String' ? it.split('') : Object(it); }; - var $iterators = { - entries: function entries() { - return arrayEntries.call(validate(this)); - }, - keys: function keys() { - return arrayKeys.call(validate(this)); - }, - values: function values() { - return arrayValues.call(validate(this)); - } + // 7.2.2 IsArray(argument) + + var _isArray = Array.isArray || function isArray(arg) { + return _cof(arg) == 'Array'; }; - var isTAIndex = function (target, key) { - return isObject(target) - && target[TYPED_ARRAY] - && typeof key != 'symbol' - && key in target - && String(+key) == String(key); - }; - var $getDesc = function getOwnPropertyDescriptor(target, key) { - return isTAIndex(target, key = toPrimitive(key, true)) - ? propertyDesc(2, target[key]) - : gOPD(target, key); - }; - var $setDesc = function defineProperty(target, key, desc) { - if (isTAIndex(target, key = toPrimitive(key, true)) - && isObject(desc) - && has(desc, 'value') - && !has(desc, 'get') - && !has(desc, 'set') - // TODO: add validation descriptor w/o calling accessors - && !desc.configurable - && (!has(desc, 'writable') || desc.writable) - && (!has(desc, 'enumerable') || desc.enumerable) - ) { - target[key] = desc.value; - return target; - } return dP(target, key, desc); + var SPECIES = _wks('species'); + + var _arraySpeciesConstructor = function (original) { + var C; + if (_isArray(original)) { + C = original.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) C = undefined; + if (_isObject(C)) { + C = C[SPECIES]; + if (C === null) C = undefined; + } + } return C === undefined ? Array : C; }; - if (!ALL_CONSTRUCTORS) { - $GOPD.f = $getDesc; - $DP.f = $setDesc; - } + // 9.4.2.3 ArraySpeciesCreate(originalArray, length) - $export($export.S + $export.F * !ALL_CONSTRUCTORS, 'Object', { - getOwnPropertyDescriptor: $getDesc, - defineProperty: $setDesc - }); - if (fails(function () { arrayToString.call({}); })) { - arrayToString = arrayToLocaleString = function toString() { - return arrayJoin.call(this); - }; - } + var _arraySpeciesCreate = function (original, length) { + return new (_arraySpeciesConstructor(original))(length); + }; - var $TypedArrayPrototype$ = redefineAll({}, proto); - redefineAll($TypedArrayPrototype$, $iterators); - hide($TypedArrayPrototype$, ITERATOR, $iterators.values); - redefineAll($TypedArrayPrototype$, { - slice: $slice, - set: $set, - constructor: function () { /* noop */ }, - toString: arrayToString, - toLocaleString: $toLocaleString - }); - addGetter($TypedArrayPrototype$, 'buffer', 'b'); - addGetter($TypedArrayPrototype$, 'byteOffset', 'o'); - addGetter($TypedArrayPrototype$, 'byteLength', 'l'); - addGetter($TypedArrayPrototype$, 'length', 'e'); - dP($TypedArrayPrototype$, TAG, { - get: function () { return this[TYPED_ARRAY]; } - }); + // 0 -> Array#forEach + // 1 -> Array#map + // 2 -> Array#filter + // 3 -> Array#some + // 4 -> Array#every + // 5 -> Array#find + // 6 -> Array#findIndex - // eslint-disable-next-line max-statements - module.exports = function (KEY, BYTES, wrapper, CLAMPED) { - CLAMPED = !!CLAMPED; - var NAME = KEY + (CLAMPED ? 'Clamped' : '') + 'Array'; - var GETTER = 'get' + KEY; - var SETTER = 'set' + KEY; - var TypedArray = global[NAME]; - var Base = TypedArray || {}; - var TAC = TypedArray && getPrototypeOf(TypedArray); - var FORCED = !TypedArray || !$typed.ABV; - var O = {}; - var TypedArrayPrototype = TypedArray && TypedArray[PROTOTYPE]; - var getter = function (that, index) { - var data = that._d; - return data.v[GETTER](index * BYTES + data.o, LITTLE_ENDIAN); - }; - var setter = function (that, index, value) { - var data = that._d; - if (CLAMPED) value = (value = Math.round(value)) < 0 ? 0 : value > 0xff ? 0xff : value & 0xff; - data.v[SETTER](index * BYTES + data.o, value, LITTLE_ENDIAN); - }; - var addElement = function (that, index) { - dP(that, index, { - get: function () { - return getter(this, index); - }, - set: function (value) { - return setter(this, index, value); - }, - enumerable: true - }); - }; - if (FORCED) { - TypedArray = wrapper(function (that, data, $offset, $length) { - anInstance(that, TypedArray, NAME, '_d'); - var index = 0; - var offset = 0; - var buffer, byteLength, length, klass; - if (!isObject(data)) { - length = toIndex(data); - byteLength = length * BYTES; - buffer = new $ArrayBuffer(byteLength); - } else if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) { - buffer = data; - offset = toOffset($offset, BYTES); - var $len = data.byteLength; - if ($length === undefined) { - if ($len % BYTES) throw RangeError(WRONG_LENGTH); - byteLength = $len - offset; - if (byteLength < 0) throw RangeError(WRONG_LENGTH); - } else { - byteLength = toLength($length) * BYTES; - if (byteLength + offset > $len) throw RangeError(WRONG_LENGTH); - } - length = byteLength / BYTES; - } else if (TYPED_ARRAY in data) { - return fromList(TypedArray, data); - } else { - return $from.call(TypedArray, data); - } - hide(that, '_d', { - b: buffer, - o: offset, - l: byteLength, - e: length, - v: new $DataView(buffer) - }); - while (index < length) addElement(that, index++); - }); - TypedArrayPrototype = TypedArray[PROTOTYPE] = create($TypedArrayPrototype$); - hide(TypedArrayPrototype, 'constructor', TypedArray); - } else if (!fails(function () { - TypedArray(1); - }) || !fails(function () { - new TypedArray(-1); // eslint-disable-line no-new - }) || !$iterDetect(function (iter) { - new TypedArray(); // eslint-disable-line no-new - new TypedArray(null); // eslint-disable-line no-new - new TypedArray(1.5); // eslint-disable-line no-new - new TypedArray(iter); // eslint-disable-line no-new - }, true)) { - TypedArray = wrapper(function (that, data, $offset, $length) { - anInstance(that, TypedArray, NAME); - var klass; - // `ws` module bug, temporarily remove validation length for Uint8Array - // https://github.com/websockets/ws/pull/645 - if (!isObject(data)) return new Base(toIndex(data)); - if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) { - return $length !== undefined - ? new Base(data, toOffset($offset, BYTES), $length) - : $offset !== undefined - ? new Base(data, toOffset($offset, BYTES)) - : new Base(data); - } - if (TYPED_ARRAY in data) return fromList(TypedArray, data); - return $from.call(TypedArray, data); - }); - arrayForEach(TAC !== Function.prototype ? gOPN(Base).concat(gOPN(TAC)) : gOPN(Base), function (key) { - if (!(key in TypedArray)) hide(TypedArray, key, Base[key]); - }); - TypedArray[PROTOTYPE] = TypedArrayPrototype; - if (!LIBRARY) TypedArrayPrototype.constructor = TypedArray; - } - var $nativeIterator = TypedArrayPrototype[ITERATOR]; - var CORRECT_ITER_NAME = !!$nativeIterator - && ($nativeIterator.name == 'values' || $nativeIterator.name == undefined); - var $iterator = $iterators.values; - hide(TypedArray, TYPED_CONSTRUCTOR, true); - hide(TypedArrayPrototype, TYPED_ARRAY, NAME); - hide(TypedArrayPrototype, VIEW, true); - hide(TypedArrayPrototype, DEF_CONSTRUCTOR, TypedArray); - - if (CLAMPED ? new TypedArray(1)[TAG] != NAME : !(TAG in TypedArrayPrototype)) { - dP(TypedArrayPrototype, TAG, { - get: function () { return NAME; } - }); - } - - O[NAME] = TypedArray; - $export($export.G + $export.W + $export.F * (TypedArray != Base), O); - $export($export.S, NAME, { - BYTES_PER_ELEMENT: BYTES - }); - $export($export.S + $export.F * fails(function () { Base.of.call(TypedArray, 1); }), NAME, { - from: $from, - of: $of - }); - if (!(BYTES_PER_ELEMENT in TypedArrayPrototype)) hide(TypedArrayPrototype, BYTES_PER_ELEMENT, BYTES); + var _arrayMethods = function (TYPE, $create) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + var create = $create || _arraySpeciesCreate; + return function ($this, callbackfn, that) { + var O = _toObject($this); + var self = _iobject(O); + var f = _ctx(callbackfn, that, 3); + var length = _toLength(self.length); + var index = 0; + var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined; + var val, res; + for (;length > index; index++) if (NO_HOLES || index in self) { + val = self[index]; + res = f(val, index, O); + if (TYPE) { + if (IS_MAP) result[index] = res; // map + else if (res) switch (TYPE) { + case 3: return true; // some + case 5: return val; // find + case 6: return index; // findIndex + case 2: result.push(val); // filter + } else if (IS_EVERY) return false; // every + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; + }; + }; - $export($export.P, NAME, proto); + // 22.1.3.31 Array.prototype[@@unscopables] + var UNSCOPABLES = _wks('unscopables'); + var ArrayProto$1 = Array.prototype; + if (ArrayProto$1[UNSCOPABLES] == undefined) _hide(ArrayProto$1, UNSCOPABLES, {}); + var _addToUnscopables = function (key) { + ArrayProto$1[UNSCOPABLES][key] = true; + }; - setSpecies(NAME); + // 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined) - $export($export.P + $export.F * FORCED_SET, NAME, { set: $set }); + var $find = _arrayMethods(5); + var KEY = 'find'; + var forced = true; + // Shouldn't skip holes + if (KEY in []) Array(1)[KEY](function () { forced = false; }); + _export(_export.P + _export.F * forced, 'Array', { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + _addToUnscopables(KEY); - $export($export.P + $export.F * !CORRECT_ITER_NAME, NAME, $iterators); + var f$1 = {}.propertyIsEnumerable; - if (!LIBRARY && TypedArrayPrototype.toString != arrayToString) TypedArrayPrototype.toString = arrayToString; + var _objectPie = { + f: f$1 + }; - $export($export.P + $export.F * fails(function () { - new TypedArray(1).slice(); - }), NAME, { slice: $slice }); + // to indexed object, toObject with fallback for non-array-like ES3 strings - $export($export.P + $export.F * (fails(function () { - return [1, 2].toLocaleString() != new TypedArray([1, 2]).toLocaleString(); - }) || !fails(function () { - TypedArrayPrototype.toLocaleString.call([1, 2]); - })), NAME, { toLocaleString: $toLocaleString }); - Iterators[NAME] = CORRECT_ITER_NAME ? $nativeIterator : $iterator; - if (!LIBRARY && !CORRECT_ITER_NAME) hide(TypedArrayPrototype, ITERATOR, $iterator); + var _toIobject = function (it) { + return _iobject(_defined(it)); }; -} else module.exports = function () { /* empty */ }; -}); -_typedArray('Int8', 1, function (init) { - return function Int8Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); - }; -}); + var gOPD = Object.getOwnPropertyDescriptor; -_typedArray('Uint8', 1, function (init) { - return function Uint8Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var f$2 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) { + O = _toIobject(O); + P = _toPrimitive(P, true); + if (_ie8DomDefine) try { + return gOPD(O, P); + } catch (e) { /* empty */ } + if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]); }; -}); -_typedArray('Uint8', 1, function (init) { - return function Uint8ClampedArray(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var _objectGopd = { + f: f$2 }; -}, true); -_typedArray('Int16', 2, function (init) { - return function Int16Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); - }; -}); + // Works with __proto__ only. Old v8 can't work with null proto objects. + /* eslint-disable no-proto */ -_typedArray('Uint16', 2, function (init) { - return function Uint16Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); - }; -}); -_typedArray('Int32', 4, function (init) { - return function Int32Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var check = function (O, proto) { + _anObject(O); + if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); }; -}); - -_typedArray('Uint32', 4, function (init) { - return function Uint32Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var _setProto = { + set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line + function (test, buggy, set) { + try { + set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2); + set(test, []); + buggy = !(test instanceof Array); + } catch (e) { buggy = true; } + return function setPrototypeOf(O, proto) { + check(O, proto); + if (buggy) O.__proto__ = proto; + else set(O, proto); + return O; + }; + }({}, false) : undefined), + check: check }; -}); -_typedArray('Float32', 4, function (init) { - return function Float32Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var setPrototypeOf = _setProto.set; + var _inheritIfRequired = function (that, target, C) { + var S = target.constructor; + var P; + if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf) { + setPrototypeOf(that, P); + } return that; }; -}); -_typedArray('Float64', 8, function (init) { - return function Float64Array(data, byteOffset, length) { - return init(this, data, byteOffset, length); + var max = Math.max; + var min$1 = Math.min; + var _toAbsoluteIndex = function (index, length) { + index = _toInteger(index); + return index < 0 ? max(index + length, 0) : min$1(index, length); }; -}); -// call something on iterator step with safe closing on error + // false -> Array#indexOf + // true -> Array#includes -var _iterCall = function (iterator, fn, value, entries) { - try { - return entries ? fn(_anObject(value)[0], value[1]) : fn(value); - // 7.4.6 IteratorClose(iterator, completion) - } catch (e) { - var ret = iterator['return']; - if (ret !== undefined) _anObject(ret.call(iterator)); - throw e; - } -}; - -var _forOf = createCommonjsModule(function (module) { -var BREAK = {}; -var RETURN = {}; -var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { - var iterFn = ITERATOR ? function () { return iterable; } : core_getIteratorMethod(iterable); - var f = _ctx(fn, that, entries ? 2 : 1); - var index = 0; - var length, step, iterator, result; - if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); - // fast case for arrays with default iterator - if (_isArrayIter(iterFn)) for (length = _toLength(iterable.length); length > index; index++) { - result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); - if (result === BREAK || result === RETURN) return result; - } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { - result = _iterCall(iterator, f, step.value, entries); - if (result === BREAK || result === RETURN) return result; - } -}; -exports.BREAK = BREAK; -exports.RETURN = RETURN; -}); - -var _meta = createCommonjsModule(function (module) { -var META = _uid('meta'); - - -var setDesc = _objectDp.f; -var id = 0; -var isExtensible = Object.isExtensible || function () { - return true; -}; -var FREEZE = !_fails(function () { - return isExtensible(Object.preventExtensions({})); -}); -var setMeta = function (it) { - setDesc(it, META, { value: { - i: 'O' + ++id, // object ID - w: {} // weak collections IDs - } }); -}; -var fastKey = function (it, create) { - // return primitive with prefix - if (!_isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; - if (!_has(it, META)) { - // can't set metadata to uncaught frozen object - if (!isExtensible(it)) return 'F'; - // not necessary to add metadata - if (!create) return 'E'; - // add missing metadata - setMeta(it); - // return object ID - } return it[META].i; -}; -var getWeak = function (it, create) { - if (!_has(it, META)) { - // can't set metadata to uncaught frozen object - if (!isExtensible(it)) return true; - // not necessary to add metadata - if (!create) return false; - // add missing metadata - setMeta(it); - // return hash weak collections IDs - } return it[META].w; -}; -// add metadata on freeze-family methods calling -var onFreeze = function (it) { - if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it); - return it; -}; -var meta = module.exports = { - KEY: META, - NEED: false, - fastKey: fastKey, - getWeak: getWeak, - onFreeze: onFreeze -}; -}); -var _meta_1 = _meta.KEY; -var _meta_2 = _meta.NEED; -var _meta_3 = _meta.fastKey; -var _meta_4 = _meta.getWeak; -var _meta_5 = _meta.onFreeze; - -var _validateCollection = function (it, TYPE) { - if (!_isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); - return it; -}; - -var dP$1 = _objectDp.f; - - - - - - - - - -var fastKey = _meta.fastKey; - -var SIZE = _descriptors ? '_s' : 'size'; - -var getEntry = function (that, key) { - // fast case - var index = fastKey(key); - var entry; - if (index !== 'F') return that._i[index]; - // frozen object case - for (entry = that._f; entry; entry = entry.n) { - if (entry.k == key) return entry; - } -}; - -var _collectionStrong = { - getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { - var C = wrapper(function (that, iterable) { - _anInstance(that, C, NAME, '_i'); - that._t = NAME; // collection type - that._i = _objectCreate(null); // index - that._f = undefined; // first entry - that._l = undefined; // last entry - that[SIZE] = 0; // size - if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); - }); - _redefineAll(C.prototype, { - // 23.1.3.1 Map.prototype.clear() - // 23.2.3.2 Set.prototype.clear() - clear: function clear() { - for (var that = _validateCollection(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) { - entry.r = true; - if (entry.p) entry.p = entry.p.n = undefined; - delete data[entry.i]; - } - that._f = that._l = undefined; - that[SIZE] = 0; - }, - // 23.1.3.3 Map.prototype.delete(key) - // 23.2.3.4 Set.prototype.delete(value) - 'delete': function (key) { - var that = _validateCollection(this, NAME); - var entry = getEntry(that, key); - if (entry) { - var next = entry.n; - var prev = entry.p; - delete that._i[entry.i]; - entry.r = true; - if (prev) prev.n = next; - if (next) next.p = prev; - if (that._f == entry) that._f = next; - if (that._l == entry) that._l = prev; - that[SIZE]--; - } return !!entry; - }, - // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) - // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) - forEach: function forEach(callbackfn /* , that = undefined */) { - _validateCollection(this, NAME); - var f = _ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3); - var entry; - while (entry = entry ? entry.n : this._f) { - f(entry.v, entry.k, this); - // revert to the last existing entry - while (entry && entry.r) entry = entry.p; - } - }, - // 23.1.3.7 Map.prototype.has(key) - // 23.2.3.7 Set.prototype.has(value) - has: function has(key) { - return !!getEntry(_validateCollection(this, NAME), key); - } - }); - if (_descriptors) dP$1(C.prototype, 'size', { - get: function () { - return _validateCollection(this, NAME)[SIZE]; - } - }); - return C; - }, - def: function (that, key, value) { - var entry = getEntry(that, key); - var prev, index; - // change existing entry - if (entry) { - entry.v = value; - // create new entry - } else { - that._l = entry = { - i: index = fastKey(key, true), // <- index - k: key, // <- key - v: value, // <- value - p: prev = that._l, // <- previous entry - n: undefined, // <- next entry - r: false // <- removed - }; - if (!that._f) that._f = entry; - if (prev) prev.n = entry; - that[SIZE]++; - // add to index - if (index !== 'F') that._i[index] = entry; - } return that; - }, - getEntry: getEntry, - setStrong: function (C, NAME, IS_MAP) { - // add .keys, .values, .entries, [@@iterator] - // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 - _iterDefine(C, NAME, function (iterated, kind) { - this._t = _validateCollection(iterated, NAME); // target - this._k = kind; // kind - this._l = undefined; // previous - }, function () { - var that = this; - var kind = that._k; - var entry = that._l; - // revert to the last existing entry - while (entry && entry.r) entry = entry.p; - // get next entry - if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) { - // or finish the iteration - that._t = undefined; - return _iterStep(1); - } - // return step by kind - if (kind == 'keys') return _iterStep(0, entry.k); - if (kind == 'values') return _iterStep(0, entry.v); - return _iterStep(0, [entry.k, entry.v]); - }, IS_MAP ? 'entries' : 'values', !IS_MAP, true); - - // add [@@species], 23.1.2.2, 23.2.2.2 - _setSpecies(NAME); - } -}; - -// Works with __proto__ only. Old v8 can't work with null proto objects. -/* eslint-disable no-proto */ -var check = function (O, proto) { - _anObject(O); - if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); -}; -var _setProto = { - set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line - function (test, buggy, set) { - try { - set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2); - set(test, []); - buggy = !(test instanceof Array); - } catch (e) { buggy = true; } - return function setPrototypeOf(O, proto) { - check(O, proto); - if (buggy) O.__proto__ = proto; - else set(O, proto); - return O; - }; - }({}, false) : undefined), - check: check -}; - -var setPrototypeOf = _setProto.set; -var _inheritIfRequired = function (that, target, C) { - var S = target.constructor; - var P; - if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf) { - setPrototypeOf(that, P); - } return that; -}; - -var _collection = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { - var Base = _global[NAME]; - var C = Base; - var ADDER = IS_MAP ? 'set' : 'add'; - var proto = C && C.prototype; - var O = {}; - var fixMethod = function (KEY) { - var fn = proto[KEY]; - _redefine(proto, KEY, - KEY == 'delete' ? function (a) { - return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); - } : KEY == 'has' ? function has(a) { - return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); - } : KEY == 'get' ? function get(a) { - return IS_WEAK && !_isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); - } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; } - : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; } - ); - }; - if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () { - new C().entries().next(); - }))) { - // create collection constructor - C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); - _redefineAll(C.prototype, methods); - _meta.NEED = true; - } else { - var instance = new C(); - // early implementations not supports chaining - var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; - // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false - var THROWS_ON_PRIMITIVES = _fails(function () { instance.has(1); }); - // most early implementations doesn't supports iterables, most modern - not close it correctly - var ACCEPT_ITERABLES = _iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new - // for early implementations -0 and +0 not the same - var BUGGY_ZERO = !IS_WEAK && _fails(function () { - // V8 ~ Chromium 42- fails only with 5+ elements - var $instance = new C(); - var index = 5; - while (index--) $instance[ADDER](index, index); - return !$instance.has(-0); - }); - if (!ACCEPT_ITERABLES) { - C = wrapper(function (target, iterable) { - _anInstance(target, C, NAME); - var that = _inheritIfRequired(new Base(), target, C); - if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); - return that; - }); - C.prototype = proto; - proto.constructor = C; - } - if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { - fixMethod('delete'); - fixMethod('has'); - IS_MAP && fixMethod('get'); - } - if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); - // weak collections should not contains .clear method - if (IS_WEAK && proto.clear) delete proto.clear; - } - - _setToStringTag(C, NAME); - - O[NAME] = C; - _export(_export.G + _export.W + _export.F * (C != Base), O); - - if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP); + var _arrayIncludes = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = _toIobject($this); + var length = _toLength(O.length); + var index = _toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; - return C; -}; + var shared = _shared('keys'); -var MAP = 'Map'; + var _sharedKey = function (key) { + return shared[key] || (shared[key] = _uid(key)); + }; -// 23.1 Map Objects -var es6_map = _collection(MAP, function (get) { - return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.1.3.6 Map.prototype.get(key) - get: function get(key) { - var entry = _collectionStrong.getEntry(_validateCollection(this, MAP), key); - return entry && entry.v; - }, - // 23.1.3.9 Map.prototype.set(key, value) - set: function set(key, value) { - return _collectionStrong.def(_validateCollection(this, MAP), key === 0 ? 0 : key, value); - } -}, _collectionStrong, true); + var arrayIndexOf = _arrayIncludes(false); + var IE_PROTO = _sharedKey('IE_PROTO'); -var SET = 'Set'; + var _objectKeysInternal = function (object, names) { + var O = _toIobject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) _has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (_has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; + }; -// 23.2 Set Objects -var es6_set = _collection(SET, function (get) { - return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.2.3.1 Set.prototype.add(value) - add: function add(value) { - return _collectionStrong.def(_validateCollection(this, SET), value = value === 0 ? 0 : value, value); - } -}, _collectionStrong); + // IE 8- don't enum bug keys + var _enumBugKeys = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' + ).split(','); -var f$4 = Object.getOwnPropertySymbols; + // 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) -var _objectGops = { - f: f$4 -}; + var hiddenKeys = _enumBugKeys.concat('length', 'prototype'); -// 19.1.2.1 Object.assign(target, source, ...) + var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return _objectKeysInternal(O, hiddenKeys); + }; + var _objectGopn = { + f: f$3 + }; + var _stringWs = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; + var space = '[' + _stringWs + ']'; + var non = '\u200b\u0085'; + var ltrim = RegExp('^' + space + space + '*'); + var rtrim = RegExp(space + space + '*$'); + var exporter = function (KEY, exec, ALIAS) { + var exp = {}; + var FORCE = _fails(function () { + return !!_stringWs[KEY]() || non[KEY]() != non; + }); + var fn = exp[KEY] = FORCE ? exec(trim) : _stringWs[KEY]; + if (ALIAS) exp[ALIAS] = fn; + _export(_export.P + _export.F * FORCE, 'String', exp); + }; -var $assign = Object.assign; + // 1 -> String#trimLeft + // 2 -> String#trimRight + // 3 -> String#trim + var trim = exporter.trim = function (string, TYPE) { + string = String(_defined(string)); + if (TYPE & 1) string = string.replace(ltrim, ''); + if (TYPE & 2) string = string.replace(rtrim, ''); + return string; + }; -// should work with symbols and should have deterministic property order (V8 bug) -var _objectAssign = !$assign || _fails(function () { - var A = {}; - var B = {}; - // eslint-disable-next-line no-undef - var S = Symbol(); - var K = 'abcdefghijklmnopqrst'; - A[S] = 7; - K.split('').forEach(function (k) { B[k] = k; }); - return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; -}) ? function assign(target, source) { // eslint-disable-line no-unused-vars - var T = _toObject(target); - var aLen = arguments.length; - var index = 1; - var getSymbols = _objectGops.f; - var isEnum = _objectPie.f; - while (aLen > index) { - var S = _iobject(arguments[index++]); - var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S); - var length = keys.length; - var j = 0; - var key; - while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; - } return T; -} : $assign; + var _stringTrim = exporter; -var getWeak = _meta.getWeak; + // 19.1.2.14 / 15.2.3.14 Object.keys(O) + var _objectKeys = Object.keys || function keys(O) { + return _objectKeysInternal(O, _enumBugKeys); + }; + var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) { + _anObject(O); + var keys = _objectKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) _objectDp.f(O, P = keys[i++], Properties[P]); + return O; + }; + var document$2 = _global.document; + var _html = document$2 && document$2.documentElement; + + // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) + + + + var IE_PROTO$1 = _sharedKey('IE_PROTO'); + var Empty = function () { /* empty */ }; + var PROTOTYPE$1 = 'prototype'; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = _domCreate('iframe'); + var i = _enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + _html.appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE$1][_enumBugKeys[i]]; + return createDict(); + }; + var _objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE$1] = _anObject(O); + result = new Empty(); + Empty[PROTOTYPE$1] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO$1] = O; + } else result = createDict(); + return Properties === undefined ? result : _objectDps(result, Properties); + }; -var arrayFind = _arrayMethods(5); -var arrayFindIndex = _arrayMethods(6); -var id$1 = 0; + var gOPN = _objectGopn.f; + var gOPD$1 = _objectGopd.f; + var dP$1 = _objectDp.f; + var $trim = _stringTrim.trim; + var NUMBER = 'Number'; + var $Number = _global[NUMBER]; + var Base = $Number; + var proto = $Number.prototype; + // Opera ~12 has broken Object#toString + var BROKEN_COF = _cof(_objectCreate(proto)) == NUMBER; + var TRIM = 'trim' in String.prototype; + + // 7.1.3 ToNumber(argument) + var toNumber = function (argument) { + var it = _toPrimitive(argument, false); + if (typeof it == 'string' && it.length > 2) { + it = TRIM ? it.trim() : $trim(it, 3); + var first = it.charCodeAt(0); + var third, radix, maxCode; + if (first === 43 || first === 45) { + third = it.charCodeAt(2); + if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix + } else if (first === 48) { + switch (it.charCodeAt(1)) { + case 66: case 98: radix = 2; maxCode = 49; break; // fast equal /^0b[01]+$/i + case 79: case 111: radix = 8; maxCode = 55; break; // fast equal /^0o[0-7]+$/i + default: return +it; + } + for (var digits = it.slice(2), i = 0, l = digits.length, code; i < l; i++) { + code = digits.charCodeAt(i); + // parseInt parses a string to a first unavailable symbol + // but ToNumber should return NaN if a string contains unavailable symbols + if (code < 48 || code > maxCode) return NaN; + } return parseInt(digits, radix); + } + } return +it; + }; -// fallback for uncaught frozen keys -var uncaughtFrozenStore = function (that) { - return that._l || (that._l = new UncaughtFrozenStore()); -}; -var UncaughtFrozenStore = function () { - this.a = []; -}; -var findUncaughtFrozen = function (store, key) { - return arrayFind(store.a, function (it) { - return it[0] === key; - }); -}; -UncaughtFrozenStore.prototype = { - get: function (key) { - var entry = findUncaughtFrozen(this, key); - if (entry) return entry[1]; - }, - has: function (key) { - return !!findUncaughtFrozen(this, key); - }, - set: function (key, value) { - var entry = findUncaughtFrozen(this, key); - if (entry) entry[1] = value; - else this.a.push([key, value]); - }, - 'delete': function (key) { - var index = arrayFindIndex(this.a, function (it) { - return it[0] === key; - }); - if (~index) this.a.splice(index, 1); - return !!~index; - } -}; - -var _collectionWeak = { - getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { - var C = wrapper(function (that, iterable) { - _anInstance(that, C, NAME, '_i'); - that._t = NAME; // collection type - that._i = id$1++; // collection id - that._l = undefined; // leak store for uncaught frozen objects - if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); - }); - _redefineAll(C.prototype, { - // 23.3.3.2 WeakMap.prototype.delete(key) - // 23.4.3.3 WeakSet.prototype.delete(value) - 'delete': function (key) { - if (!_isObject(key)) return false; - var data = getWeak(key); - if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key); - return data && _has(data, this._i) && delete data[this._i]; - }, - // 23.3.3.4 WeakMap.prototype.has(key) - // 23.4.3.4 WeakSet.prototype.has(value) - has: function has(key) { - if (!_isObject(key)) return false; - var data = getWeak(key); - if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key); - return data && _has(data, this._i); + if (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) { + $Number = function Number(value) { + var it = arguments.length < 1 ? 0 : value; + var that = this; + return that instanceof $Number + // check on 1..constructor(foo) case + && (BROKEN_COF ? _fails(function () { proto.valueOf.call(that); }) : _cof(that) != NUMBER) + ? _inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it); + }; + for (var keys = _descriptors ? gOPN(Base) : ( + // ES3: + 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + + // ES6 (in case, if modules with ES6 Number statics required before): + 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' + + 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger' + ).split(','), j = 0, key; keys.length > j; j++) { + if (_has(Base, key = keys[j]) && !_has($Number, key)) { + dP$1($Number, key, gOPD$1(Base, key)); } - }); - return C; - }, - def: function (that, key, value) { - var data = getWeak(_anObject(key), true); - if (data === true) uncaughtFrozenStore(that).set(key, value); - else data[that._i] = value; - return that; - }, - ufstore: uncaughtFrozenStore -}; + } + $Number.prototype = proto; + proto.constructor = $Number; + _redefine(_global, NUMBER, $Number); + } -var es6_weakMap = createCommonjsModule(function (module) { -var each = _arrayMethods(0); + // most Object methods by ES6 should accept primitives + var _objectSap = function (KEY, exec) { + var fn = (_core.Object || {})[KEY] || Object[KEY]; + var exp = {}; + exp[KEY] = exec(fn); + _export(_export.S + _export.F * _fails(function () { fn(1); }), 'Object', exp); + }; + // 19.1.2.14 Object.keys(O) -var WEAK_MAP = 'WeakMap'; -var getWeak = _meta.getWeak; -var isExtensible = Object.isExtensible; -var uncaughtFrozenStore = _collectionWeak.ufstore; -var tmp = {}; -var InternalMap; + _objectSap('keys', function () { + return function keys(it) { + return _objectKeys(_toObject(it)); + }; + }); -var wrapper = function (get) { - return function WeakMap() { - return get(this, arguments.length > 0 ? arguments[0] : undefined); - }; -}; + // 7.2.8 IsRegExp(argument) -var methods = { - // 23.3.3.3 WeakMap.prototype.get(key) - get: function get(key) { - if (_isObject(key)) { - var data = getWeak(key); - if (data === true) return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key); - return data ? data[this._i] : undefined; - } - }, - // 23.3.3.5 WeakMap.prototype.set(key, value) - set: function set(key, value) { - return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value); - } -}; - -// 23.3 WeakMap Objects -var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true); - -// IE11 WeakMap frozen keys fix -if (_fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { - InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP); - _objectAssign(InternalMap.prototype, methods); - _meta.NEED = true; - each(['delete', 'has', 'get', 'set'], function (key) { - var proto = $WeakMap.prototype; - var method = proto[key]; - _redefine(proto, key, function (a, b) { - // store frozen objects on internal weakmap shim - if (_isObject(a) && !isExtensible(a)) { - if (!this._f) this._f = new InternalMap(); - var result = this._f[key](a, b); - return key == 'set' ? this : result; - // store all the rest on native weakmap - } return method.call(this, a, b); - }); - }); -} -}); - -var WEAK_SET = 'WeakSet'; - -// 23.4 WeakSet Objects -_collection(WEAK_SET, function (get) { - return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.4.3.1 WeakSet.prototype.add(value) - add: function add(value) { - return _collectionWeak.def(_validateCollection(this, WEAK_SET), value, true); - } -}, _collectionWeak, false, true); -// 26.1.1 Reflect.apply(target, thisArgument, argumentsList) + var MATCH = _wks('match'); + var _isRegexp = function (it) { + var isRegExp; + return _isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : _cof(it) == 'RegExp'); + }; + // helper for String#{startsWith, endsWith, includes} -var rApply = (_global.Reflect || {}).apply; -var fApply = Function.apply; -// MS Edge argumentsList argument is optional -_export(_export.S + _export.F * !_fails(function () { - rApply(function () { /* empty */ }); -}), 'Reflect', { - apply: function apply(target, thisArgument, argumentsList) { - var T = _aFunction(target); - var L = _anObject(argumentsList); - return rApply ? rApply(T, thisArgument, L) : fApply.call(T, thisArgument, L); - } -}); - -// fast apply, http://jsperf.lnkit.com/fast-apply/5 -var _invoke = function (fn, args, that) { - var un = that === undefined; - switch (args.length) { - case 0: return un ? fn() - : fn.call(that); - case 1: return un ? fn(args[0]) - : fn.call(that, args[0]); - case 2: return un ? fn(args[0], args[1]) - : fn.call(that, args[0], args[1]); - case 3: return un ? fn(args[0], args[1], args[2]) - : fn.call(that, args[0], args[1], args[2]); - case 4: return un ? fn(args[0], args[1], args[2], args[3]) - : fn.call(that, args[0], args[1], args[2], args[3]); - } return fn.apply(that, args); -}; - -var arraySlice = [].slice; -var factories = {}; - -var construct = function (F, len, args) { - if (!(len in factories)) { - for (var n = [], i = 0; i < len; i++) n[i] = 'a[' + i + ']'; - // eslint-disable-next-line no-new-func - factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')'); - } return factories[len](F, args); -}; -var _bind = Function.bind || function bind(that /* , ...args */) { - var fn = _aFunction(this); - var partArgs = arraySlice.call(arguments, 1); - var bound = function (/* args... */) { - var args = partArgs.concat(arraySlice.call(arguments)); - return this instanceof bound ? construct(fn, args.length, args) : _invoke(fn, args, that); + var _stringContext = function (that, searchString, NAME) { + if (_isRegexp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!"); + return String(_defined(that)); }; - if (_isObject(fn.prototype)) bound.prototype = fn.prototype; - return bound; -}; -// 26.1.2 Reflect.construct(target, argumentsList [, newTarget]) + var MATCH$1 = _wks('match'); + var _failsIsRegexp = function (KEY) { + var re = /./; + try { + '/./'[KEY](re); + } catch (e) { + try { + re[MATCH$1] = false; + return !'/./'[KEY](re); + } catch (f) { /* empty */ } + } return true; + }; + var INCLUDES = 'includes'; + _export(_export.P + _export.F * _failsIsRegexp(INCLUDES), 'String', { + includes: function includes(searchString /* , position = 0 */) { + return !!~_stringContext(this, searchString, INCLUDES) + .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined); + } + }); + // https://github.com/tc39/Array.prototype.includes + var $includes = _arrayIncludes(true); + _export(_export.P, 'Array', { + includes: function includes(el /* , fromIndex = 0 */) { + return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); + } + }); + _addToUnscopables('includes'); -var rConstruct = (_global.Reflect || {}).construct; + // 7.2.9 SameValue(x, y) + var _sameValue = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare + return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; + }; -// MS Edge supports only 2 arguments and argumentsList argument is optional -// FF Nightly sets third argument as `new.target`, but does not create `this` from it -var NEW_TARGET_BUG = _fails(function () { - function F() { /* empty */ } - return !(rConstruct(function () { /* empty */ }, [], F) instanceof F); -}); -var ARGS_BUG = !_fails(function () { - rConstruct(function () { /* empty */ }); -}); + var builtinExec = RegExp.prototype.exec; -_export(_export.S + _export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', { - construct: function construct(Target, args /* , newTarget */) { - _aFunction(Target); - _anObject(args); - var newTarget = arguments.length < 3 ? Target : _aFunction(arguments[2]); - if (ARGS_BUG && !NEW_TARGET_BUG) return rConstruct(Target, args, newTarget); - if (Target == newTarget) { - // w/o altered newTarget, optimization for 0-4 arguments - switch (args.length) { - case 0: return new Target(); - case 1: return new Target(args[0]); - case 2: return new Target(args[0], args[1]); - case 3: return new Target(args[0], args[1], args[2]); - case 4: return new Target(args[0], args[1], args[2], args[3]); + // `RegExpExec` abstract operation + // https://tc39.github.io/ecma262/#sec-regexpexec + var _regexpExecAbstract = function (R, S) { + var exec = R.exec; + if (typeof exec === 'function') { + var result = exec.call(R, S); + if (typeof result !== 'object') { + throw new TypeError('RegExp exec method returned something other than an Object or null'); } - // w/o altered newTarget, lot of arguments case - var $args = [null]; - $args.push.apply($args, args); - return new (_bind.apply(Target, $args))(); + return result; } - // with altered newTarget, not support built-in constructors - var proto = newTarget.prototype; - var instance = _objectCreate(_isObject(proto) ? proto : Object.prototype); - var result = Function.apply.call(Target, instance, args); - return _isObject(result) ? result : instance; - } -}); - -// 26.1.3 Reflect.defineProperty(target, propertyKey, attributes) + if (_classof(R) !== 'RegExp') { + throw new TypeError('RegExp#exec called on incompatible receiver'); + } + return builtinExec.call(R, S); + }; + // 21.2.5.3 get RegExp.prototype.flags + var _flags = function () { + var that = _anObject(this); + var result = ''; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.unicode) result += 'u'; + if (that.sticky) result += 'y'; + return result; + }; + var nativeExec = RegExp.prototype.exec; + // This always refers to the native implementation, because the + // String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js, + // which loads this file before patching the method. + var nativeReplace = String.prototype.replace; + var patchedExec = nativeExec; -// MS Edge has broken Reflect.defineProperty - throwing instead of returning false -_export(_export.S + _export.F * _fails(function () { - // eslint-disable-next-line no-undef - Reflect.defineProperty(_objectDp.f({}, 1, { value: 1 }), 1, { value: 2 }); -}), 'Reflect', { - defineProperty: function defineProperty(target, propertyKey, attributes) { - _anObject(target); - propertyKey = _toPrimitive(propertyKey, true); - _anObject(attributes); - try { - _objectDp.f(target, propertyKey, attributes); - return true; - } catch (e) { - return false; - } - } -}); + var LAST_INDEX = 'lastIndex'; -// 26.1.4 Reflect.deleteProperty(target, propertyKey) + var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/, + re2 = /b*/g; + nativeExec.call(re1, 'a'); + nativeExec.call(re2, 'a'); + return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0; + })(); -var gOPD$1 = _objectGopd.f; + // nonparticipating capturing group, copied from es5-shim's String#split patch. + var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED; -_export(_export.S, 'Reflect', { - deleteProperty: function deleteProperty(target, propertyKey) { - var desc = gOPD$1(_anObject(target), propertyKey); - return desc && !desc.configurable ? false : delete target[propertyKey]; - } -}); + if (PATCH) { + patchedExec = function exec(str) { + var re = this; + var lastIndex, reCopy, match, i; -// 26.1.6 Reflect.get(target, propertyKey [, receiver]) + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + re.source + '$(?!\\s)', _flags.call(re)); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX]; + match = nativeExec.call(re, str); + if (UPDATES_LAST_INDEX_WRONG && match) { + re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/ + // eslint-disable-next-line no-loop-func + nativeReplace.call(match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; + } + }); + } + return match; + }; + } + var _regexpExec = patchedExec; + _export({ + target: 'RegExp', + proto: true, + forced: _regexpExec !== /./.exec + }, { + exec: _regexpExec + }); + var SPECIES$1 = _wks('species'); + + var REPLACE_SUPPORTS_NAMED_GROUPS = !_fails(function () { + // #replace needs built-in support for named groups. + // #match works fine because it just return the exec results, even if it has + // a "grops" property. + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + return ''.replace(re, '$<a>') !== '7'; + }); -function get(target, propertyKey /* , receiver */) { - var receiver = arguments.length < 3 ? target : arguments[2]; - var desc, proto; - if (_anObject(target) === receiver) return target[propertyKey]; - if (desc = _objectGopd.f(target, propertyKey)) return _has(desc, 'value') - ? desc.value - : desc.get !== undefined - ? desc.get.call(receiver) - : undefined; - if (_isObject(proto = _objectGpo(target))) return get(proto, propertyKey, receiver); -} + var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = (function () { + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length === 2 && result[0] === 'a' && result[1] === 'b'; + })(); + + var _fixReWks = function (KEY, length, exec) { + var SYMBOL = _wks(KEY); + + var DELEGATES_TO_SYMBOL = !_fails(function () { + // String methods call symbol-named RegEp methods + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) != 7; + }); -_export(_export.S, 'Reflect', { get: get }); + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !_fails(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + re.exec = function () { execCalled = true; return null; }; + if (KEY === 'split') { + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES$1] = function () { return re; }; + } + re[SYMBOL](''); + return !execCalled; + }) : undefined; + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) || + (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) + ) { + var nativeRegExpMethod = /./[SYMBOL]; + var fns = exec( + _defined, + SYMBOL, + ''[KEY], + function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) { + if (regexp.exec === _regexpExec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) }; + } + return { done: true, value: nativeMethod.call(str, regexp, arg2) }; + } + return { done: false }; + } + ); + var strfn = fns[0]; + var rxfn = fns[1]; + + _redefine(String.prototype, KEY, strfn); + _hide(RegExp.prototype, SYMBOL, length == 2 + // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) + // 21.2.5.11 RegExp.prototype[@@split](string, limit) + ? function (string, arg) { return rxfn.call(string, this, arg); } + // 21.2.5.6 RegExp.prototype[@@match](string) + // 21.2.5.9 RegExp.prototype[@@search](string) + : function (string) { return rxfn.call(string, this); } + ); + } + }; -// 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey) + // @@search logic + _fixReWks('search', 1, function (defined, SEARCH, $search, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.github.io/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[SEARCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@search + function (regexp) { + var res = maybeCallNative($search, regexp, this); + if (res.done) return res.value; + var rx = _anObject(regexp); + var S = String(this); + var previousLastIndex = rx.lastIndex; + if (!_sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = _regexpExecAbstract(rx, S); + if (!_sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; + }); + // 21.2.5.3 get RegExp.prototype.flags() + if (_descriptors && /./g.flags != 'g') _objectDp.f(RegExp.prototype, 'flags', { + configurable: true, + get: _flags + }); + var TO_STRING = 'toString'; + var $toString = /./[TO_STRING]; + var define = function (fn) { + _redefine(RegExp.prototype, TO_STRING, fn, true); + }; -_export(_export.S, 'Reflect', { - getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey) { - return _objectGopd.f(_anObject(target), propertyKey); + // 21.2.5.14 RegExp.prototype.toString() + if (_fails(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) { + define(function toString() { + var R = _anObject(this); + return '/'.concat(R.source, '/', + 'flags' in R ? R.flags : !_descriptors && R instanceof RegExp ? _flags.call(R) : undefined); + }); + // FF44- RegExp#toString has a wrong name + } else if ($toString.name != TO_STRING) { + define(function toString() { + return $toString.call(this); + }); } -}); -// 26.1.8 Reflect.getPrototypeOf(target) + var _iterStep = function (done, value) { + return { value: value, done: !!done }; + }; + var def = _objectDp.f; + var TAG$1 = _wks('toStringTag'); + var _setToStringTag = function (it, tag, stat) { + if (it && !_has(it = stat ? it : it.prototype, TAG$1)) def(it, TAG$1, { configurable: true, value: tag }); + }; -_export(_export.S, 'Reflect', { - getPrototypeOf: function getPrototypeOf(target) { - return _objectGpo(_anObject(target)); - } -}); + var IteratorPrototype = {}; + + // 25.1.2.1.1 %IteratorPrototype%[@@iterator]() + _hide(IteratorPrototype, _wks('iterator'), function () { return this; }); -// 26.1.9 Reflect.has(target, propertyKey) + var _iterCreate = function (Constructor, NAME, next) { + Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) }); + _setToStringTag(Constructor, NAME + ' Iterator'); + }; + // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) -_export(_export.S, 'Reflect', { - has: function has(target, propertyKey) { - return propertyKey in target; - } -}); -// 26.1.10 Reflect.isExtensible(target) + var IE_PROTO$2 = _sharedKey('IE_PROTO'); + var ObjectProto = Object.prototype; + + var _objectGpo = Object.getPrototypeOf || function (O) { + O = _toObject(O); + if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; + }; + var ITERATOR$3 = _wks('iterator'); + var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` + var FF_ITERATOR = '@@iterator'; + var KEYS = 'keys'; + var VALUES = 'values'; + + var returnThis = function () { return this; }; + + var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + _iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR$3] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = _objectGpo($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + _setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!_library && typeof IteratorPrototype[ITERATOR$3] != 'function') _hide(IteratorPrototype, ITERATOR$3, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR$3])) { + _hide(proto, ITERATOR$3, $default); + } + // Plug for library + _iterators[NAME] = $default; + _iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) _redefine(proto, key, methods[key]); + } else _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; + }; -var $isExtensible = Object.isExtensible; + // 22.1.3.4 Array.prototype.entries() + // 22.1.3.13 Array.prototype.keys() + // 22.1.3.29 Array.prototype.values() + // 22.1.3.30 Array.prototype[@@iterator]() + var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) { + this._t = _toIobject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind + // 22.1.5.2.1 %ArrayIteratorPrototype%.next() + }, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return _iterStep(1); + } + if (kind == 'keys') return _iterStep(0, index); + if (kind == 'values') return _iterStep(0, O[index]); + return _iterStep(0, [index, O[index]]); + }, 'values'); + + // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) + _iterators.Arguments = _iterators.Array; + + _addToUnscopables('keys'); + _addToUnscopables('values'); + _addToUnscopables('entries'); + + var ITERATOR$4 = _wks('iterator'); + var TO_STRING_TAG = _wks('toStringTag'); + var ArrayValues = _iterators.Array; + + var DOMIterables = { + CSSRuleList: true, // TODO: Not spec compliant, should be false. + CSSStyleDeclaration: false, + CSSValueList: false, + ClientRectList: false, + DOMRectList: false, + DOMStringList: false, + DOMTokenList: true, + DataTransferItemList: false, + FileList: false, + HTMLAllCollection: false, + HTMLCollection: false, + HTMLFormElement: false, + HTMLSelectElement: false, + MediaList: true, // TODO: Not spec compliant, should be false. + MimeTypeArray: false, + NamedNodeMap: false, + NodeList: true, + PaintRequestList: false, + Plugin: false, + PluginArray: false, + SVGLengthList: false, + SVGNumberList: false, + SVGPathSegList: false, + SVGPointList: false, + SVGStringList: false, + SVGTransformList: false, + SourceBufferList: false, + StyleSheetList: true, // TODO: Not spec compliant, should be false. + TextTrackCueList: false, + TextTrackList: false, + TouchList: false + }; -_export(_export.S, 'Reflect', { - isExtensible: function isExtensible(target) { - _anObject(target); - return $isExtensible ? $isExtensible(target) : true; + for (var collections = _objectKeys(DOMIterables), i = 0; i < collections.length; i++) { + var NAME = collections[i]; + var explicit = DOMIterables[NAME]; + var Collection = _global[NAME]; + var proto$1 = Collection && Collection.prototype; + var key$1; + if (proto$1) { + if (!proto$1[ITERATOR$4]) _hide(proto$1, ITERATOR$4, ArrayValues); + if (!proto$1[TO_STRING_TAG]) _hide(proto$1, TO_STRING_TAG, NAME); + _iterators[NAME] = ArrayValues; + if (explicit) for (key$1 in es6_array_iterator) if (!proto$1[key$1]) _redefine(proto$1, key$1, es6_array_iterator[key$1], true); + } } -}); -// all object keys, includes non-enumerable and symbols + // true -> String#at + // false -> String#codePointAt + var _stringAt = function (TO_STRING) { + return function (that, pos) { + var s = String(_defined(that)); + var i = _toInteger(pos); + var l = s.length; + var a, b; + if (i < 0 || i >= l) return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; + }; + var $at = _stringAt(true); + + // 21.1.3.27 String.prototype[@@iterator]() + _iterDefine(String, 'String', function (iterated) { + this._t = String(iterated); // target + this._i = 0; // next index + // 21.1.5.2.1 %StringIteratorPrototype%.next() + }, function () { + var O = this._t; + var index = this._i; + var point; + if (index >= O.length) return { value: undefined, done: true }; + point = $at(O, index); + this._i += point.length; + return { value: point, done: false }; + }); + var _meta = createCommonjsModule(function (module) { + var META = _uid('meta'); -var Reflect$1 = _global.Reflect; -var _ownKeys = Reflect$1 && Reflect$1.ownKeys || function ownKeys(it) { - var keys = _objectGopn.f(_anObject(it)); - var getSymbols = _objectGops.f; - return getSymbols ? keys.concat(getSymbols(it)) : keys; -}; -// 26.1.11 Reflect.ownKeys(target) + var setDesc = _objectDp.f; + var id = 0; + var isExtensible = Object.isExtensible || function () { + return true; + }; + var FREEZE = !_fails(function () { + return isExtensible(Object.preventExtensions({})); + }); + var setMeta = function (it) { + setDesc(it, META, { value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + } }); + }; + var fastKey = function (it, create) { + // return primitive with prefix + if (!_isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if (!_has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return 'F'; + // not necessary to add metadata + if (!create) return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; + }; + var getWeak = function (it, create) { + if (!_has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return true; + // not necessary to add metadata + if (!create) return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; + }; + // add metadata on freeze-family methods calling + var onFreeze = function (it) { + if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it); + return it; + }; + var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze + }; + }); + var _meta_1 = _meta.KEY; + var _meta_2 = _meta.NEED; + var _meta_3 = _meta.fastKey; + var _meta_4 = _meta.getWeak; + var _meta_5 = _meta.onFreeze; + var f$4 = Object.getOwnPropertySymbols; -_export(_export.S, 'Reflect', { ownKeys: _ownKeys }); + var _objectGops = { + f: f$4 + }; -// 26.1.12 Reflect.preventExtensions(target) + // 19.1.2.1 Object.assign(target, source, ...) -var $preventExtensions = Object.preventExtensions; -_export(_export.S, 'Reflect', { - preventExtensions: function preventExtensions(target) { - _anObject(target); - try { - if ($preventExtensions) $preventExtensions(target); - return true; - } catch (e) { - return false; - } - } -}); -// 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) + var $assign = Object.assign; + // should work with symbols and should have deterministic property order (V8 bug) + var _objectAssign = !$assign || _fails(function () { + var A = {}; + var B = {}; + // eslint-disable-next-line no-undef + var S = Symbol(); + var K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function (k) { B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; + }) ? function assign(target, source) { // eslint-disable-line no-unused-vars + var T = _toObject(target); + var aLen = arguments.length; + var index = 1; + var getSymbols = _objectGops.f; + var isEnum = _objectPie.f; + while (aLen > index) { + var S = _iobject(arguments[index++]); + var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; + } return T; + } : $assign; + + var _redefineAll = function (target, src, safe) { + for (var key in src) _redefine(target, key, src[key], safe); + return target; + }; + var _anInstance = function (it, Constructor, name, forbiddenField) { + if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { + throw TypeError(name + ': incorrect invocation!'); + } return it; + }; + var _forOf = createCommonjsModule(function (module) { + var BREAK = {}; + var RETURN = {}; + var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { + var iterFn = ITERATOR ? function () { return iterable; } : core_getIteratorMethod(iterable); + var f = _ctx(fn, that, entries ? 2 : 1); + var index = 0; + var length, step, iterator, result; + if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if (_isArrayIter(iterFn)) for (length = _toLength(iterable.length); length > index; index++) { + result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if (result === BREAK || result === RETURN) return result; + } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { + result = _iterCall(iterator, f, step.value, entries); + if (result === BREAK || result === RETURN) return result; + } + }; + exports.BREAK = BREAK; + exports.RETURN = RETURN; + }); + var _validateCollection = function (it, TYPE) { + if (!_isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); + return it; + }; + var getWeak = _meta.getWeak; -function set(target, propertyKey, V /* , receiver */) { - var receiver = arguments.length < 4 ? target : arguments[3]; - var ownDesc = _objectGopd.f(_anObject(target), propertyKey); - var existingDescriptor, proto; - if (!ownDesc) { - if (_isObject(proto = _objectGpo(target))) { - return set(proto, propertyKey, V, receiver); - } - ownDesc = _propertyDesc(0); - } - if (_has(ownDesc, 'value')) { - if (ownDesc.writable === false || !_isObject(receiver)) return false; - existingDescriptor = _objectGopd.f(receiver, propertyKey) || _propertyDesc(0); - existingDescriptor.value = V; - _objectDp.f(receiver, propertyKey, existingDescriptor); - return true; - } - return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true); -} -_export(_export.S, 'Reflect', { set: set }); -// 26.1.14 Reflect.setPrototypeOf(target, proto) + var arrayFind = _arrayMethods(5); + var arrayFindIndex = _arrayMethods(6); + var id$1 = 0; -if (_setProto) _export(_export.S, 'Reflect', { - setPrototypeOf: function setPrototypeOf(target, proto) { - _setProto.check(target, proto); - try { - _setProto.set(target, proto); - return true; - } catch (e) { - return false; - } - } -}); - -var process = _global.process; -var setTask = _global.setImmediate; -var clearTask = _global.clearImmediate; -var MessageChannel = _global.MessageChannel; -var Dispatch = _global.Dispatch; -var counter = 0; -var queue = {}; -var ONREADYSTATECHANGE = 'onreadystatechange'; -var defer, channel, port; -var run = function () { - var id = +this; - // eslint-disable-next-line no-prototype-builtins - if (queue.hasOwnProperty(id)) { - var fn = queue[id]; - delete queue[id]; - fn(); - } -}; -var listener = function (event) { - run.call(event.data); -}; -// Node.js 0.9+ & IE10+ has setImmediate, otherwise: -if (!setTask || !clearTask) { - setTask = function setImmediate(fn) { - var args = []; - var i = 1; - while (arguments.length > i) args.push(arguments[i++]); - queue[++counter] = function () { - // eslint-disable-next-line no-new-func - _invoke(typeof fn == 'function' ? fn : Function(fn), args); - }; - defer(counter); - return counter; + // fallback for uncaught frozen keys + var uncaughtFrozenStore = function (that) { + return that._l || (that._l = new UncaughtFrozenStore()); }; - clearTask = function clearImmediate(id) { - delete queue[id]; + var UncaughtFrozenStore = function () { + this.a = []; }; - // Node.js 0.8- - if (_cof(process) == 'process') { - defer = function (id) { - process.nextTick(_ctx(run, id, 1)); - }; - // Sphere (JS game engine) Dispatch API - } else if (Dispatch && Dispatch.now) { - defer = function (id) { - Dispatch.now(_ctx(run, id, 1)); - }; - // Browsers with MessageChannel, includes WebWorkers - } else if (MessageChannel) { - channel = new MessageChannel(); - port = channel.port2; - channel.port1.onmessage = listener; - defer = _ctx(port.postMessage, port, 1); - // Browsers with postMessage, skip WebWorkers - // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' - } else if (_global.addEventListener && typeof postMessage == 'function' && !_global.importScripts) { - defer = function (id) { - _global.postMessage(id + '', '*'); - }; - _global.addEventListener('message', listener, false); - // IE8- - } else if (ONREADYSTATECHANGE in _domCreate('script')) { - defer = function (id) { - _html.appendChild(_domCreate('script'))[ONREADYSTATECHANGE] = function () { - _html.removeChild(this); - run.call(id); - }; - }; - // Rest old browsers - } else { - defer = function (id) { - setTimeout(_ctx(run, id, 1), 0); - }; - } -} -var _task = { - set: setTask, - clear: clearTask -}; - -var macrotask = _task.set; -var Observer = _global.MutationObserver || _global.WebKitMutationObserver; -var process$1 = _global.process; -var Promise$1 = _global.Promise; -var isNode = _cof(process$1) == 'process'; - -var _microtask = function () { - var head, last, notify; - - var flush = function () { - var parent, fn; - if (isNode && (parent = process$1.domain)) parent.exit(); - while (head) { - fn = head.fn; - head = head.next; - try { - fn(); - } catch (e) { - if (head) notify(); - else last = undefined; - throw e; - } - } last = undefined; - if (parent) parent.enter(); + var findUncaughtFrozen = function (store, key) { + return arrayFind(store.a, function (it) { + return it[0] === key; + }); + }; + UncaughtFrozenStore.prototype = { + get: function (key) { + var entry = findUncaughtFrozen(this, key); + if (entry) return entry[1]; + }, + has: function (key) { + return !!findUncaughtFrozen(this, key); + }, + set: function (key, value) { + var entry = findUncaughtFrozen(this, key); + if (entry) entry[1] = value; + else this.a.push([key, value]); + }, + 'delete': function (key) { + var index = arrayFindIndex(this.a, function (it) { + return it[0] === key; + }); + if (~index) this.a.splice(index, 1); + return !!~index; + } }; - // Node.js - if (isNode) { - notify = function () { - process$1.nextTick(flush); - }; - // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 - } else if (Observer && !(_global.navigator && _global.navigator.standalone)) { - var toggle = true; - var node = document.createTextNode(''); - new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new - notify = function () { - node.data = toggle = !toggle; - }; - // environments with maybe non-completely correct, but existent Promise - } else if (Promise$1 && Promise$1.resolve) { - var promise = Promise$1.resolve(); - notify = function () { - promise.then(flush); - }; - // for other environments - macrotask based on: - // - setImmediate - // - MessageChannel - // - window.postMessag - // - onreadystatechange - // - setTimeout - } else { - notify = function () { - // strange IE + webpack dev server bug - use .call(global) - macrotask.call(_global, flush); + var _collectionWeak = { + getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { + var C = wrapper(function (that, iterable) { + _anInstance(that, C, NAME, '_i'); + that._t = NAME; // collection type + that._i = id$1++; // collection id + that._l = undefined; // leak store for uncaught frozen objects + if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); + }); + _redefineAll(C.prototype, { + // 23.3.3.2 WeakMap.prototype.delete(key) + // 23.4.3.3 WeakSet.prototype.delete(value) + 'delete': function (key) { + if (!_isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key); + return data && _has(data, this._i) && delete data[this._i]; + }, + // 23.3.3.4 WeakMap.prototype.has(key) + // 23.4.3.4 WeakSet.prototype.has(value) + has: function has(key) { + if (!_isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key); + return data && _has(data, this._i); + } + }); + return C; + }, + def: function (that, key, value) { + var data = getWeak(_anObject(key), true); + if (data === true) uncaughtFrozenStore(that).set(key, value); + else data[that._i] = value; + return that; + }, + ufstore: uncaughtFrozenStore + }; + + var _collection = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { + var Base = _global[NAME]; + var C = Base; + var ADDER = IS_MAP ? 'set' : 'add'; + var proto = C && C.prototype; + var O = {}; + var fixMethod = function (KEY) { + var fn = proto[KEY]; + _redefine(proto, KEY, + KEY == 'delete' ? function (a) { + return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'has' ? function has(a) { + return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'get' ? function get(a) { + return IS_WEAK && !_isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; } + : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; } + ); }; - } + if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () { + new C().entries().next(); + }))) { + // create collection constructor + C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); + _redefineAll(C.prototype, methods); + _meta.NEED = true; + } else { + var instance = new C(); + // early implementations not supports chaining + var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; + // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false + var THROWS_ON_PRIMITIVES = _fails(function () { instance.has(1); }); + // most early implementations doesn't supports iterables, most modern - not close it correctly + var ACCEPT_ITERABLES = _iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new + // for early implementations -0 and +0 not the same + var BUGGY_ZERO = !IS_WEAK && _fails(function () { + // V8 ~ Chromium 42- fails only with 5+ elements + var $instance = new C(); + var index = 5; + while (index--) $instance[ADDER](index, index); + return !$instance.has(-0); + }); + if (!ACCEPT_ITERABLES) { + C = wrapper(function (target, iterable) { + _anInstance(target, C, NAME); + var that = _inheritIfRequired(new Base(), target, C); + if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); + return that; + }); + C.prototype = proto; + proto.constructor = C; + } + if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { + fixMethod('delete'); + fixMethod('has'); + IS_MAP && fixMethod('get'); + } + if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); + // weak collections should not contains .clear method + if (IS_WEAK && proto.clear) delete proto.clear; + } - return function (fn) { - var task = { fn: fn, next: undefined }; - if (last) last.next = task; - if (!head) { - head = task; - notify(); - } last = task; - }; -}; + _setToStringTag(C, NAME); -// 25.4.1.5 NewPromiseCapability(C) + O[NAME] = C; + _export(_export.G + _export.W + _export.F * (C != Base), O); + if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP); -function PromiseCapability(C) { - var resolve, reject; - this.promise = new C(function ($$resolve, $$reject) { - if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); - resolve = $$resolve; - reject = $$reject; - }); - this.resolve = _aFunction(resolve); - this.reject = _aFunction(reject); -} + return C; + }; -var f$5 = function (C) { - return new PromiseCapability(C); -}; + var es6_weakMap = createCommonjsModule(function (module) { + var each = _arrayMethods(0); -var _newPromiseCapability = { - f: f$5 -}; -var _perform = function (exec) { - try { - return { e: false, v: exec() }; - } catch (e) { - return { e: true, v: e }; - } -}; -var _promiseResolve = function (C, x) { - _anObject(C); - if (_isObject(x) && x.constructor === C) return x; - var promiseCapability = _newPromiseCapability.f(C); - var resolve = promiseCapability.resolve; - resolve(x); - return promiseCapability.promise; -}; -var task = _task.set; -var microtask = _microtask(); -var PROMISE = 'Promise'; -var TypeError$1 = _global.TypeError; -var process$2 = _global.process; -var $Promise = _global[PROMISE]; -var isNode$1 = _classof(process$2) == 'process'; -var empty = function () { /* empty */ }; -var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; -var newPromiseCapability = newGenericPromiseCapability = _newPromiseCapability.f; + var WEAK_MAP = 'WeakMap'; + var getWeak = _meta.getWeak; + var isExtensible = Object.isExtensible; + var uncaughtFrozenStore = _collectionWeak.ufstore; + var tmp = {}; + var InternalMap; -var USE_NATIVE = !!function () { - try { - // correct subclassing with @@species support - var promise = $Promise.resolve(1); - var FakePromise = (promise.constructor = {})[_wks('species')] = function (exec) { - exec(empty, empty); + var wrapper = function (get) { + return function WeakMap() { + return get(this, arguments.length > 0 ? arguments[0] : undefined); }; - // unhandled rejections tracking support, NodeJS Promise without it fails @@species test - return (isNode$1 || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; - } catch (e) { /* empty */ } -}(); - -// helpers -var isThenable = function (it) { - var then; - return _isObject(it) && typeof (then = it.then) == 'function' ? then : false; -}; -var notify = function (promise, isReject) { - if (promise._n) return; - promise._n = true; - var chain = promise._c; - microtask(function () { - var value = promise._v; - var ok = promise._s == 1; - var i = 0; - var run = function (reaction) { - var handler = ok ? reaction.ok : reaction.fail; - var resolve = reaction.resolve; - var reject = reaction.reject; - var domain = reaction.domain; - var result, then; - try { - if (handler) { - if (!ok) { - if (promise._h == 2) onHandleUnhandled(promise); - promise._h = 1; - } - if (handler === true) result = value; - else { - if (domain) domain.enter(); - result = handler(value); - if (domain) domain.exit(); - } - if (result === reaction.promise) { - reject(TypeError$1('Promise-chain cycle')); - } else if (then = isThenable(result)) { - then.call(result, resolve, reject); - } else resolve(result); - } else reject(value); - } catch (e) { - reject(e); + }; + + var methods = { + // 23.3.3.3 WeakMap.prototype.get(key) + get: function get(key) { + if (_isObject(key)) { + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key); + return data ? data[this._i] : undefined; } - }; - while (chain.length > i) run(chain[i++]); // variable length - can't use forEach - promise._c = []; - promise._n = false; - if (isReject && !promise._h) onUnhandled(promise); - }); -}; -var onUnhandled = function (promise) { - task.call(_global, function () { - var value = promise._v; - var unhandled = isUnhandled(promise); - var result, handler, console; - if (unhandled) { - result = _perform(function () { - if (isNode$1) { - process$2.emit('unhandledRejection', value, promise); - } else if (handler = _global.onunhandledrejection) { - handler({ promise: promise, reason: value }); - } else if ((console = _global.console) && console.error) { - console.error('Unhandled promise rejection', value); - } - }); - // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should - promise._h = isNode$1 || isUnhandled(promise) ? 2 : 1; - } promise._a = undefined; - if (unhandled && result.e) throw result.v; - }); -}; -var isUnhandled = function (promise) { - return promise._h !== 1 && (promise._a || promise._c).length === 0; -}; -var onHandleUnhandled = function (promise) { - task.call(_global, function () { - var handler; - if (isNode$1) { - process$2.emit('rejectionHandled', promise); - } else if (handler = _global.onrejectionhandled) { - handler({ promise: promise, reason: promise._v }); + }, + // 23.3.3.5 WeakMap.prototype.set(key, value) + set: function set(key, value) { + return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value); } - }); -}; -var $reject = function (value) { - var promise = this; - if (promise._d) return; - promise._d = true; - promise = promise._w || promise; // unwrap - promise._v = value; - promise._s = 2; - if (!promise._a) promise._a = promise._c.slice(); - notify(promise, true); -}; -var $resolve = function (value) { - var promise = this; - var then; - if (promise._d) return; - promise._d = true; - promise = promise._w || promise; // unwrap - try { - if (promise === value) throw TypeError$1("Promise can't be resolved itself"); - if (then = isThenable(value)) { - microtask(function () { - var wrapper = { _w: promise, _d: false }; // wrap - try { - then.call(value, _ctx($resolve, wrapper, 1), _ctx($reject, wrapper, 1)); - } catch (e) { - $reject.call(wrapper, e); - } + }; + + // 23.3 WeakMap Objects + var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true); + + // IE11 WeakMap frozen keys fix + if (_fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { + InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP); + _objectAssign(InternalMap.prototype, methods); + _meta.NEED = true; + each(['delete', 'has', 'get', 'set'], function (key) { + var proto = $WeakMap.prototype; + var method = proto[key]; + _redefine(proto, key, function (a, b) { + // store frozen objects on internal weakmap shim + if (_isObject(a) && !isExtensible(a)) { + if (!this._f) this._f = new InternalMap(); + var result = this._f[key](a, b); + return key == 'set' ? this : result; + // store all the rest on native weakmap + } return method.call(this, a, b); }); - } else { - promise._v = value; - promise._s = 1; - notify(promise, false); - } - } catch (e) { - $reject.call({ _w: promise, _d: false }, e); // wrap + }); } -}; - -// constructor polyfill -if (!USE_NATIVE) { - // 25.4.3.1 Promise(executor) - $Promise = function Promise(executor) { - _anInstance(this, $Promise, PROMISE, '_h'); - _aFunction(executor); - Internal.call(this); - try { - executor(_ctx($resolve, this, 1), _ctx($reject, this, 1)); - } catch (err) { - $reject.call(this, err); + }); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); } - }; - // eslint-disable-next-line no-unused-vars - Internal = function Promise(executor) { - this._c = []; // <- awaiting reactions - this._a = undefined; // <- checked in isUnhandled reactions - this._s = 0; // <- state - this._d = false; // <- done - this._v = undefined; // <- value - this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled - this._n = false; // <- notify - }; - Internal.prototype = _redefineAll($Promise.prototype, { - // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) - then: function then(onFulfilled, onRejected) { - var reaction = newPromiseCapability(_speciesConstructor(this, $Promise)); - reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; - reaction.fail = typeof onRejected == 'function' && onRejected; - reaction.domain = isNode$1 ? process$2.domain : undefined; - this._c.push(reaction); - if (this._a) this._a.push(reaction); - if (this._s) notify(this, false); - return reaction.promise; - }, - // 25.4.5.1 Promise.prototype.catch(onRejected) - 'catch': function (onRejected) { - return this.then(undefined, onRejected); + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); } - }); - OwnPromiseCapability = function () { - var promise = new Internal(); - this.promise = promise; - this.resolve = _ctx($resolve, promise, 1); - this.reject = _ctx($reject, promise, 1); - }; - _newPromiseCapability.f = newPromiseCapability = function (C) { - return C === $Promise || C === Wrapper - ? new OwnPromiseCapability(C) - : newGenericPromiseCapability(C); - }; -} - -_export(_export.G + _export.W + _export.F * !USE_NATIVE, { Promise: $Promise }); -_setToStringTag($Promise, PROMISE); -_setSpecies(PROMISE); -Wrapper = _core[PROMISE]; - -// statics -_export(_export.S + _export.F * !USE_NATIVE, PROMISE, { - // 25.4.4.5 Promise.reject(r) - reject: function reject(r) { - var capability = newPromiseCapability(this); - var $$reject = capability.reject; - $$reject(r); - return capability.promise; } -}); -_export(_export.S + _export.F * (_library || !USE_NATIVE), PROMISE, { - // 25.4.4.6 Promise.resolve(x) - resolve: function resolve(x) { - return _promiseResolve(_library && this === Wrapper ? $Promise : this, x); + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; } -}); -_export(_export.S + _export.F * !(USE_NATIVE && _iterDetect(function (iter) { - $Promise.all(iter)['catch'](empty); -})), PROMISE, { - // 25.4.4.1 Promise.all(iterable) - all: function all(iterable) { - var C = this; - var capability = newPromiseCapability(C); - var resolve = capability.resolve; - var reject = capability.reject; - var result = _perform(function () { - var values = []; - var index = 0; - var remaining = 1; - _forOf(iterable, false, function (promise) { - var $index = index++; - var alreadyCalled = false; - values.push(undefined); - remaining++; - C.resolve(promise).then(function (value) { - if (alreadyCalled) return; - alreadyCalled = true; - values[$index] = value; - --remaining || resolve(values); - }, reject); - }); - --remaining || resolve(values); - }); - if (result.e) reject(result.v); - return capability.promise; - }, - // 25.4.4.4 Promise.race(iterable) - race: function race(iterable) { - var C = this; - var capability = newPromiseCapability(C); - var reject = capability.reject; - var result = _perform(function () { - _forOf(iterable, false, function (promise) { - C.resolve(promise).then(capability.resolve, reject); + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true }); - }); - if (result.e) reject(result.v); - return capability.promise; - } -}); + } else { + obj[key] = value; + } -var f$6 = _wks; + return obj; + } -var _wksExt = { - f: f$6 -}; + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } -var defineProperty = _objectDp.f; -var _wksDefine = function (name) { - var $Symbol = _core.Symbol || (_core.Symbol = _library ? {} : _global.Symbol || {}); - if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: _wksExt.f(name) }); -}; + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } -// all enumerable object keys, includes symbols + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + return arr2; + } + } + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } -var _enumKeys = function (it) { - var result = _objectKeys(it); - var getSymbols = _objectGops.f; - if (getSymbols) { - var symbols = getSymbols(it); - var isEnum = _objectPie.f; - var i = 0; - var key; - while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key); - } return result; -}; + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } -// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window + function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; -var gOPN = _objectGopn.f; -var toString$1 = {}.toString; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); -var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames - ? Object.getOwnPropertyNames(window) : []; + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } -var getWindowNames = function (it) { - try { - return gOPN(it); - } catch (e) { - return windowNames.slice(); + return _arr; } -}; - -var f$7 = function getOwnPropertyNames(it) { - return windowNames && toString$1.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(_toIobject(it)); -}; -var _objectGopnExt = { - f: f$7 -}; - -// ECMAScript 6 symbols shim + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + var _strictMethod = function (method, arg) { + return !!method && _fails(function () { + // eslint-disable-next-line no-useless-call + arg ? method.call(null, function () { /* empty */ }, 1) : method.call(null); + }); + }; + var $sort = [].sort; + var test = [1, 2, 3]; + _export(_export.P + _export.F * (_fails(function () { + // IE8- + test.sort(undefined); + }) || !_fails(function () { + // V8 bug + test.sort(null); + // Old WebKit + }) || !_strictMethod($sort)), 'Array', { + // 22.1.3.25 Array.prototype.sort(comparefn) + sort: function sort(comparefn) { + return comparefn === undefined + ? $sort.call(_toObject(this)) + : $sort.call(_toObject(this), _aFunction(comparefn)); + } + }); -var META = _meta.KEY; + // 19.1.3.1 Object.assign(target, source) + _export(_export.S + _export.F, 'Object', { assign: _objectAssign }); + // 7.3.20 SpeciesConstructor(O, defaultConstructor) + var SPECIES$2 = _wks('species'); + var _speciesConstructor = function (O, D) { + var C = _anObject(O).constructor; + var S; + return C === undefined || (S = _anObject(C)[SPECIES$2]) == undefined ? D : _aFunction(S); + }; + var at = _stringAt(true); + // `AdvanceStringIndex` abstract operation + // https://tc39.github.io/ecma262/#sec-advancestringindex + var _advanceStringIndex = function (S, index, unicode) { + return index + (unicode ? at(S, index).length : 1); + }; + var $min = Math.min; + var $push = [].push; + var $SPLIT = 'split'; + var LENGTH = 'length'; + var LAST_INDEX$1 = 'lastIndex'; + var MAX_UINT32 = 0xffffffff; + + // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError + var SUPPORTS_Y = !_fails(function () { }); + + // @@split logic + _fixReWks('split', 2, function (defined, SPLIT, $split, maybeCallNative) { + var internalSplit; + if ( + 'abbc'[$SPLIT](/(b)*/)[1] == 'c' || + 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || + 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 || + '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 || + '.'[$SPLIT](/()()/)[LENGTH] > 1 || + ''[$SPLIT](/.?/)[LENGTH] + ) { + // based on es5-shim implementation, need to rework it + internalSplit = function (separator, limit) { + var string = String(this); + if (separator === undefined && limit === 0) return []; + // If `separator` is not a regex, use native split + if (!_isRegexp(separator)) return $split.call(string, separator, limit); + var output = []; + var flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.unicode ? 'u' : '') + + (separator.sticky ? 'y' : ''); + var lastLastIndex = 0; + var splitLimit = limit === undefined ? MAX_UINT32 : limit >>> 0; + // Make `global` and avoid `lastIndex` issues by working with a copy + var separatorCopy = new RegExp(separator.source, flags + 'g'); + var match, lastIndex, lastLength; + while (match = _regexpExec.call(separatorCopy, string)) { + lastIndex = separatorCopy[LAST_INDEX$1]; + if (lastIndex > lastLastIndex) { + output.push(string.slice(lastLastIndex, match.index)); + if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1)); + lastLength = match[0][LENGTH]; + lastLastIndex = lastIndex; + if (output[LENGTH] >= splitLimit) break; + } + if (separatorCopy[LAST_INDEX$1] === match.index) separatorCopy[LAST_INDEX$1]++; // Avoid an infinite loop + } + if (lastLastIndex === string[LENGTH]) { + if (lastLength || !separatorCopy.test('')) output.push(''); + } else output.push(string.slice(lastLastIndex)); + return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output; + }; + // Chakra, V8 + } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) { + internalSplit = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit); + }; + } else { + internalSplit = $split; + } + return [ + // `String.prototype.split` method + // https://tc39.github.io/ecma262/#sec-string.prototype.split + function split(separator, limit) { + var O = defined(this); + var splitter = separator == undefined ? undefined : separator[SPLIT]; + return splitter !== undefined + ? splitter.call(separator, O, limit) + : internalSplit.call(String(O), separator, limit); + }, + // `RegExp.prototype[@@split]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split + // + // NOTE: This cannot be properly polyfilled in engines that don't support + // the 'y' flag. + function (regexp, limit) { + var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split); + if (res.done) return res.value; + + var rx = _anObject(regexp); + var S = String(this); + var C = _speciesConstructor(rx, RegExp); + + var unicodeMatching = rx.unicode; + var flags = (rx.ignoreCase ? 'i' : '') + + (rx.multiline ? 'm' : '') + + (rx.unicode ? 'u' : '') + + (SUPPORTS_Y ? 'y' : 'g'); + + // ^(? + rx + ) is needed, in combination with some S slicing, to + // simulate the 'y' flag. + var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (S.length === 0) return _regexpExecAbstract(splitter, S) === null ? [S] : []; + var p = 0; + var q = 0; + var A = []; + while (q < S.length) { + splitter.lastIndex = SUPPORTS_Y ? q : 0; + var z = _regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q)); + var e; + if ( + z === null || + (e = $min(_toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p + ) { + q = _advanceStringIndex(S, q, unicodeMatching); + } else { + A.push(S.slice(p, q)); + if (A.length === lim) return A; + for (var i = 1; i <= z.length - 1; i++) { + A.push(z[i]); + if (A.length === lim) return A; + } + q = p = e; + } + } + A.push(S.slice(p)); + return A; + } + ]; + }); + var isEnum = _objectPie.f; + var _objectToArray = function (isEntries) { + return function (it) { + var O = _toIobject(it); + var keys = _objectKeys(O); + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) if (isEnum.call(O, key = keys[i++])) { + result.push(isEntries ? [key, O[key]] : O[key]); + } return result; + }; + }; + // https://github.com/tc39/proposal-object-values-entries + var $entries = _objectToArray(true); + _export(_export.S, 'Object', { + entries: function entries(it) { + return $entries(it); + } + }); + // https://github.com/tc39/proposal-object-values-entries + var $values = _objectToArray(false); + _export(_export.S, 'Object', { + values: function values(it) { + return $values(it); + } + }); + var max$1 = Math.max; + var min$2 = Math.min; + var floor$1 = Math.floor; + var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g; + var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g; + var maybeToString = function (it) { + return it === undefined ? it : String(it); + }; -var gOPD$2 = _objectGopd.f; -var dP$2 = _objectDp.f; -var gOPN$1 = _objectGopnExt.f; -var $Symbol = _global.Symbol; -var $JSON = _global.JSON; -var _stringify = $JSON && $JSON.stringify; -var PROTOTYPE$2 = 'prototype'; -var HIDDEN = _wks('_hidden'); -var TO_PRIMITIVE = _wks('toPrimitive'); -var isEnum = {}.propertyIsEnumerable; -var SymbolRegistry = _shared('symbol-registry'); -var AllSymbols = _shared('symbols'); -var OPSymbols = _shared('op-symbols'); -var ObjectProto$1 = Object[PROTOTYPE$2]; -var USE_NATIVE$1 = typeof $Symbol == 'function'; -var QObject = _global.QObject; -// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 -var setter = !QObject || !QObject[PROTOTYPE$2] || !QObject[PROTOTYPE$2].findChild; + // @@replace logic + _fixReWks('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) { + return [ + // `String.prototype.replace` method + // https://tc39.github.io/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = defined(this); + var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; + return fn !== undefined + ? fn.call(searchValue, O, replaceValue) + : $replace.call(String(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace + function (regexp, replaceValue) { + var res = maybeCallNative($replace, regexp, this, replaceValue); + if (res.done) return res.value; + + var rx = _anObject(regexp); + var S = String(this); + var functionalReplace = typeof replaceValue === 'function'; + if (!functionalReplace) replaceValue = String(replaceValue); + var global = rx.global; + if (global) { + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + var results = []; + while (true) { + var result = _regexpExecAbstract(rx, S); + if (result === null) break; + results.push(result); + if (!global) break; + var matchStr = String(result[0]); + if (matchStr === '') rx.lastIndex = _advanceStringIndex(S, _toLength(rx.lastIndex), fullUnicode); + } + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + var matched = String(result[0]); + var position = max$1(min$2(_toInteger(result.index), S.length), 0); + var captures = []; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = [matched].concat(captures, position, S); + if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); + var replacement = String(replaceValue.apply(undefined, replacerArgs)); + } else { + replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += S.slice(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + return accumulatedResult + S.slice(nextSourcePosition); + } + ]; + + // https://tc39.github.io/ecma262/#sec-getsubstitution + function getSubstitution(matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = _toObject(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return $replace.call(replacement, symbols, function (match, ch) { + var capture; + switch (ch.charAt(0)) { + case '$': return '$'; + case '&': return matched; + case '`': return str.slice(0, position); + case "'": return str.slice(tailPos); + case '<': + capture = namedCaptures[ch.slice(1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return match; + if (n > m) { + var f = floor$1(n / 10); + if (f === 0) return match; + if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); + return match; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + } + }); -// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 -var setSymbolDesc = _descriptors && _fails(function () { - return _objectCreate(dP$2({}, 'a', { - get: function () { return dP$2(this, 'a', { value: 7 }).a; } - })).a != 7; -}) ? function (it, key, D) { - var protoDesc = gOPD$2(ObjectProto$1, key); - if (protoDesc) delete ObjectProto$1[key]; - dP$2(it, key, D); - if (protoDesc && it !== ObjectProto$1) dP$2(ObjectProto$1, key, protoDesc); -} : dP$2; + // fast apply, http://jsperf.lnkit.com/fast-apply/5 + var _invoke = function (fn, args, that) { + var un = that === undefined; + switch (args.length) { + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); + }; -var wrap = function (tag) { - var sym = AllSymbols[tag] = _objectCreate($Symbol[PROTOTYPE$2]); - sym._k = tag; - return sym; -}; + var process = _global.process; + var setTask = _global.setImmediate; + var clearTask = _global.clearImmediate; + var MessageChannel = _global.MessageChannel; + var Dispatch = _global.Dispatch; + var counter = 0; + var queue = {}; + var ONREADYSTATECHANGE = 'onreadystatechange'; + var defer, channel, port; + var run = function () { + var id = +this; + // eslint-disable-next-line no-prototype-builtins + if (queue.hasOwnProperty(id)) { + var fn = queue[id]; + delete queue[id]; + fn(); + } + }; + var listener = function (event) { + run.call(event.data); + }; + // Node.js 0.9+ & IE10+ has setImmediate, otherwise: + if (!setTask || !clearTask) { + setTask = function setImmediate(fn) { + var args = []; + var i = 1; + while (arguments.length > i) args.push(arguments[i++]); + queue[++counter] = function () { + // eslint-disable-next-line no-new-func + _invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id) { + delete queue[id]; + }; + // Node.js 0.8- + if (_cof(process) == 'process') { + defer = function (id) { + process.nextTick(_ctx(run, id, 1)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(_ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if (MessageChannel) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = listener; + defer = _ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if (_global.addEventListener && typeof postMessage == 'function' && !_global.importScripts) { + defer = function (id) { + _global.postMessage(id + '', '*'); + }; + _global.addEventListener('message', listener, false); + // IE8- + } else if (ONREADYSTATECHANGE in _domCreate('script')) { + defer = function (id) { + _html.appendChild(_domCreate('script'))[ONREADYSTATECHANGE] = function () { + _html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(_ctx(run, id, 1), 0); + }; + } + } + var _task = { + set: setTask, + clear: clearTask + }; -var isSymbol = USE_NATIVE$1 && typeof $Symbol.iterator == 'symbol' ? function (it) { - return typeof it == 'symbol'; -} : function (it) { - return it instanceof $Symbol; -}; + var macrotask = _task.set; + var Observer = _global.MutationObserver || _global.WebKitMutationObserver; + var process$1 = _global.process; + var Promise$1 = _global.Promise; + var isNode = _cof(process$1) == 'process'; + + var _microtask = function () { + var head, last, notify; + + var flush = function () { + var parent, fn; + if (isNode && (parent = process$1.domain)) parent.exit(); + while (head) { + fn = head.fn; + head = head.next; + try { + fn(); + } catch (e) { + if (head) notify(); + else last = undefined; + throw e; + } + } last = undefined; + if (parent) parent.enter(); + }; -var $defineProperty = function defineProperty(it, key, D) { - if (it === ObjectProto$1) $defineProperty(OPSymbols, key, D); - _anObject(it); - key = _toPrimitive(key, true); - _anObject(D); - if (_has(AllSymbols, key)) { - if (!D.enumerable) { - if (!_has(it, HIDDEN)) dP$2(it, HIDDEN, _propertyDesc(1, {})); - it[HIDDEN][key] = true; + // Node.js + if (isNode) { + notify = function () { + process$1.nextTick(flush); + }; + // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 + } else if (Observer && !(_global.navigator && _global.navigator.standalone)) { + var toggle = true; + var node = document.createTextNode(''); + new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new + notify = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (Promise$1 && Promise$1.resolve) { + // Promise.resolve without an argument throws an error in LG WebOS 2 + var promise = Promise$1.resolve(undefined); + notify = function () { + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout } else { - if (_has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false; - D = _objectCreate(D, { enumerable: _propertyDesc(0, false) }); - } return setSymbolDesc(it, key, D); - } return dP$2(it, key, D); -}; -var $defineProperties = function defineProperties(it, P) { - _anObject(it); - var keys = _enumKeys(P = _toIobject(P)); - var i = 0; - var l = keys.length; - var key; - while (l > i) $defineProperty(it, key = keys[i++], P[key]); - return it; -}; -var $create = function create(it, P) { - return P === undefined ? _objectCreate(it) : $defineProperties(_objectCreate(it), P); -}; -var $propertyIsEnumerable = function propertyIsEnumerable(key) { - var E = isEnum.call(this, key = _toPrimitive(key, true)); - if (this === ObjectProto$1 && _has(AllSymbols, key) && !_has(OPSymbols, key)) return false; - return E || !_has(this, key) || !_has(AllSymbols, key) || _has(this, HIDDEN) && this[HIDDEN][key] ? E : true; -}; -var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) { - it = _toIobject(it); - key = _toPrimitive(key, true); - if (it === ObjectProto$1 && _has(AllSymbols, key) && !_has(OPSymbols, key)) return; - var D = gOPD$2(it, key); - if (D && _has(AllSymbols, key) && !(_has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true; - return D; -}; -var $getOwnPropertyNames = function getOwnPropertyNames(it) { - var names = gOPN$1(_toIobject(it)); - var result = []; - var i = 0; - var key; - while (names.length > i) { - if (!_has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key); - } return result; -}; -var $getOwnPropertySymbols = function getOwnPropertySymbols(it) { - var IS_OP = it === ObjectProto$1; - var names = gOPN$1(IS_OP ? OPSymbols : _toIobject(it)); - var result = []; - var i = 0; - var key; - while (names.length > i) { - if (_has(AllSymbols, key = names[i++]) && (IS_OP ? _has(ObjectProto$1, key) : true)) result.push(AllSymbols[key]); - } return result; -}; - -// 19.4.1.1 Symbol([description]) -if (!USE_NATIVE$1) { - $Symbol = function Symbol() { - if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!'); - var tag = _uid(arguments.length > 0 ? arguments[0] : undefined); - var $set = function (value) { - if (this === ObjectProto$1) $set.call(OPSymbols, value); - if (_has(this, HIDDEN) && _has(this[HIDDEN], tag)) this[HIDDEN][tag] = false; - setSymbolDesc(this, tag, _propertyDesc(1, value)); + notify = function () { + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(_global, flush); + }; + } + + return function (fn) { + var task = { fn: fn, next: undefined }; + if (last) last.next = task; + if (!head) { + head = task; + notify(); + } last = task; }; - if (_descriptors && setter) setSymbolDesc(ObjectProto$1, tag, { configurable: true, set: $set }); - return wrap(tag); }; - _redefine($Symbol[PROTOTYPE$2], 'toString', function toString() { - return this._k; - }); - _objectGopd.f = $getOwnPropertyDescriptor; - _objectDp.f = $defineProperty; - _objectGopn.f = _objectGopnExt.f = $getOwnPropertyNames; - _objectPie.f = $propertyIsEnumerable; - _objectGops.f = $getOwnPropertySymbols; + // 25.4.1.5 NewPromiseCapability(C) - if (_descriptors && !_library) { - _redefine(ObjectProto$1, 'propertyIsEnumerable', $propertyIsEnumerable, true); - } - _wksExt.f = function (name) { - return wrap(_wks(name)); - }; -} - -_export(_export.G + _export.W + _export.F * !USE_NATIVE$1, { Symbol: $Symbol }); - -for (var es6Symbols = ( - // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14 - 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables' -).split(','), j = 0; es6Symbols.length > j;)_wks(es6Symbols[j++]); - -for (var wellKnownSymbols = _objectKeys(_wks.store), k = 0; wellKnownSymbols.length > k;) _wksDefine(wellKnownSymbols[k++]); - -_export(_export.S + _export.F * !USE_NATIVE$1, 'Symbol', { - // 19.4.2.1 Symbol.for(key) - 'for': function (key) { - return _has(SymbolRegistry, key += '') - ? SymbolRegistry[key] - : SymbolRegistry[key] = $Symbol(key); - }, - // 19.4.2.5 Symbol.keyFor(sym) - keyFor: function keyFor(sym) { - if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!'); - for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key; - }, - useSetter: function () { setter = true; }, - useSimple: function () { setter = false; } -}); - -_export(_export.S + _export.F * !USE_NATIVE$1, 'Object', { - // 19.1.2.2 Object.create(O [, Properties]) - create: $create, - // 19.1.2.4 Object.defineProperty(O, P, Attributes) - defineProperty: $defineProperty, - // 19.1.2.3 Object.defineProperties(O, Properties) - defineProperties: $defineProperties, - // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) - getOwnPropertyDescriptor: $getOwnPropertyDescriptor, - // 19.1.2.7 Object.getOwnPropertyNames(O) - getOwnPropertyNames: $getOwnPropertyNames, - // 19.1.2.8 Object.getOwnPropertySymbols(O) - getOwnPropertySymbols: $getOwnPropertySymbols -}); - -// 24.3.2 JSON.stringify(value [, replacer [, space]]) -$JSON && _export(_export.S + _export.F * (!USE_NATIVE$1 || _fails(function () { - var S = $Symbol(); - // MS Edge converts symbol values to JSON as {} - // WebKit converts symbol values to JSON as null - // V8 throws on boxed symbols - return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}'; -})), 'JSON', { - stringify: function stringify(it) { - var args = [it]; - var i = 1; - var replacer, $replacer; - while (arguments.length > i) args.push(arguments[i++]); - $replacer = replacer = args[1]; - if (!_isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined - if (!_isArray(replacer)) replacer = function (key, value) { - if (typeof $replacer == 'function') value = $replacer.call(this, key, value); - if (!isSymbol(value)) return value; - }; - args[1] = replacer; - return _stringify.apply($JSON, args); + function PromiseCapability(C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = _aFunction(resolve); + this.reject = _aFunction(reject); } -}); -// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) -$Symbol[PROTOTYPE$2][TO_PRIMITIVE] || _hide($Symbol[PROTOTYPE$2], TO_PRIMITIVE, $Symbol[PROTOTYPE$2].valueOf); -// 19.4.3.5 Symbol.prototype[@@toStringTag] -_setToStringTag($Symbol, 'Symbol'); -// 20.2.1.9 Math[@@toStringTag] -_setToStringTag(Math, 'Math', true); -// 24.3.3 JSON[@@toStringTag] -_setToStringTag(_global.JSON, 'JSON', true); + var f$5 = function (C) { + return new PromiseCapability(C); + }; -// most Object methods by ES6 should accept primitives + var _newPromiseCapability = { + f: f$5 + }; + var _perform = function (exec) { + try { + return { e: false, v: exec() }; + } catch (e) { + return { e: true, v: e }; + } + }; + var navigator$1 = _global.navigator; -var _objectSap = function (KEY, exec) { - var fn = (_core.Object || {})[KEY] || Object[KEY]; - var exp = {}; - exp[KEY] = exec(fn); - _export(_export.S + _export.F * _fails(function () { fn(1); }), 'Object', exp); -}; + var _userAgent = navigator$1 && navigator$1.userAgent || ''; -// 19.1.2.5 Object.freeze(O) + var _promiseResolve = function (C, x) { + _anObject(C); + if (_isObject(x) && x.constructor === C) return x; + var promiseCapability = _newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; + }; -var meta = _meta.onFreeze; + var SPECIES$3 = _wks('species'); -_objectSap('freeze', function ($freeze) { - return function freeze(it) { - return $freeze && _isObject(it) ? $freeze(meta(it)) : it; + var _setSpecies = function (KEY) { + var C = _global[KEY]; + if (_descriptors && C && !C[SPECIES$3]) _objectDp.f(C, SPECIES$3, { + configurable: true, + get: function () { return this; } + }); }; -}); -// 19.1.2.17 Object.seal(O) + var task = _task.set; + var microtask = _microtask(); -var meta$1 = _meta.onFreeze; -_objectSap('seal', function ($seal) { - return function seal(it) { - return $seal && _isObject(it) ? $seal(meta$1(it)) : it; - }; -}); -// 19.1.2.15 Object.preventExtensions(O) -var meta$2 = _meta.onFreeze; + var PROMISE = 'Promise'; + var TypeError$1 = _global.TypeError; + var process$2 = _global.process; + var versions = process$2 && process$2.versions; + var v8 = versions && versions.v8 || ''; + var $Promise = _global[PROMISE]; + var isNode$1 = _classof(process$2) == 'process'; + var empty = function () { /* empty */ }; + var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; + var newPromiseCapability = newGenericPromiseCapability = _newPromiseCapability.f; -_objectSap('preventExtensions', function ($preventExtensions) { - return function preventExtensions(it) { - return $preventExtensions && _isObject(it) ? $preventExtensions(meta$2(it)) : it; + var USE_NATIVE = !!function () { + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1); + var FakePromise = (promise.constructor = {})[_wks('species')] = function (exec) { + exec(empty, empty); + }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode$1 || typeof PromiseRejectionEvent == 'function') + && promise.then(empty) instanceof FakePromise + // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables + // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 + // we can't detect it synchronously, so just check versions + && v8.indexOf('6.6') !== 0 + && _userAgent.indexOf('Chrome/66') === -1; + } catch (e) { /* empty */ } + }(); + + // helpers + var isThenable = function (it) { + var then; + return _isObject(it) && typeof (then = it.then) == 'function' ? then : false; }; -}); + var notify = function (promise, isReject) { + if (promise._n) return; + promise._n = true; + var chain = promise._c; + microtask(function () { + var value = promise._v; + var ok = promise._s == 1; + var i = 0; + var run = function (reaction) { + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then, exited; + try { + if (handler) { + if (!ok) { + if (promise._h == 2) onHandleUnhandled(promise); + promise._h = 1; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); // may throw + if (domain) { + domain.exit(); + exited = true; + } + } + if (result === reaction.promise) { + reject(TypeError$1('Promise-chain cycle')); + } else if (then = isThenable(result)) { + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (e) { + if (domain && !exited) domain.exit(); + reject(e); + } + }; + while (chain.length > i) run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if (isReject && !promise._h) onUnhandled(promise); + }); + }; + var onUnhandled = function (promise) { + task.call(_global, function () { + var value = promise._v; + var unhandled = isUnhandled(promise); + var result, handler, console; + if (unhandled) { + result = _perform(function () { + if (isNode$1) { + process$2.emit('unhandledRejection', value, promise); + } else if (handler = _global.onunhandledrejection) { + handler({ promise: promise, reason: value }); + } else if ((console = _global.console) && console.error) { + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode$1 || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if (unhandled && result.e) throw result.v; + }); + }; + var isUnhandled = function (promise) { + return promise._h !== 1 && (promise._a || promise._c).length === 0; + }; + var onHandleUnhandled = function (promise) { + task.call(_global, function () { + var handler; + if (isNode$1) { + process$2.emit('rejectionHandled', promise); + } else if (handler = _global.onrejectionhandled) { + handler({ promise: promise, reason: promise._v }); + } + }); + }; + var $reject = function (value) { + var promise = this; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if (!promise._a) promise._a = promise._c.slice(); + notify(promise, true); + }; + var $resolve = function (value) { + var promise = this; + var then; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if (promise === value) throw TypeError$1("Promise can't be resolved itself"); + if (then = isThenable(value)) { + microtask(function () { + var wrapper = { _w: promise, _d: false }; // wrap + try { + then.call(value, _ctx($resolve, wrapper, 1), _ctx($reject, wrapper, 1)); + } catch (e) { + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch (e) { + $reject.call({ _w: promise, _d: false }, e); // wrap + } + }; + + // constructor polyfill + if (!USE_NATIVE) { + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor) { + _anInstance(this, $Promise, PROMISE, '_h'); + _aFunction(executor); + Internal.call(this); + try { + executor(_ctx($resolve, this, 1), _ctx($reject, this, 1)); + } catch (err) { + $reject.call(this, err); + } + }; + // eslint-disable-next-line no-unused-vars + Internal = function Promise(executor) { + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = _redefineAll($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected) { + var reaction = newPromiseCapability(_speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode$1 ? process$2.domain : undefined; + this._c.push(reaction); + if (this._a) this._a.push(reaction); + if (this._s) notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + OwnPromiseCapability = function () { + var promise = new Internal(); + this.promise = promise; + this.resolve = _ctx($resolve, promise, 1); + this.reject = _ctx($reject, promise, 1); + }; + _newPromiseCapability.f = newPromiseCapability = function (C) { + return C === $Promise || C === Wrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; + } -// 19.1.2.12 Object.isFrozen(O) + _export(_export.G + _export.W + _export.F * !USE_NATIVE, { Promise: $Promise }); + _setToStringTag($Promise, PROMISE); + _setSpecies(PROMISE); + Wrapper = _core[PROMISE]; + + // statics + _export(_export.S + _export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r) { + var capability = newPromiseCapability(this); + var $$reject = capability.reject; + $$reject(r); + return capability.promise; + } + }); + _export(_export.S + _export.F * (_library || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x) { + return _promiseResolve(_library && this === Wrapper ? $Promise : this, x); + } + }); + _export(_export.S + _export.F * !(USE_NATIVE && _iterDetect(function (iter) { + $Promise.all(iter)['catch'](empty); + })), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = _perform(function () { + var values = []; + var index = 0; + var remaining = 1; + _forOf(iterable, false, function (promise) { + var $index = index++; + var alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.e) reject(result.v); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var reject = capability.reject; + var result = _perform(function () { + _forOf(iterable, false, function (promise) { + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if (result.e) reject(result.v); + return capability.promise; + } + }); + var STARTS_WITH = 'startsWith'; + var $startsWith = ''[STARTS_WITH]; + + _export(_export.P + _export.F * _failsIsRegexp(STARTS_WITH), 'String', { + startsWith: function startsWith(searchString /* , position = 0 */) { + var that = _stringContext(this, searchString, STARTS_WITH); + var index = _toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length)); + var search = String(searchString); + return $startsWith + ? $startsWith.call(that, search, index) + : that.slice(index, index + search.length) === search; + } + }); -_objectSap('isFrozen', function ($isFrozen) { - return function isFrozen(it) { - return _isObject(it) ? $isFrozen ? $isFrozen(it) : false : true; - }; -}); + // 20.1.2.4 Number.isNaN(number) -// 19.1.2.13 Object.isSealed(O) + _export(_export.S, 'Number', { + isNaN: function isNaN(number) { + // eslint-disable-next-line no-self-compare + return number != number; + } + }); -_objectSap('isSealed', function ($isSealed) { - return function isSealed(it) { - return _isObject(it) ? $isSealed ? $isSealed(it) : false : true; + // ========================================================================== + // Type checking utils + // ========================================================================== + var getConstructor = function getConstructor(input) { + return input !== null && typeof input !== 'undefined' ? input.constructor : null; }; -}); -// 19.1.2.11 Object.isExtensible(O) + var instanceOf = function instanceOf(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); + }; + var isNullOrUndefined = function isNullOrUndefined(input) { + return input === null || typeof input === 'undefined'; + }; -_objectSap('isExtensible', function ($isExtensible) { - return function isExtensible(it) { - return _isObject(it) ? $isExtensible ? $isExtensible(it) : true : false; + var isObject = function isObject(input) { + return getConstructor(input) === Object; }; -}); -// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) + var isNumber = function isNumber(input) { + return getConstructor(input) === Number && !Number.isNaN(input); + }; -var $getOwnPropertyDescriptor$1 = _objectGopd.f; + var isString = function isString(input) { + return getConstructor(input) === String; + }; -_objectSap('getOwnPropertyDescriptor', function () { - return function getOwnPropertyDescriptor(it, key) { - return $getOwnPropertyDescriptor$1(_toIobject(it), key); + var isBoolean = function isBoolean(input) { + return getConstructor(input) === Boolean; }; -}); -// 19.1.2.9 Object.getPrototypeOf(O) + var isFunction = function isFunction(input) { + return getConstructor(input) === Function; + }; + var isArray = function isArray(input) { + return Array.isArray(input); + }; + var isWeakMap = function isWeakMap(input) { + return instanceOf(input, WeakMap); + }; -_objectSap('getPrototypeOf', function () { - return function getPrototypeOf(it) { - return _objectGpo(_toObject(it)); + var isNodeList = function isNodeList(input) { + return instanceOf(input, NodeList); }; -}); -// 19.1.2.14 Object.keys(O) + var isElement = function isElement(input) { + return instanceOf(input, Element); + }; + var isTextNode = function isTextNode(input) { + return getConstructor(input) === Text; + }; + var isEvent = function isEvent(input) { + return instanceOf(input, Event); + }; -_objectSap('keys', function () { - return function keys(it) { - return _objectKeys(_toObject(it)); + var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); }; -}); -// 19.1.2.7 Object.getOwnPropertyNames(O) -_objectSap('getOwnPropertyNames', function () { - return _objectGopnExt.f; -}); + var isCue = function isCue(input) { + return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); + }; -// 19.1.3.1 Object.assign(target, source) + var isTrack = function isTrack(input) { + return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind); + }; + var isEmpty = function isEmpty(input) { + return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length; + }; -_export(_export.S + _export.F, 'Object', { assign: _objectAssign }); + var isUrl = function isUrl(input) { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } // Must be string from here -// 7.2.9 SameValue(x, y) -var _sameValue = Object.is || function is(x, y) { - // eslint-disable-next-line no-self-compare - return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; -}; -// 19.1.3.10 Object.is(value1, value2) + if (!isString(input)) { + return false; + } // Add the protocol if required + -_export(_export.S, 'Object', { is: _sameValue }); + var string = input; -var dP$3 = _objectDp.f; -var FProto = Function.prototype; -var nameRE = /^\s*function ([^ (]*)/; -var NAME = 'name'; + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = "http://".concat(input); + } -// 19.2.4.2 name -NAME in FProto || _descriptors && dP$3(FProto, NAME, { - configurable: true, - get: function () { try { - return ('' + this).match(nameRE)[1]; + return !isEmpty(new URL(string).hostname); } catch (e) { - return ''; + return false; } - } -}); - -_export(_export.S, 'String', { - // 21.1.2.4 String.raw(callSite, ...substitutions) - raw: function raw(callSite) { - var tpl = _toIobject(callSite.raw); - var len = _toLength(tpl.length); - var aLen = arguments.length; - var res = []; - var i = 0; - while (len > i) { - res.push(String(tpl[i++])); - if (i < aLen) res.push(String(arguments[i])); - } return res.join(''); - } -}); - -var fromCharCode = String.fromCharCode; -var $fromCodePoint = String.fromCodePoint; - -// length should be 1, old FF problem -_export(_export.S + _export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', { - // 21.1.2.2 String.fromCodePoint(...codePoints) - fromCodePoint: function fromCodePoint(x) { // eslint-disable-line no-unused-vars - var res = []; - var aLen = arguments.length; - var i = 0; - var code; - while (aLen > i) { - code = +arguments[i++]; - if (_toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point'); - res.push(code < 0x10000 - ? fromCharCode(code) - : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00) - ); - } return res.join(''); - } -}); - -// true -> String#at -// false -> String#codePointAt -var _stringAt = function (TO_STRING) { - return function (that, pos) { - var s = String(_defined(that)); - var i = _toInteger(pos); - var l = s.length; - var a, b; - if (i < 0 || i >= l) return TO_STRING ? '' : undefined; - a = s.charCodeAt(i); - return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff - ? TO_STRING ? s.charAt(i) : a - : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; - }; -}; - -var $at = _stringAt(false); -_export(_export.P, 'String', { - // 21.1.3.3 String.prototype.codePointAt(pos) - codePointAt: function codePointAt(pos) { - return $at(this, pos); - } -}); - -var _stringRepeat = function repeat(count) { - var str = String(_defined(this)); - var res = ''; - var n = _toInteger(count); - if (n < 0 || n == Infinity) throw RangeError("Count can't be negative"); - for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) res += str; - return res; -}; - -_export(_export.P, 'String', { - // 21.1.3.13 String.prototype.repeat(count) - repeat: _stringRepeat -}); - -// 7.2.8 IsRegExp(argument) - - -var MATCH = _wks('match'); -var _isRegexp = function (it) { - var isRegExp; - return _isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : _cof(it) == 'RegExp'); -}; - -// helper for String#{startsWith, endsWith, includes} + }; + var is$1 = { + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty + }; + // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // https://www.youtube.com/watch?v=NPM6172J22g -var _stringContext = function (that, searchString, NAME) { - if (_isRegexp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!"); - return String(_defined(that)); -}; + var supportsPassiveListeners = function () { + // Test via a getter in the options object to see if the passive property is accessed + var supported = false; -var MATCH$1 = _wks('match'); -var _failsIsRegexp = function (KEY) { - var re = /./; - try { - '/./'[KEY](re); - } catch (e) { try { - re[MATCH$1] = false; - return !'/./'[KEY](re); - } catch (f) { /* empty */ } - } return true; -}; - -var STARTS_WITH = 'startsWith'; -var $startsWith = ''[STARTS_WITH]; - -_export(_export.P + _export.F * _failsIsRegexp(STARTS_WITH), 'String', { - startsWith: function startsWith(searchString /* , position = 0 */) { - var that = _stringContext(this, searchString, STARTS_WITH); - var index = _toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length)); - var search = String(searchString); - return $startsWith - ? $startsWith.call(that, search, index) - : that.slice(index, index + search.length) === search; - } -}); - -var ENDS_WITH = 'endsWith'; -var $endsWith = ''[ENDS_WITH]; - -_export(_export.P + _export.F * _failsIsRegexp(ENDS_WITH), 'String', { - endsWith: function endsWith(searchString /* , endPosition = @length */) { - var that = _stringContext(this, searchString, ENDS_WITH); - var endPosition = arguments.length > 1 ? arguments[1] : undefined; - var len = _toLength(that.length); - var end = endPosition === undefined ? len : Math.min(_toLength(endPosition), len); - var search = String(searchString); - return $endsWith - ? $endsWith.call(that, search, end) - : that.slice(end - search.length, end) === search; - } -}); - -var INCLUDES = 'includes'; - -_export(_export.P + _export.F * _failsIsRegexp(INCLUDES), 'String', { - includes: function includes(searchString /* , position = 0 */) { - return !!~_stringContext(this, searchString, INCLUDES) - .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined); - } -}); - -// 21.2.5.3 get RegExp.prototype.flags - -var _flags = function () { - var that = _anObject(this); - var result = ''; - if (that.global) result += 'g'; - if (that.ignoreCase) result += 'i'; - if (that.multiline) result += 'm'; - if (that.unicode) result += 'u'; - if (that.sticky) result += 'y'; - return result; -}; - -// 21.2.5.3 get RegExp.prototype.flags() -if (_descriptors && /./g.flags != 'g') _objectDp.f(RegExp.prototype, 'flags', { - configurable: true, - get: _flags -}); - -var _fixReWks = function (KEY, length, exec) { - var SYMBOL = _wks(KEY); - var fns = exec(_defined, SYMBOL, ''[KEY]); - var strfn = fns[0]; - var rxfn = fns[1]; - if (_fails(function () { - var O = {}; - O[SYMBOL] = function () { return 7; }; - return ''[KEY](O) != 7; - })) { - _redefine(String.prototype, KEY, strfn); - _hide(RegExp.prototype, SYMBOL, length == 2 - // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) - // 21.2.5.11 RegExp.prototype[@@split](string, limit) - ? function (string, arg) { return rxfn.call(string, this, arg); } - // 21.2.5.6 RegExp.prototype[@@match](string) - // 21.2.5.9 RegExp.prototype[@@search](string) - : function (string) { return rxfn.call(string, this); } - ); - } -}; - -// @@match logic -_fixReWks('match', 1, function (defined, MATCH, $match) { - // 21.1.3.11 String.prototype.match(regexp) - return [function match(regexp) { - var O = defined(this); - var fn = regexp == undefined ? undefined : regexp[MATCH]; - return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); - }, $match]; -}); - -// @@replace logic -_fixReWks('replace', 2, function (defined, REPLACE, $replace) { - // 21.1.3.14 String.prototype.replace(searchValue, replaceValue) - return [function replace(searchValue, replaceValue) { - var O = defined(this); - var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; - return fn !== undefined - ? fn.call(searchValue, O, replaceValue) - : $replace.call(String(O), searchValue, replaceValue); - }, $replace]; -}); - -// @@split logic -_fixReWks('split', 2, function (defined, SPLIT, $split) { - var isRegExp = _isRegexp; - var _split = $split; - var $push = [].push; - var $SPLIT = 'split'; - var LENGTH = 'length'; - var LAST_INDEX = 'lastIndex'; - if ( - 'abbc'[$SPLIT](/(b)*/)[1] == 'c' || - 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || - 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 || - '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 || - '.'[$SPLIT](/()()/)[LENGTH] > 1 || - ''[$SPLIT](/.?/)[LENGTH] - ) { - var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group - // based on es5-shim implementation, need to rework it - $split = function (separator, limit) { - var string = String(this); - if (separator === undefined && limit === 0) return []; - // If `separator` is not a regex, use native split - if (!isRegExp(separator)) return _split.call(string, separator, limit); - var output = []; - var flags = (separator.ignoreCase ? 'i' : '') + - (separator.multiline ? 'm' : '') + - (separator.unicode ? 'u' : '') + - (separator.sticky ? 'y' : ''); - var lastLastIndex = 0; - var splitLimit = limit === undefined ? 4294967295 : limit >>> 0; - // Make `global` and avoid `lastIndex` issues by working with a copy - var separatorCopy = new RegExp(separator.source, flags + 'g'); - var separator2, match, lastIndex, lastLength, i; - // Doesn't need flags gy, but they don't hurt - if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags); - while (match = separatorCopy.exec(string)) { - // `separatorCopy.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0][LENGTH]; - if (lastIndex > lastLastIndex) { - output.push(string.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG - // eslint-disable-next-line no-loop-func - if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () { - for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined; - }); - if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1)); - lastLength = match[0][LENGTH]; - lastLastIndex = lastIndex; - if (output[LENGTH] >= splitLimit) break; + var options = Object.defineProperty({}, 'passive', { + get: function get() { + supported = true; + return null; } - if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop - } - if (lastLastIndex === string[LENGTH]) { - if (lastLength || !separatorCopy.test('')) output.push(''); - } else output.push(string.slice(lastLastIndex)); - return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output; - }; - // Chakra, V8 - } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) { - $split = function (separator, limit) { - return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit); - }; - } - // 21.1.3.17 String.prototype.split(separator, limit) - return [function split(separator, limit) { - var O = defined(this); - var fn = separator == undefined ? undefined : separator[SPLIT]; - return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit); - }, $split]; -}); - -// @@search logic -_fixReWks('search', 1, function (defined, SEARCH, $search) { - // 21.1.3.15 String.prototype.search(regexp) - return [function search(regexp) { - var O = defined(this); - var fn = regexp == undefined ? undefined : regexp[SEARCH]; - return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); - }, $search]; -}); - -var _createProperty = function (object, index, value) { - if (index in object) _objectDp.f(object, index, _propertyDesc(0, value)); - else object[index] = value; -}; - -_export(_export.S + _export.F * !_iterDetect(function (iter) { }), 'Array', { - // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) - from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { - var O = _toObject(arrayLike); - var C = typeof this == 'function' ? this : Array; - var aLen = arguments.length; - var mapfn = aLen > 1 ? arguments[1] : undefined; - var mapping = mapfn !== undefined; - var index = 0; - var iterFn = core_getIteratorMethod(O); - var length, result, step, iterator; - if (mapping) mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); - // if object isn't iterable or it's array with default iterator - use simple case - if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) { - for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) { - _createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value); - } - } else { - length = _toLength(O.length); - for (result = new C(length); length > index; index++) { - _createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); - } + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) {// Do nothing } - result.length = index; - return result; - } -}); - -// WebKit Array.of isn't generic -_export(_export.S + _export.F * _fails(function () { - function F() { /* empty */ } - return !(Array.of.call(F) instanceof F); -}), 'Array', { - // 22.1.2.3 Array.of( ...items) - of: function of(/* ...args */) { - var index = 0; - var aLen = arguments.length; - var result = new (typeof this == 'function' ? this : Array)(aLen); - while (aLen > index) _createProperty(result, index, arguments[index++]); - result.length = aLen; - return result; - } -}); - -// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length) - - -_export(_export.P, 'Array', { copyWithin: _arrayCopyWithin }); - -_addToUnscopables('copyWithin'); - -// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined) - -var $find = _arrayMethods(5); -var KEY = 'find'; -var forced = true; -// Shouldn't skip holes -if (KEY in []) Array(1)[KEY](function () { forced = false; }); -_export(_export.P + _export.F * forced, 'Array', { - find: function find(callbackfn /* , that = undefined */) { - return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); - } -}); -_addToUnscopables(KEY); - -// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined) - -var $find$1 = _arrayMethods(6); -var KEY$1 = 'findIndex'; -var forced$1 = true; -// Shouldn't skip holes -if (KEY$1 in []) Array(1)[KEY$1](function () { forced$1 = false; }); -_export(_export.P + _export.F * forced$1, 'Array', { - findIndex: function findIndex(callbackfn /* , that = undefined */) { - return $find$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); - } -}); -_addToUnscopables(KEY$1); -// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length) + return supported; + }(); // Toggle event listener -_export(_export.P, 'Array', { fill: _arrayFill }); + function toggleListener(element, event, callback) { + var _this = this; -_addToUnscopables('fill'); + var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; -// 20.1.2.2 Number.isFinite(number) + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is$1.empty(event) || !is$1.function(callback)) { + return; + } // Allow multiple events -var _isFinite = _global.isFinite; - -_export(_export.S, 'Number', { - isFinite: function isFinite(it) { - return typeof it == 'number' && _isFinite(it); - } -}); -// 20.1.2.3 Number.isInteger(number) + var events = event.split(' '); // Build options + // Default to just the capture boolean for browsers with no passive listener support -var floor$1 = Math.floor; -var _isInteger = function isInteger(it) { - return !_isObject(it) && isFinite(it) && floor$1(it) === it; -}; + var options = capture; // If passive events listeners are supported -// 20.1.2.3 Number.isInteger(number) - - -_export(_export.S, 'Number', { isInteger: _isInteger }); + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: passive, + // Whether the listener is a capturing listener or not + capture: capture + }; + } // If a single node is passed, bind the event listener -// 20.1.2.5 Number.isSafeInteger(number) + events.forEach(function (type) { + if (_this && _this.eventListeners && toggle) { + // Cache event listener + _this.eventListeners.push({ + element: element, + type: type, + callback: callback, + options: options + }); + } -var abs = Math.abs; + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); + } // Bind event handler + + function on(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, true, passive, capture); + } // Unbind event handler + + function off(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, false, passive, capture); + } // Bind once-only event handler + + function once(element) { + var _this2 = this; + + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + var onceCallback = function onceCallback() { + off(element, events, onceCallback, passive, capture); + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } -_export(_export.S, 'Number', { - isSafeInteger: function isSafeInteger(number) { - return _isInteger(number) && abs(number) <= 0x1fffffffffffff; - } -}); + callback.apply(_this2, args); + }; -// 20.1.2.4 Number.isNaN(number) + toggleListener.call(this, element, events, onceCallback, true, passive, capture); + } // Trigger event + + function triggerEvent(element) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + // Bail if no element + if (!is$1.element(element) || is$1.empty(type)) { + return; + } // Create and dispatch the event + + + var event = new CustomEvent(type, { + bubbles: bubbles, + detail: Object.assign({}, detail, { + plyr: this + }) + }); // Dispatch the event + + element.dispatchEvent(event); + } // Unbind all cached event listeners + + function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(function (item) { + var element = item.element, + type = item.type, + callback = item.callback, + options = item.options; + element.removeEventListener(type, callback, options); + }); + this.eventListeners = []; + } + } // Run method when / if player is ready + function ready() { + var _this3 = this; -_export(_export.S, 'Number', { - isNaN: function isNaN(number) { - // eslint-disable-next-line no-self-compare - return number != number; + return new Promise(function (resolve) { + return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve); + }).then(function () {}); } -}); - -// 20.1.2.1 Number.EPSILON - -_export(_export.S, 'Number', { EPSILON: Math.pow(2, -52) }); + function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). -// 20.1.2.10 Number.MIN_SAFE_INTEGER + Array.from(targets).reverse().forEach(function (element, index) { + var child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling. + var parent = element.parentNode; + var sibling = element.nextSibling; // Wrap the element (is automatically removed from its current + // parent). -_export(_export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff }); + child.appendChild(element); // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. -// 20.1.2.6 Number.MAX_SAFE_INTEGER + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); + } // Set attributes + function setAttributes(element, attributes) { + if (!is$1.element(element) || is$1.empty(attributes)) { + return; + } // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" -_export(_export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff }); -// 20.2.2.20 Math.log1p(x) -var _mathLog1p = Math.log1p || function log1p(x) { - return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x); -}; + Object.entries(attributes).filter(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + value = _ref2[1]; -// 20.2.2.3 Math.acosh(x) + return !is$1.nullOrUndefined(value); + }).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + return element.setAttribute(key, value); + }); + } // Create a DocumentFragment -var sqrt = Math.sqrt; -var $acosh = Math.acosh; + function createElement(type, attributes, text) { + // Create a new <element> + var element = document.createElement(type); // Set all passed attributes -_export(_export.S + _export.F * !($acosh - // V8 bug: https://code.google.com/p/v8/issues/detail?id=3509 - && Math.floor($acosh(Number.MAX_VALUE)) == 710 - // Tor Browser bug: Math.acosh(Infinity) -> NaN - && $acosh(Infinity) == Infinity -), 'Math', { - acosh: function acosh(x) { - return (x = +x) < 1 ? NaN : x > 94906265.62425156 - ? Math.log(x) + Math.LN2 - : _mathLog1p(x - 1 + sqrt(x - 1) * sqrt(x + 1)); - } -}); + if (is$1.object(attributes)) { + setAttributes(element, attributes); + } // Add text node -// 20.2.2.5 Math.asinh(x) -var $asinh = Math.asinh; + if (is$1.string(text)) { + element.innerText = text; + } // Return built element -function asinh(x) { - return !isFinite(x = +x) || x == 0 ? x : x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1)); -} -// Tor Browser bug: Math.asinh(0) -> -0 -_export(_export.S + _export.F * !($asinh && 1 / $asinh(0) > 0), 'Math', { asinh: asinh }); + return element; + } // Inaert an element after another -// 20.2.2.7 Math.atanh(x) + function insertAfter(element, target) { + if (!is$1.element(element) || !is$1.element(target)) { + return; + } -var $atanh = Math.atanh; + target.parentNode.insertBefore(element, target.nextSibling); + } // Insert a DocumentFragment -// Tor Browser bug: Math.atanh(-0) -> 0 -_export(_export.S + _export.F * !($atanh && 1 / $atanh(-0) < 0), 'Math', { - atanh: function atanh(x) { - return (x = +x) == 0 ? x : Math.log((1 + x) / (1 - x)) / 2; - } -}); + function insertElement(type, parent, attributes, text) { + if (!is$1.element(parent)) { + return; + } -// 20.2.2.28 Math.sign(x) -var _mathSign = Math.sign || function sign(x) { - // eslint-disable-next-line no-self-compare - return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1; -}; + parent.appendChild(createElement(type, attributes, text)); + } // Remove element(s) -// 20.2.2.9 Math.cbrt(x) + function removeElement(element) { + if (is$1.nodeList(element) || is$1.array(element)) { + Array.from(element).forEach(removeElement); + return; + } + if (!is$1.element(element) || !is$1.element(element.parentNode)) { + return; + } + element.parentNode.removeChild(element); + } // Remove all child elements -_export(_export.S, 'Math', { - cbrt: function cbrt(x) { - return _mathSign(x = +x) * Math.pow(Math.abs(x), 1 / 3); - } -}); + function emptyElement(element) { + if (!is$1.element(element)) { + return; + } -// 20.2.2.11 Math.clz32(x) + var length = element.childNodes.length; + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } + } // Replace element -_export(_export.S, 'Math', { - clz32: function clz32(x) { - return (x >>>= 0) ? 31 - Math.floor(Math.log(x + 0.5) * Math.LOG2E) : 32; - } -}); + function replaceElement(newChild, oldChild) { + if (!is$1.element(oldChild) || !is$1.element(oldChild.parentNode) || !is$1.element(newChild)) { + return null; + } -// 20.2.2.12 Math.cosh(x) + oldChild.parentNode.replaceChild(newChild, oldChild); + return newChild; + } // Get an attribute object from a string selector + + function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + if (!is$1.string(sel) || is$1.empty(sel)) { + return {}; + } -var exp = Math.exp; + var attributes = {}; + var existing = existingAttributes; + sel.split(',').forEach(function (s) { + // Remove whitespace + var selector = s.trim(); + var className = selector.replace('.', ''); + var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value + + var parts = stripped.split('='); + var key = parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character + + var start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is$1.object(existing) && is$1.string(existing.class)) { + existing.class += " ".concat(className); + } -_export(_export.S, 'Math', { - cosh: function cosh(x) { - return (exp(x = +x) + exp(-x)) / 2; - } -}); + attributes.class = className; + break; -// 20.2.2.14 Math.expm1(x) -var $expm1 = Math.expm1; -var _mathExpm1 = (!$expm1 - // Old FF bug - || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168 - // Tor Browser bug - || $expm1(-2e-17) != -2e-17 -) ? function expm1(x) { - return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1; -} : $expm1; + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; -// 20.2.2.14 Math.expm1(x) + case '[': + // Attribute selector + attributes[key] = value; + break; + default: + break; + } + }); + return attributes; + } // Toggle hidden + function toggleHidden(element, hidden) { + if (!is$1.element(element)) { + return; + } -_export(_export.S + _export.F * (_mathExpm1 != Math.expm1), 'Math', { expm1: _mathExpm1 }); + var hide = hidden; -// 20.2.2.16 Math.fround(x) + if (!is$1.boolean(hide)) { + hide = !element.hidden; + } -var pow = Math.pow; -var EPSILON = pow(2, -52); -var EPSILON32 = pow(2, -23); -var MAX32 = pow(2, 127) * (2 - EPSILON32); -var MIN32 = pow(2, -126); + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } + } // Mirror Element.classList.toggle, with IE compatibility for "force" argument -var roundTiesToEven = function (n) { - return n + 1 / EPSILON - 1 / EPSILON; -}; + function toggleClass(element, className, force) { + if (is$1.nodeList(element)) { + return Array.from(element).map(function (e) { + return toggleClass(e, className, force); + }); + } -var _mathFround = Math.fround || function fround(x) { - var $abs = Math.abs(x); - var $sign = _mathSign(x); - var a, result; - if ($abs < MIN32) return $sign * roundTiesToEven($abs / MIN32 / EPSILON32) * MIN32 * EPSILON32; - a = (1 + EPSILON32 / EPSILON) * $abs; - result = a - (a - $abs); - // eslint-disable-next-line no-self-compare - if (result > MAX32 || result != result) return $sign * Infinity; - return $sign * result; -}; + if (is$1.element(element)) { + var method = 'toggle'; -// 20.2.2.16 Math.fround(x) + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } + element.classList[method](className); + return element.classList.contains(className); + } -_export(_export.S, 'Math', { fround: _mathFround }); + return false; + } // Has class name -// 20.2.2.17 Math.hypot([value1[, value2[, … ]]]) + function hasClass(element, className) { + return is$1.element(element) && element.classList.contains(className); + } // Element matches selector -var abs$1 = Math.abs; + function matches(element, selector) { -_export(_export.S, 'Math', { - hypot: function hypot(value1, value2) { // eslint-disable-line no-unused-vars - var sum = 0; - var i = 0; - var aLen = arguments.length; - var larg = 0; - var arg, div; - while (i < aLen) { - arg = abs$1(arguments[i++]); - if (larg < arg) { - div = larg / arg; - sum = sum * div * div + 1; - larg = arg; - } else if (arg > 0) { - div = arg / larg; - sum += div * div; - } else sum += arg; + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); } - return larg === Infinity ? Infinity : larg * Math.sqrt(sum); - } -}); - -// 20.2.2.18 Math.imul(x, y) - -var $imul = Math.imul; - -// some WebKit versions fails with big numbers, some has wrong arity -_export(_export.S + _export.F * _fails(function () { - return $imul(0xffffffff, 5) != -5 || $imul.length != 2; -}), 'Math', { - imul: function imul(x, y) { - var UINT16 = 0xffff; - var xn = +x; - var yn = +y; - var xl = UINT16 & xn; - var yl = UINT16 & yn; - return 0 | xl * yl + ((UINT16 & xn >>> 16) * yl + xl * (UINT16 & yn >>> 16) << 16 >>> 0); - } -}); -// 20.2.2.20 Math.log1p(x) + var matches = match; + return matches.call(element, selector); + } // Find all elements + function getElements(selector) { + return this.elements.container.querySelectorAll(selector); + } // Find a single element -_export(_export.S, 'Math', { log1p: _mathLog1p }); + function getElement(selector) { + return this.elements.container.querySelector(selector); + } // Trap focus inside container -// 20.2.2.21 Math.log10(x) + function trapFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (!is$1.element(element)) { + return; + } -_export(_export.S, 'Math', { - log10: function log10(x) { - return Math.log(x) * Math.LOG10E; - } -}); + var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + var first = focusable[0]; + var last = focusable[focusable.length - 1]; -// 20.2.2.22 Math.log2(x) + var trap = function trap(event) { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } // Get the current focused element -_export(_export.S, 'Math', { - log2: function log2(x) { - return Math.log(x) / Math.LN2; - } -}); + var focused = document.activeElement; -// 20.2.2.28 Math.sign(x) + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); + } // Set focus and tab focus class -_export(_export.S, 'Math', { sign: _mathSign }); + function setFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; -// 20.2.2.30 Math.sinh(x) + if (!is$1.element(element)) { + return; + } // Set regular focus -var exp$1 = Math.exp; + element.focus({ + preventScroll: true + }); // If we want to mimic keyboard focus via tab -// V8 near Chromium 38 has a problem with very small numbers -_export(_export.S + _export.F * _fails(function () { - return !Math.sinh(-2e-17) != -2e-17; -}), 'Math', { - sinh: function sinh(x) { - return Math.abs(x = +x) < 1 - ? (_mathExpm1(x) - _mathExpm1(-x)) / 2 - : (exp$1(x - 1) - exp$1(-x - 1)) * (Math.E / 2); + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } } -}); - -// 20.2.2.33 Math.tanh(x) + var transitionEndEvent = function () { + var element = document.createElement('span'); + var events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + var type = Object.keys(events).find(function (event) { + return element.style[event] !== undefined; + }); + return is$1.string(type) ? events[type] : false; + }(); // Force repaint of element -var exp$2 = Math.exp; + function repaint(element) { + setTimeout(function () { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line -_export(_export.S, 'Math', { - tanh: function tanh(x) { - var a = _mathExpm1(x = +x); - var b = _mathExpm1(-x); - return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (exp$2(x) + exp$2(-x)); + toggleHidden(element, false); + } catch (e) {// Do nothing + } + }, 0); } -}); -// 20.2.2.34 Math.trunc(x) + // ========================================================================== + // Browser sniffing + // Unfortunately, due to mixed support, UA sniffing is required + // ========================================================================== + var browser = { + isIE: + /* @cc_on!@ */ + !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) + }; + var defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora' + }; // Check for feature support -_export(_export.S, 'Math', { - trunc: function trunc(it) { - return (it > 0 ? Math.floor : Math.ceil)(it); - } -}); + var support = { + // Basic support + audio: 'canPlayType' in document.createElement('audio'), + video: 'canPlayType' in document.createElement('video'), + // Check for support + // Basic functionality vs full UI + check: function check(type, provider, playsinline) { + var canPlayInline = browser.isIPhone && playsinline && support.playsinline; + var api = support[type] || provider !== 'html5'; + var ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); + return { + api: api, + ui: ui + }; + }, + // Picture-in-picture support + // Safari & Chrome only currently + pip: function () { + if (browser.isIPhone) { + return false; + } // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls -// https://github.com/tc39/Array.prototype.includes -var $includes = _arrayIncludes(true); + if (is$1.function(createElement('video').webkitSetPresentationMode)) { + return true; + } // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture -_export(_export.P, 'Array', { - includes: function includes(el /* , fromIndex = 0 */) { - return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); - } -}); -_addToUnscopables('includes'); + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } -var isEnum$1 = _objectPie.f; -var _objectToArray = function (isEntries) { - return function (it) { - var O = _toIobject(it); - var keys = _objectKeys(O); - var length = keys.length; - var i = 0; - var result = []; - var key; - while (length > i) if (isEnum$1.call(O, key = keys[i++])) { - result.push(isEntries ? [key, O[key]] : O[key]); - } return result; - }; -}; + return false; + }(), + // Airplay support + // Safari only currently + airplay: is$1.function(window.WebKitPlaybackTargetAvailabilityEvent), + // Inline playback support + // https://webkit.org/blog/6784/new-video-policies-for-ios/ + playsinline: 'playsInline' in document.createElement('video'), + // Check for mime type support against a player instance + // Credits: http://diveintohtml5.info/everything.html + // Related: http://www.leanbackplayer.com/test/h5mt.html + mime: function mime(input) { + if (is$1.empty(input)) { + return false; + } -// https://github.com/tc39/proposal-object-values-entries + var _input$split = input.split('/'), + _input$split2 = _slicedToArray(_input$split, 1), + mediaType = _input$split2[0]; -var $values = _objectToArray(false); + var type = input; // Verify we're using HTML5 and there's no media type mismatch -_export(_export.S, 'Object', { - values: function values(it) { - return $values(it); - } -}); + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } // Add codec if required -// https://github.com/tc39/proposal-object-values-entries -var $entries = _objectToArray(true); + if (Object.keys(defaultCodecs).includes(type)) { + type += "; codecs=\"".concat(defaultCodecs[input], "\""); + } -_export(_export.S, 'Object', { - entries: function entries(it) { - return $entries(it); - } -}); + try { + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); + } catch (e) { + return false; + } + }, + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), + // <input type="range"> Sliders + rangeInput: function () { + var range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; + }(), + // Touch + // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event + touch: 'ontouchstart' in document.documentElement, + // Detect transitions support + transitions: transitionEndEvent !== false, + // Reduced motion iOS & MacOS setting + // https://webkit.org/blog/7551/responsive-design-for-motion/ + reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches + }; -// https://github.com/tc39/proposal-object-getownpropertydescriptors + var html5 = { + getSources: function getSources() { + var _this = this; + if (!this.isHTML5) { + return []; + } + var sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified) + return sources.filter(function (source) { + var type = source.getAttribute('type'); + if (is$1.empty(type)) { + return true; + } + return support.mime.call(_this, type); + }); + }, + // Get quality levels + getQualityOptions: function getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources.call(this).map(function (source) { + return Number(source.getAttribute('size')); + }).filter(Boolean); + }, + extend: function extend() { + if (!this.isHTML5) { + return; + } -_export(_export.S, 'Object', { - getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) { - var O = _toIobject(object); - var getDesc = _objectGopd.f; - var keys = _ownKeys(O); - var result = {}; - var i = 0; - var key, desc; - while (keys.length > i) { - desc = getDesc(O, key = keys[i++]); - if (desc !== undefined) _createProperty(result, key, desc); - } - return result; - } -}); + var player = this; // Quality -// https://github.com/tc39/proposal-string-pad-start-end + Object.defineProperty(player.media, 'quality', { + get: function get() { + // Get sources + var sources = html5.getSources.call(player); + var source = sources.find(function (source) { + return source.getAttribute('src') === player.source; + }); // Return size, if match is found + return source && Number(source.getAttribute('size')); + }, + set: function set(input) { + // Get sources + var sources = html5.getSources.call(player); // Get first match for requested size + var source = sources.find(function (source) { + return Number(source.getAttribute('size')) === input; + }); // No matching source found + if (!source) { + return; + } // Get current state -var _stringPad = function (that, maxLength, fillString, left) { - var S = String(_defined(that)); - var stringLength = S.length; - var fillStr = fillString === undefined ? ' ' : String(fillString); - var intMaxLength = _toLength(maxLength); - if (intMaxLength <= stringLength || fillStr == '') return S; - var fillLen = intMaxLength - stringLength; - var stringFiller = _stringRepeat.call(fillStr, Math.ceil(fillLen / fillStr.length)); - if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen); - return left ? stringFiller + S : S + stringFiller; -}; -var navigator$1 = _global.navigator; + var _player$media = player.media, + currentTime = _player$media.currentTime, + paused = _player$media.paused, + preload = _player$media.preload, + readyState = _player$media.readyState; // Set new source -var _userAgent = navigator$1 && navigator$1.userAgent || ''; + player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044) -// https://github.com/tc39/proposal-string-pad-start-end + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', function () { + player.currentTime = currentTime; // Resume playing + if (!paused) { + player.play(); + } + }); // Load new source + player.media.load(); + } // Trigger change event -// https://github.com/zloirock/core-js/issues/280 -_export(_export.P + _export.F * /Version\/10\.\d+(\.\d+)? Safari\//.test(_userAgent), 'String', { - padStart: function padStart(maxLength /* , fillString = ' ' */) { - return _stringPad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true); - } -}); + triggerEvent.call(player, player.media, 'qualitychange', false, { + quality: input + }); + } + }); + }, + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests: function cancelRequests() { + if (!this.isHTML5) { + return; + } // Remove child sources -// https://github.com/tc39/proposal-string-pad-start-end + removeElement(html5.getSources.call(this)); // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + this.media.load(); // Debugging -// https://github.com/zloirock/core-js/issues/280 -_export(_export.P + _export.F * /Version\/10\.\d+(\.\d+)? Safari\//.test(_userAgent), 'String', { - padEnd: function padEnd(maxLength /* , fillString = ' ' */) { - return _stringPad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false); - } -}); - -// ie9- setTimeout & setInterval additional parameters fix - - - -var slice = [].slice; -var MSIE = /MSIE .\./.test(_userAgent); // <- dirty ie9- check -var wrap$1 = function (set) { - return function (fn, time /* , ...args */) { - var boundArgs = arguments.length > 2; - var args = boundArgs ? slice.call(arguments, 2) : false; - return set(boundArgs ? function () { - // eslint-disable-next-line no-new-func - (typeof fn == 'function' ? fn : Function(fn)).apply(this, args); - } : fn, time); - }; -}; -_export(_export.G + _export.B + _export.F * MSIE, { - setTimeout: wrap$1(_global.setTimeout), - setInterval: wrap$1(_global.setInterval) -}); - -_export(_export.G + _export.B, { - setImmediate: _task.set, - clearImmediate: _task.clear -}); - -var ITERATOR$4 = _wks('iterator'); -var TO_STRING_TAG = _wks('toStringTag'); -var ArrayValues = _iterators.Array; - -var DOMIterables = { - CSSRuleList: true, // TODO: Not spec compliant, should be false. - CSSStyleDeclaration: false, - CSSValueList: false, - ClientRectList: false, - DOMRectList: false, - DOMStringList: false, - DOMTokenList: true, - DataTransferItemList: false, - FileList: false, - HTMLAllCollection: false, - HTMLCollection: false, - HTMLFormElement: false, - HTMLSelectElement: false, - MediaList: true, // TODO: Not spec compliant, should be false. - MimeTypeArray: false, - NamedNodeMap: false, - NodeList: true, - PaintRequestList: false, - Plugin: false, - PluginArray: false, - SVGLengthList: false, - SVGNumberList: false, - SVGPathSegList: false, - SVGPointList: false, - SVGStringList: false, - SVGTransformList: false, - SourceBufferList: false, - StyleSheetList: true, // TODO: Not spec compliant, should be false. - TextTrackCueList: false, - TextTrackList: false, - TouchList: false -}; - -for (var collections = _objectKeys(DOMIterables), i$1 = 0; i$1 < collections.length; i$1++) { - var NAME$1 = collections[i$1]; - var explicit = DOMIterables[NAME$1]; - var Collection = _global[NAME$1]; - var proto = Collection && Collection.prototype; - var key; - if (proto) { - if (!proto[ITERATOR$4]) _hide(proto, ITERATOR$4, ArrayValues); - if (!proto[TO_STRING_TAG]) _hide(proto, TO_STRING_TAG, NAME$1); - _iterators[NAME$1] = ArrayValues; - if (explicit) for (key in es6_array_iterator) if (!proto[key]) _redefine(proto, key, es6_array_iterator[key], true); - } -} - -var runtime = createCommonjsModule(function (module) { -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -!(function(global) { - - var Op = Object.prototype; - var hasOwn = Op.hasOwnProperty; - var undefined; // More compressible than void 0. - var $Symbol = typeof Symbol === "function" ? Symbol : {}; - var iteratorSymbol = $Symbol.iterator || "@@iterator"; - var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; - var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; - - var inModule = 'object' === "object"; - var runtime = global.regeneratorRuntime; - if (runtime) { - if (inModule) { - // If regeneratorRuntime is defined globally and we're in a module, - // make the exports object identical to regeneratorRuntime. - module.exports = runtime; + this.debug.log('Cancelled network requests'); } - // Don't bother evaluating the rest of this file if the runtime was - // already defined globally. - return; - } + }; - // Define the runtime globally (as expected by generated code) as either - // module.exports (if we're in a module) or a new, empty object. - runtime = global.regeneratorRuntime = inModule ? module.exports : {}; + // ========================================================================== - function wrap(innerFn, outerFn, self, tryLocsList) { - // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. - var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; - var generator = Object.create(protoGenerator.prototype); - var context = new Context(tryLocsList || []); + function dedupe(array) { + if (!is$1.array(array)) { + return array; + } - // The ._invoke method unifies the implementations of the .next, - // .throw, and .return methods. - generator._invoke = makeInvokeMethod(innerFn, self, context); + return array.filter(function (item, index) { + return array.indexOf(item) === index; + }); + } // Get the closest value in an array - return generator; - } - runtime.wrap = wrap; - - // Try/catch helper to minimize deoptimizations. Returns a completion - // record like context.tryEntries[i].completion. This interface could - // have been (and was previously) designed to take a closure to be - // invoked without arguments, but in all the cases we care about we - // already have an existing method we want to call, so there's no need - // to create a new function object. We can even get away with assuming - // the method takes exactly one argument, since that happens to be true - // in every case, so we don't have to touch the arguments object. The - // only additional allocation required is the completion record, which - // has a stable shape and so hopefully should be cheap to allocate. - function tryCatch(fn, obj, arg) { - try { - return { type: "normal", arg: fn.call(obj, arg) }; - } catch (err) { - return { type: "throw", arg: err }; + function closest(array, value) { + if (!is$1.array(array) || !array.length) { + return null; } - } - var GenStateSuspendedStart = "suspendedStart"; - var GenStateSuspendedYield = "suspendedYield"; - var GenStateExecuting = "executing"; - var GenStateCompleted = "completed"; - - // Returning this object from the innerFn has the same effect as - // breaking out of the dispatch switch statement. - var ContinueSentinel = {}; - - // Dummy constructor functions that we use as the .constructor and - // .constructor.prototype properties for functions that return Generator - // objects. For full spec compliance, you may wish to configure your - // minifier not to mangle the names of these two functions. - function Generator() {} - function GeneratorFunction() {} - function GeneratorFunctionPrototype() {} - - // This is a polyfill for %IteratorPrototype% for environments that - // don't natively support it. - var IteratorPrototype = {}; - IteratorPrototype[iteratorSymbol] = function () { - return this; - }; - - var getProto = Object.getPrototypeOf; - var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); - if (NativeIteratorPrototype && - NativeIteratorPrototype !== Op && - hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { - // This environment has a native %IteratorPrototype%; use it instead - // of the polyfill. - IteratorPrototype = NativeIteratorPrototype; - } - - var Gp = GeneratorFunctionPrototype.prototype = - Generator.prototype = Object.create(IteratorPrototype); - GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; - GeneratorFunctionPrototype.constructor = GeneratorFunction; - GeneratorFunctionPrototype[toStringTagSymbol] = - GeneratorFunction.displayName = "GeneratorFunction"; - - // Helper for defining the .next, .throw, and .return methods of the - // Iterator interface in terms of a single ._invoke method. - function defineIteratorMethods(prototype) { - ["next", "throw", "return"].forEach(function(method) { - prototype[method] = function(arg) { - return this._invoke(method, arg); - }; + return array.reduce(function (prev, curr) { + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; }); } - runtime.isGeneratorFunction = function(genFun) { - var ctor = typeof genFun === "function" && genFun.constructor; - return ctor - ? ctor === GeneratorFunction || - // For the native GeneratorFunction constructor, the best we can - // do is to check its .name property. - (ctor.displayName || ctor.name) === "GeneratorFunction" - : false; - }; + function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); + } // Get a nested value in an object - runtime.mark = function(genFun) { - if (Object.setPrototypeOf) { - Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); - } else { - genFun.__proto__ = GeneratorFunctionPrototype; - if (!(toStringTagSymbol in genFun)) { - genFun[toStringTagSymbol] = "GeneratorFunction"; - } - } - genFun.prototype = Object.create(Gp); - return genFun; - }; - - // Within the body of any async function, `await x` is transformed to - // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test - // `hasOwn.call(value, "__await")` to determine if the yielded value is - // meant to be awaited. - runtime.awrap = function(arg) { - return { __await: arg }; - }; + function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); + } // Deep extend destination object with N more objects - function AsyncIterator(generator) { - function invoke(method, arg, resolve, reject) { - var record = tryCatch(generator[method], generator, arg); - if (record.type === "throw") { - reject(record.arg); - } else { - var result = record.arg; - var value = result.value; - if (value && - typeof value === "object" && - hasOwn.call(value, "__await")) { - return Promise.resolve(value.__await).then(function(value) { - invoke("next", value, resolve, reject); - }, function(err) { - invoke("throw", err, resolve, reject); - }); - } + function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - return Promise.resolve(value).then(function(unwrapped) { - // When a yielded Promise is resolved, its final value becomes - // the .value of the Promise<{value,done}> result for the - // current iteration. If the Promise is rejected, however, the - // result for this iteration will be rejected with the same - // reason. Note that rejections of yielded Promises are not - // thrown back into the generator function, as is the case - // when an awaited Promise is rejected. This difference in - // behavior between yield and await is important, because it - // allows the consumer to decide what to do with the yielded - // rejection (swallow it and continue, manually .throw it back - // into the generator, abandon iteration, whatever). With - // await, by contrast, there is no opportunity to examine the - // rejection reason outside the generator function, so the - // only option is to throw it from the await expression, and - // let the generator function handle the exception. - result.value = unwrapped; - resolve(result); - }, reject); - } + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; } - if (typeof global.process === "object" && global.process.domain) { - invoke = global.process.domain.bind(invoke); + if (!sources.length) { + return target; } - var previousPromise; - - function enqueue(method, arg) { - function callInvokeWithMethodAndArg() { - return new Promise(function(resolve, reject) { - invoke(method, arg, resolve, reject); - }); - } + var source = sources.shift(); - return previousPromise = - // If enqueue has been called before, then we want to wait until - // all previous Promises have been resolved before calling invoke, - // so that results are always delivered in the correct order. If - // enqueue has not been called before, then it is important to - // call invoke immediately, without waiting on a callback to fire, - // so that the async generator function has the opportunity to do - // any necessary setup in a predictable way. This predictability - // is why the Promise constructor synchronously invokes its - // executor callback, and why async functions synchronously - // execute code before the first await. Since we implement simple - // async functions in terms of async generators, it is especially - // important to get this right, even though it requires care. - previousPromise ? previousPromise.then( - callInvokeWithMethodAndArg, - // Avoid propagating failures to Promises returned by later - // invocations of the iterator. - callInvokeWithMethodAndArg - ) : callInvokeWithMethodAndArg(); + if (!is$1.object(source)) { + return target; } - // Define the unified helper method that is used to implement .next, - // .throw, and .return (see defineIteratorMethods). - this._invoke = enqueue; - } - - defineIteratorMethods(AsyncIterator.prototype); - AsyncIterator.prototype[asyncIteratorSymbol] = function () { - return this; - }; - runtime.AsyncIterator = AsyncIterator; - - // Note that simple async functions are implemented on top of - // AsyncIterator objects; they just return a Promise for the value of - // the final result produced by the iterator. - runtime.async = function(innerFn, outerFn, self, tryLocsList) { - var iter = new AsyncIterator( - wrap(innerFn, outerFn, self, tryLocsList) - ); - - return runtime.isGeneratorFunction(outerFn) - ? iter // If outerFn is a generator, return the full iterator. - : iter.next().then(function(result) { - return result.done ? result.value : iter.next(); - }); - }; - - function makeInvokeMethod(innerFn, self, context) { - var state = GenStateSuspendedStart; - - return function invoke(method, arg) { - if (state === GenStateExecuting) { - throw new Error("Generator is already running"); - } - - if (state === GenStateCompleted) { - if (method === "throw") { - throw arg; + Object.keys(source).forEach(function (key) { + if (is$1.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); } - // Be forgiving, per 25.3.3.3.3 of the spec: - // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume - return doneResult(); + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); } + }); + return extend.apply(void 0, [target].concat(sources)); + } - context.method = method; - context.arg = arg; - - while (true) { - var delegate = context.delegate; - if (delegate) { - var delegateResult = maybeInvokeDelegate(delegate, context); - if (delegateResult) { - if (delegateResult === ContinueSentinel) continue; - return delegateResult; - } - } - - if (context.method === "next") { - // Setting context._sent for legacy support of Babel's - // function.sent implementation. - context.sent = context._sent = context.arg; - - } else if (context.method === "throw") { - if (state === GenStateSuspendedStart) { - state = GenStateCompleted; - throw context.arg; - } - - context.dispatchException(context.arg); - - } else if (context.method === "return") { - context.abrupt("return", context.arg); - } - - state = GenStateExecuting; - - var record = tryCatch(innerFn, self, context); - if (record.type === "normal") { - // If an exception is thrown from innerFn, we leave state === - // GenStateExecuting and loop back for another invocation. - state = context.done - ? GenStateCompleted - : GenStateSuspendedYield; + var dP$2 = _objectDp.f; + var gOPN$1 = _objectGopn.f; - if (record.arg === ContinueSentinel) { - continue; - } - return { - value: record.arg, - done: context.done - }; + var $RegExp = _global.RegExp; + var Base$1 = $RegExp; + var proto$2 = $RegExp.prototype; + var re1 = /a/g; + var re2 = /a/g; + // "new" creates a new object, old webkit buggy here + var CORRECT_NEW = new $RegExp(re1) !== re1; - } else if (record.type === "throw") { - state = GenStateCompleted; - // Dispatch the exception by looping back around to the - // context.dispatchException(context.arg) call above. - context.method = "throw"; - context.arg = record.arg; - } - } + if (_descriptors && (!CORRECT_NEW || _fails(function () { + re2[_wks('match')] = false; + // RegExp constructor can alter flags and IsRegExp works correct with @@match + return $RegExp(re1) != re1 || $RegExp(re2) == re2 || $RegExp(re1, 'i') != '/a/i'; + }))) { + $RegExp = function RegExp(p, f) { + var tiRE = this instanceof $RegExp; + var piRE = _isRegexp(p); + var fiU = f === undefined; + return !tiRE && piRE && p.constructor === $RegExp && fiU ? p + : _inheritIfRequired(CORRECT_NEW + ? new Base$1(piRE && !fiU ? p.source : p, f) + : Base$1((piRE = p instanceof $RegExp) ? p.source : p, piRE && fiU ? _flags.call(p) : f) + , tiRE ? this : proto$2, $RegExp); }; + var proxy = function (key) { + key in $RegExp || dP$2($RegExp, key, { + configurable: true, + get: function () { return Base$1[key]; }, + set: function (it) { Base$1[key] = it; } + }); + }; + for (var keys$1 = gOPN$1(Base$1), i$1 = 0; keys$1.length > i$1;) proxy(keys$1[i$1++]); + proto$2.constructor = $RegExp; + $RegExp.prototype = proto$2; + _redefine(_global, 'RegExp', $RegExp); } - // Call delegate.iterator[context.method](context.arg) and handle the - // result, either by returning a { value, done } result from the - // delegate iterator, or by modifying context.method and context.arg, - // setting context.delegate to null, and returning the ContinueSentinel. - function maybeInvokeDelegate(delegate, context) { - var method = delegate.iterator[context.method]; - if (method === undefined) { - // A .throw or .return when the delegate iterator has no .throw - // method always terminates the yield* loop. - context.delegate = null; - - if (context.method === "throw") { - if (delegate.iterator.return) { - // If the delegate iterator has a return method, give it a - // chance to clean up. - context.method = "return"; - context.arg = undefined; - maybeInvokeDelegate(delegate, context); - - if (context.method === "throw") { - // If maybeInvokeDelegate(context) changed context.method from - // "return" to "throw", let that override the TypeError below. - return ContinueSentinel; - } - } + _setSpecies('RegExp'); - context.method = "throw"; - context.arg = new TypeError( - "The iterator does not provide a 'throw' method"); - } + function generateId(prefix) { + return "".concat(prefix, "-").concat(Math.floor(Math.random() * 10000)); + } // Format string - return ContinueSentinel; + function format(input) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; } - var record = tryCatch(method, delegate.iterator, context.arg); - - if (record.type === "throw") { - context.method = "throw"; - context.arg = record.arg; - context.delegate = null; - return ContinueSentinel; + if (is$1.empty(input)) { + return input; } - var info = record.arg; + return input.toString().replace(/{(\d+)}/g, function (match, i) { + return args[i].toString(); + }); + } // Get percentage - if (! info) { - context.method = "throw"; - context.arg = new TypeError("iterator result is not an object"); - context.delegate = null; - return ContinueSentinel; + function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; } - if (info.done) { - // Assign the result of the finished delegate to the temporary - // variable specified by delegate.resultName (see delegateYield). - context[delegate.resultName] = info.value; + return (current / max * 100).toFixed(2); + } // Replace all occurances of a string in a string - // Resume execution at the desired location (see delegateYield). - context.next = delegate.nextLoc; + function replaceAll() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); + } // Convert to title case - // If context.method was "throw" but the delegate handled the - // exception, let the outer generator proceed normally. If - // context.method was "next", forget context.arg since it has been - // "consumed" by the delegate iterator. If context.method was - // "return", allow the original .return call to continue in the - // outer generator. - if (context.method !== "return") { - context.method = "next"; - context.arg = undefined; - } - - } else { - // Re-yield the result returned by the delegate method. - return info; - } + function toTitleCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return input.toString().replace(/\w\S*/g, function (text) { + return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); + }); + } // Convert string to pascalCase - // The delegate iterator is finished, so forget it and continue with - // the outer generator. - context.delegate = null; - return ContinueSentinel; - } + function toPascalCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert kebab case - // Define Generator.prototype.{next,throw,return} in terms of the - // unified ._invoke helper method. - defineIteratorMethods(Gp); + string = replaceAll(string, '-', ' '); // Convert snake case - Gp[toStringTagSymbol] = "Generator"; + string = replaceAll(string, '_', ' '); // Convert to title case - // A Generator should always return itself as the iterator object when the - // @@iterator function is called on it. Some browsers' implementations of the - // iterator prototype chain incorrectly implement this, causing the Generator - // object to not be returned from this call. This ensures that doesn't happen. - // See https://github.com/facebook/regenerator/issues/274 for more details. - Gp[iteratorSymbol] = function() { - return this; - }; + string = toTitleCase(string); // Convert to pascal case - Gp.toString = function() { - return "[object Generator]"; - }; + return replaceAll(string, ' ', ''); + } // Convert string to pascalCase - function pushTryEntry(locs) { - var entry = { tryLoc: locs[0] }; + function toCamelCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert to pascal case - if (1 in locs) { - entry.catchLoc = locs[1]; - } - - if (2 in locs) { - entry.finallyLoc = locs[2]; - entry.afterLoc = locs[3]; - } + string = toPascalCase(string); // Convert first character to lowercase - this.tryEntries.push(entry); - } + return string.charAt(0).toLowerCase() + string.slice(1); + } // Remove HTML from a string - function resetTryEntry(entry) { - var record = entry.completion || {}; - record.type = "normal"; - delete record.arg; - entry.completion = record; - } + function stripHTML(source) { + var fragment = document.createDocumentFragment(); + var element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; + } // Like outerHTML, but also works for DocumentFragment - function Context(tryLocsList) { - // The root entry object (effectively a try statement without a catch - // or a finally block) gives us a place to store values thrown from - // locations where there is no enclosing try statement. - this.tryEntries = [{ tryLoc: "root" }]; - tryLocsList.forEach(pushTryEntry, this); - this.reset(true); + function getHTML(element) { + var wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; } - runtime.keys = function(object) { - var keys = []; - for (var key in object) { - keys.push(key); - } - keys.reverse(); - - // Rather than returning an object with a next method, we keep - // things simple and return the next function itself. - return function next() { - while (keys.length) { - var key = keys.pop(); - if (key in object) { - next.value = key; - next.done = false; - return next; - } - } - - // To avoid creating an additional object, we just hang the .value - // and .done properties off the next function object itself. This - // also ensures that the minifier will not anonymize the function. - next.done = true; - return next; - }; + var resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube' }; + var i18n = { + get: function get() { + var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - function values(iterable) { - if (iterable) { - var iteratorMethod = iterable[iteratorSymbol]; - if (iteratorMethod) { - return iteratorMethod.call(iterable); - } - - if (typeof iterable.next === "function") { - return iterable; - } - - if (!isNaN(iterable.length)) { - var i = -1, next = function next() { - while (++i < iterable.length) { - if (hasOwn.call(iterable, i)) { - next.value = iterable[i]; - next.done = false; - return next; - } - } - - next.value = undefined; - next.done = true; - - return next; - }; - - return next.next = next; + if (is$1.empty(key) || is$1.empty(config)) { + return ''; } - } - - // Return an iterator with no values. - return { next: doneResult }; - } - runtime.values = values; - function doneResult() { - return { value: undefined, done: true }; - } + var string = getDeep(config.i18n, key); - Context.prototype = { - constructor: Context, - - reset: function(skipTempReset) { - this.prev = 0; - this.next = 0; - // Resetting context._sent for legacy support of Babel's - // function.sent implementation. - this.sent = this._sent = undefined; - this.done = false; - this.delegate = null; - - this.method = "next"; - this.arg = undefined; - - this.tryEntries.forEach(resetTryEntry); - - if (!skipTempReset) { - for (var name in this) { - // Not sure about the optimal order of these conditions: - if (name.charAt(0) === "t" && - hasOwn.call(this, name) && - !isNaN(+name.slice(1))) { - this[name] = undefined; - } + if (is$1.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; } - } - }, - stop: function() { - this.done = true; - - var rootEntry = this.tryEntries[0]; - var rootRecord = rootEntry.completion; - if (rootRecord.type === "throw") { - throw rootRecord.arg; + return ''; } - return this.rval; - }, - - dispatchException: function(exception) { - if (this.done) { - throw exception; - } + var replace = { + '{seektime}': config.seekTime, + '{title}': config.title + }; + Object.entries(replace).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; - var context = this; - function handle(loc, caught) { - record.type = "throw"; - record.arg = exception; - context.next = loc; + string = replaceAll(string, key, value); + }); + return string; + } + }; - if (caught) { - // If the dispatched exception was caught by a catch block, - // then let that catch block handle the exception normally. - context.method = "next"; - context.arg = undefined; - } + var Storage = + /*#__PURE__*/ + function () { + function Storage(player) { + _classCallCheck(this, Storage); - return !! caught; - } + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } // Check for actual support (see if we can use it) - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - var record = entry.completion; - if (entry.tryLoc === "root") { - // Exception thrown outside of any try block that could handle - // it, so set the completion value of the entire function to - // throw the exception. - return handle("end"); + _createClass(Storage, [{ + key: "get", + value: function get(key) { + if (!Storage.supported || !this.enabled) { + return null; } - if (entry.tryLoc <= this.prev) { - var hasCatch = hasOwn.call(entry, "catchLoc"); - var hasFinally = hasOwn.call(entry, "finallyLoc"); + var store = window.localStorage.getItem(this.key); - if (hasCatch && hasFinally) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } else if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else if (hasCatch) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } - - } else if (hasFinally) { - if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else { - throw new Error("try statement without catch or finally"); - } + if (is$1.empty(store)) { + return null; } - } - }, - abrupt: function(type, arg) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc <= this.prev && - hasOwn.call(entry, "finallyLoc") && - this.prev < entry.finallyLoc) { - var finallyEntry = entry; - break; - } + var json = JSON.parse(store); + return is$1.string(key) && key.length ? json[key] : json; } + }, { + key: "set", + value: function set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } // Can only store objectst - if (finallyEntry && - (type === "break" || - type === "continue") && - finallyEntry.tryLoc <= arg && - arg <= finallyEntry.finallyLoc) { - // Ignore the finally entry if control is not jumping to a - // location outside the try/catch block. - finallyEntry = null; - } - var record = finallyEntry ? finallyEntry.completion : {}; - record.type = type; - record.arg = arg; + if (!is$1.object(object)) { + return; + } // Get current storage - if (finallyEntry) { - this.method = "next"; - this.next = finallyEntry.finallyLoc; - return ContinueSentinel; - } - return this.complete(record); - }, + var storage = this.get(); // Default to empty object - complete: function(record, afterLoc) { - if (record.type === "throw") { - throw record.arg; - } + if (is$1.empty(storage)) { + storage = {}; + } // Update the working copy of the values - if (record.type === "break" || - record.type === "continue") { - this.next = record.arg; - } else if (record.type === "return") { - this.rval = this.arg = record.arg; - this.method = "return"; - this.next = "end"; - } else if (record.type === "normal" && afterLoc) { - this.next = afterLoc; - } - return ContinueSentinel; - }, + extend(storage, object); // Update storage - finish: function(finallyLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.finallyLoc === finallyLoc) { - this.complete(entry.completion, entry.afterLoc); - resetTryEntry(entry); - return ContinueSentinel; - } + window.localStorage.setItem(this.key, JSON.stringify(storage)); } - }, - - "catch": function(tryLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc === tryLoc) { - var record = entry.completion; - if (record.type === "throw") { - var thrown = record.arg; - resetTryEntry(entry); + }], [{ + key: "supported", + get: function get() { + try { + if (!('localStorage' in window)) { + return false; } - return thrown; - } - } - - // The context.catch method must only be called with a location - // argument that corresponds to a known catch block. - throw new Error("illegal catch attempt"); - }, - delegateYield: function(iterable, resultName, nextLoc) { - this.delegate = { - iterator: values(iterable), - resultName: resultName, - nextLoc: nextLoc - }; + var test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 - if (this.method === "next") { - // Deliberately forget the last sent value so that we don't - // accidentally pass it on to the delegate. - this.arg = undefined; + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } } + }]); - return ContinueSentinel; - } - }; -})( - // Among the various tricks for obtaining a reference to the global - // object, this seems to be the most reliable technique that does not - // use indirect eval (which violates Content Security Policy). - typeof commonjsGlobal === "object" ? commonjsGlobal : - typeof window === "object" ? window : - typeof self === "object" ? self : commonjsGlobal -); -}); - -// Polyfill for creating CustomEvents on IE9/10/11 - -// code pulled from: -// https://github.com/d4tocchini/customevent-polyfill -// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill - -try { - var ce = new window.CustomEvent('test'); - ce.preventDefault(); - if (ce.defaultPrevented !== true) { - // IE has problems with .preventDefault() on custom events - // http://stackoverflow.com/questions/23349191 - throw new Error('Could not prevent default'); - } -} catch(e) { - var CustomEvent$1 = function(event, params) { - var evt, origPrevent; - params = params || { - bubbles: false, - cancelable: false, - detail: undefined - }; - - evt = document.createEvent("CustomEvent"); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - origPrevent = evt.preventDefault; - evt.preventDefault = function () { - origPrevent.call(this); + return Storage; + }(); + + // ========================================================================== + // Fetch wrapper + // Using XHR to avoid issues with older browsers + // ========================================================================== + function fetch(url) { + var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + return new Promise(function (resolve, reject) { try { - Object.defineProperty(this, 'defaultPrevented', { - get: function () { - return true; + var request = new XMLHttpRequest(); // Check for CORS support + + if (!('withCredentials' in request)) { + return; + } + + request.addEventListener('load', function () { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); } }); - } catch(e) { - this.defaultPrevented = true; - } - }; - return evt; - }; - - CustomEvent$1.prototype = window.Event.prototype; - window.CustomEvent = CustomEvent$1; // expose definition to window -} + request.addEventListener('error', function () { + throw new Error(request.status); + }); + request.open('GET', url, true); // Set the required response type -var loadjs_umd = createCommonjsModule(function (module, exports) { -(function(root, factory) { - if (typeof undefined === 'function' && undefined.amd) { - undefined([], factory); - } else { - module.exports = factory(); + request.responseType = responseType; + request.send(); + } catch (e) { + reject(e); + } + }); } -}(commonjsGlobal, function() { -/** - * Global dependencies. - * @global {Object} document - DOM - */ - -var devnull = function() {}, - bundleIdCache = {}, - bundleResultCache = {}, - bundleCallbackQueue = {}; + // ========================================================================== -/** - * Subscribe to bundle load event. - * @param {string[]} bundleIds - Bundle ids - * @param {Function} callbackFn - The callback function - */ -function subscribe(bundleIds, callbackFn) { - // listify - bundleIds = bundleIds.push ? bundleIds : [bundleIds]; - - var depsNotFound = [], - i = bundleIds.length, - numWaiting = i, - fn, - bundleId, - r, - q; - - // define callback function - fn = function (bundleId, pathsNotFound) { - if (pathsNotFound.length) depsNotFound.push(bundleId); - - numWaiting--; - if (!numWaiting) callbackFn(depsNotFound); - }; - - // register callback - while (i--) { - bundleId = bundleIds[i]; - - // execute callback if in result cache - r = bundleResultCache[bundleId]; - if (r) { - fn(bundleId, r); - continue; + function loadSprite(url, id) { + if (!is$1.string(url)) { + return; } - // add to callback queue - q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; - q.push(fn); - } -} + var prefix = 'cache'; + var hasId = is$1.string(id); + var isCached = false; + var exists = function exists() { + return document.getElementById(id) !== null; + }; -/** - * Publish bundle load event. - * @param {string} bundleId - Bundle id - * @param {string[]} pathsNotFound - List of files not found - */ -function publish(bundleId, pathsNotFound) { - // exit if id isn't defined - if (!bundleId) return; + var update = function update(container, data) { + container.innerHTML = data; // Check again incase of race condition - var q = bundleCallbackQueue[bundleId]; + if (hasId && exists()) { + return; + } // Inject the SVG to the body - // cache result - bundleResultCache[bundleId] = pathsNotFound; - // exit if queue is empty - if (!q) return; + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set - // empty callback queue - while (q.length) { - q[0](bundleId, pathsNotFound); - q.splice(0, 1); - } -} - - -/** - * Execute callbacks. - * @param {Object or Function} args - The callback args - * @param {string[]} depsNotFound - List of dependencies not found - */ -function executeCallbacks(args, depsNotFound) { - // accept function as argument - if (args.call) args = {success: args}; - - // success and error callbacks - if (depsNotFound.length) (args.error || devnull)(depsNotFound); - else (args.success || devnull)(args); -} - - -/** - * Load individual file. - * @param {string} path - The file path - * @param {Function} callbackFn - The callback function - */ -function loadFile(path, callbackFn, args, numTries) { - var doc = document, - async = args.async, - maxTries = (args.numRetries || 0) + 1, - beforeCallbackFn = args.before || devnull, - pathStripped = path.replace(/^(css|img)!/, ''), - isCss, - e; - - numTries = numTries || 0; - - if (/(^css!|\.css$)/.test(path)) { - isCss = true; - - // css - e = doc.createElement('link'); - e.rel = 'stylesheet'; - e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix - } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { - // image - e = doc.createElement('img'); - e.src = pathStripped; - } else { - // javascript - e = doc.createElement('script'); - e.src = path; - e.async = async === undefined ? true : async; - } - e.onload = e.onerror = e.onbeforeload = function (ev) { - var result = ev.type[0]; + if (!hasId || !exists()) { + var useStorage = Storage.supported; // Create container - // Note: The following code isolates IE using `hideFocus` and treats empty - // stylesheets as failures to get around lack of onerror support - if (isCss && 'hideFocus' in e) { - try { - if (!e.sheet.cssText.length) result = 'e'; - } catch (x) { - // sheets objects created from load errors don't allow access to - // `cssText` - result = 'e'; - } - } + var container = document.createElement('div'); + container.setAttribute('hidden', ''); - // handle retries in case of load failure - if (result == 'e') { - // increment counter - numTries += 1; + if (hasId) { + container.setAttribute('id', id); + } // Check in cache - // exit function and try again - if (numTries < maxTries) { - return loadFile(path, callbackFn, args, numTries); - } - } - // execute callback - callbackFn(path, result, ev.defaultPrevented); - }; + if (useStorage) { + var cached = window.localStorage.getItem("".concat(prefix, "-").concat(id)); + isCached = cached !== null; + + if (isCached) { + var data = JSON.parse(cached); + update(container, data.content); + } + } // Get the sprite - // add to document (unless callback returns `false`) - if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); -} + fetch(url).then(function (result) { + if (is$1.empty(result)) { + return; + } -/** - * Load multiple files. - * @param {string[]} paths - The file paths - * @param {Function} callbackFn - The callback function - */ -function loadFiles(paths, callbackFn, args) { - // listify paths - paths = paths.push ? paths : [paths]; + if (useStorage) { + window.localStorage.setItem("".concat(prefix, "-").concat(id), JSON.stringify({ + content: result + })); + } + + update(container, result); + }).catch(function () {}); + } + } - var numWaiting = paths.length, - x = numWaiting, - pathsNotFound = [], - fn, - i; + // 20.2.2.34 Math.trunc(x) - // define callback function - fn = function(path, result, defaultPrevented) { - // handle error - if (result == 'e') pathsNotFound.push(path); - // handle beforeload event. If defaultPrevented then that means the load - // will be blocked (ex. Ghostery/ABP on Safari) - if (result == 'b') { - if (defaultPrevented) pathsNotFound.push(path); - else return; + _export(_export.S, 'Math', { + trunc: function trunc(it) { + return (it > 0 ? Math.floor : Math.ceil)(it); } + }); - numWaiting--; - if (!numWaiting) callbackFn(pathsNotFound); + var getHours = function getHours(value) { + return Math.trunc(value / 60 / 60 % 60, 10); + }; + var getMinutes = function getMinutes(value) { + return Math.trunc(value / 60 % 60, 10); }; + var getSeconds = function getSeconds(value) { + return Math.trunc(value % 60, 10); + }; // Format time to UI friendly string - // load scripts - for (i=0; i < x; i++) loadFile(paths[i], fn, args); -} + function formatTime() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + // Bail if the value isn't a number + if (!is$1.number(time)) { + return formatTime(null, displayHours, inverted); + } // Format time component to add leading zero -/** - * Initiate script load and register bundle. - * @param {(string|string[])} paths - The file paths - * @param {(string|Function)} [arg1] - The bundleId or success callback - * @param {Function} [arg2] - The success or error callback - * @param {Function} [arg3] - The error callback - */ -function loadjs(paths, arg1, arg2) { - var bundleId, - args; - // bundleId (if string) - if (arg1 && arg1.trim) bundleId = arg1; + var format = function format(value) { + return "0".concat(value).slice(-2); + }; // Breakdown to hours, mins, secs - // args (default is {}) - args = (bundleId ? arg2 : arg1) || {}; - // throw error if bundle is already defined - if (bundleId) { - if (bundleId in bundleIdCache) { - throw "LoadJS"; + var hours = getHours(time); + var mins = getMinutes(time); + var secs = getSeconds(time); // Do we need to display hours? + + if (displayHours || hours > 0) { + hours = "".concat(hours, ":"); } else { - bundleIdCache[bundleId] = true; - } - } + hours = ''; + } // Render - // load scripts - loadFiles(paths, function (pathsNotFound) { - // execute callbacks - executeCallbacks(args, pathsNotFound); - - // publish bundle load event - publish(bundleId, pathsNotFound); - }, args); -} - - -/** - * Execute callbacks when dependencies have been satisfied. - * @param {(string|string[])} deps - List of bundle ids - * @param {Object} args - success/error arguments - */ -loadjs.ready = function ready(deps, args) { - // subscribe to bundle load event - subscribe(deps, function (depsNotFound) { - // execute callbacks - executeCallbacks(args, depsNotFound); - }); - return loadjs; -}; + return "".concat(inverted && time > 0 ? '-' : '').concat(hours).concat(format(mins), ":").concat(format(secs)); + } + var controls = { + // Get icon URL + getIconUrl: function getIconUrl() { + var url = new URL(this.config.iconUrl, window.location); + var cors = url.host !== window.location.host || browser.isIE && !window.svg4everybody; + return { + url: this.config.iconUrl, + cors: cors + }; + }, + // Find the UI controls + findElements: function findElements() { + try { + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons + + this.elements.buttons = { + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen) + }; // Progress + + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs + + this.elements.inputs = { + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume) + }; // Display + + this.elements.display = { + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration) + }; // Seek tooltip + + if (is$1.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip)); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls + + this.toggleNativeControls(true); + return false; + } + }, + // Create <svg> icon + createIcon: function createIcon(type, attributes) { + var namespace = 'http://www.w3.org/2000/svg'; + var iconUrl = controls.getIconUrl.call(this); + var iconPath = "".concat(!iconUrl.cors ? iconUrl.url : '', "#").concat(this.config.iconPrefix); // Create <svg> -/** - * Manually satisfy bundle dependencies. - * @param {string} bundleId - The bundle id - */ -loadjs.done = function done(bundleId) { - publish(bundleId, []); -}; + var icon = document.createElementNS(namespace, 'svg'); + setAttributes(icon, extend(attributes, { + role: 'presentation', + focusable: 'false' + })); // Create the <use> to reference sprite + var use = document.createElementNS(namespace, 'use'); + var path = "".concat(iconPath, "-").concat(type); // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href -/** - * Reset loadjs dependencies statuses - */ -loadjs.reset = function reset() { - bundleIdCache = {}; - bundleResultCache = {}; - bundleCallbackQueue = {}; -}; + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } // Always set the older attribute even though it's "deprecated" (it'll be around for ages) -/** - * Determine if bundle has already been defined - * @param String} bundleId - The bundle id - */ -loadjs.isDefined = function isDefined(bundleId) { - return bundleId in bundleIdCache; -}; + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg> + icon.appendChild(use); + return icon; + }, + // Create hidden text label + createLabel: function createLabel(key) { + var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var text = i18n.get(key, this.config); + var attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') + }); + return createElement('span', attributes, text); + }, + // Create a badge + createBadge: function createBadge(text) { + if (is$1.empty(text)) { + return null; + } -// export -return loadjs; + var badge = createElement('span', { + class: this.config.classNames.menu.value + }); + badge.appendChild(createElement('span', { + class: this.config.classNames.menu.badge + }, text)); + return badge; + }, + // Create a <button> + createButton: function createButton(buttonType, attr) { + var attributes = Object.assign({}, attr); + var type = toCamelCase(buttonType); + var props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null + }; + ['element', 'icon', 'label'].forEach(function (key) { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); // Default to 'button' type to prevent form submission -})); -}); + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { + attributes.type = 'button'; + } // Set class name -// ========================================================================== -// Plyr supported types and providers -// ========================================================================== -var providers = { - html5: 'html5', - youtube: 'youtube', - vimeo: 'vimeo' -}; + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { + attributes.class += " ".concat(this.config.classNames.control); + } + } else { + attributes.class = this.config.classNames.control; + } // Large play button -var types = { - audio: 'audio', - video: 'video' -}; -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; + switch (buttonType) { + case 'play': + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; + break; -var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } + case 'mute': + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; + break; - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); + case 'captions': + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; + break; -var defineProperty$1 = function (obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } + case 'fullscreen': + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; + break; - return obj; -}; + case 'play-large': + attributes.class += " ".concat(this.config.classNames.control, "--overlaid"); + type = 'play'; + props.label = 'play'; + props.icon = 'play'; + break; -var slicedToArray = function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; + default: + if (is$1.empty(props.label)) { + props.label = type; + } - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); + if (is$1.empty(props.icon)) { + props.icon = buttonType; + } - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; } - } - return _arr; - } + var button = createElement(props.element); // Setup toggle icon and labels - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; -}(); + if (props.toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed' + })); + button.appendChild(controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed' + })); // Label/Tooltip -var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + button.appendChild(controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed' + })); + button.appendChild(controls.createLabel.call(this, props.label, { + class: 'label--not-pressed' + })); + } else { + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); + } // Merge and set attributes - return arr2; - } else { - return Array.from(arr); - } -}; -// ========================================================================== + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons -var utils = { - // Check variable types - is: { - plyr: function plyr(input) { - return this.instanceof(input, window.Plyr); - }, - object: function object(input) { - return this.getConstructor(input) === Object; - }, - number: function number(input) { - return this.getConstructor(input) === Number && !Number.isNaN(input); - }, - string: function string(input) { - return this.getConstructor(input) === String; - }, - boolean: function boolean(input) { - return this.getConstructor(input) === Boolean; - }, - function: function _function(input) { - return this.getConstructor(input) === Function; - }, - array: function array(input) { - return !this.nullOrUndefined(input) && Array.isArray(input); - }, - weakMap: function weakMap(input) { - return this.instanceof(input, window.WeakMap); - }, - nodeList: function nodeList(input) { - return this.instanceof(input, window.NodeList); - }, - element: function element(input) { - return this.instanceof(input, window.Element); - }, - textNode: function textNode(input) { - return this.getConstructor(input) === Text; - }, - event: function event(input) { - return this.instanceof(input, window.Event); - }, - cue: function cue(input) { - return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); - }, - track: function track(input) { - return this.instanceof(input, TextTrack) || !this.nullOrUndefined(input) && this.string(input.kind); - }, - url: function url(input) { - return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input); - }, - nullOrUndefined: function nullOrUndefined(input) { - return input === null || typeof input === 'undefined'; - }, - empty: function empty(input) { - return this.nullOrUndefined(input) || (this.string(input) || this.array(input) || this.nodeList(input)) && !input.length || this.object(input) && !Object.keys(input).length; - }, - instanceof: function _instanceof$$1(input, constructor) { - return Boolean(input && constructor && input instanceof constructor); - }, - getConstructor: function getConstructor(input) { - return !this.nullOrUndefined(input) ? input.constructor : null; + if (type === 'play') { + if (!is$1.array(this.elements.buttons[type])) { + this.elements.buttons[type] = []; } - }, - // Unfortunately, due to mixed support, UA sniffing is required - getBrowser: function getBrowser() { - return { - isIE: /* @cc_on!@ */false || !!document.documentMode, - isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), - isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), - isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) - }; - }, + this.elements.buttons[type].push(button); + } else { + this.elements.buttons[type] = button; + } + return button; + }, + // Create an <input type='range'> + createRange: function createRange(type, attributes) { + // Seek input + var input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + // A11y fixes for https://github.com/sampotts/plyr/issues/905 + role: 'slider', + 'aria-label': i18n.get(type, this.config), + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'aria-valuenow': 0 + }, attributes)); + this.elements.inputs[type] = input; // Set the fill for webkit now + + controls.updateRangeFill.call(this, input); + return input; + }, + // Create a <progress> + createProgress: function createProgress(type, attributes) { + var progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), { + min: 0, + max: 100, + value: 0, + role: 'presentation', + 'aria-hidden': true + }, attributes)); // Create the label inside + + if (type !== 'volume') { + progress.appendChild(createElement('span', null, '0')); + var suffixKey = { + played: 'played', + buffer: 'buffered' + }[type]; + var suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; + progress.innerText = "% ".concat(suffix.toLowerCase()); + } - // Fetch wrapper - // Using XHR to avoid issues with older browsers - fetch: function fetch(url) { - var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + this.elements.display[type] = progress; + return progress; + }, + // Create time display + createTime: function createTime(type) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + var container = createElement('div', extend(attributes, { + class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-label': i18n.get(type, this.config) + }), '00:00'); // Reference for updates - return new Promise(function (resolve, reject) { - try { - var request = new XMLHttpRequest(); + this.elements.display[type] = container; + return container; + }, + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { + var _this = this; - // Check for CORS support - if (!('withCredentials' in request)) { - return; - } + // Navigate through menus via arrow keys and space + on(menuItem, 'keydown keyup', function (event) { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } // Prevent play / seek - request.addEventListener('load', function () { - if (responseType === 'text') { - try { - resolve(JSON.parse(request.responseText)); - } catch (e) { - resolve(request.responseText); - } - } else { - resolve(request.response); - } - }); - request.addEventListener('error', function () { - throw new Error(request.statusText); - }); + event.preventDefault(); + event.stopPropagation(); // We're just here to prevent the keydown bubbling - request.open('GET', url, true); + if (event.type === 'keydown') { + return; + } - // Set the required response type - request.responseType = responseType; + var isRadioButton = matches(menuItem, '[role="menuitemradio"]'); // Show the respective menu - request.send(); - } catch (e) { - reject(e); - } - }); - }, + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(_this, type, true); + } else { + var target; + if (event.which !== 32) { + if (event.which === 40 || isRadioButton && event.which === 39) { + target = menuItem.nextElementSibling; - // Load an external script - loadScript: function loadScript(url) { - return new Promise(function (resolve, reject) { - loadjs_umd(url, { - success: resolve, - error: reject - }); - }); - }, + if (!is$1.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; + if (!is$1.element(target)) { + target = menuItem.parentNode.lastElementChild; + } + } - // Load an external SVG sprite - loadSprite: function loadSprite(url, id) { - if (!utils.is.string(url)) { - return; + setFocus.call(_this, target, true); + } } + }, false); // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here - var prefix = 'cache-'; - var hasId = utils.is.string(id); - var isCached = false; + on(menuItem, 'keyup', function (event) { + if (event.which !== 13) { + return; + } - var exists = function exists() { - return document.querySelectorAll('#' + id).length; - }; + controls.focusFirstMenuItem.call(_this, null, true); + }); + }, + // Create a settings menu item + createMenuItem: function createMenuItem(_ref) { + var _this2 = this; + + var value = _ref.value, + list = _ref.list, + type = _ref.type, + title = _ref.title, + _ref$badge = _ref.badge, + badge = _ref$badge === void 0 ? null : _ref$badge, + _ref$checked = _ref.checked, + checked = _ref$checked === void 0 ? false : _ref$checked; + var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + var menuItem = createElement('button', extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: "".concat(this.config.classNames.control, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-checked': checked, + value: value + })); + var flex = createElement('span'); // We have to set as HTML incase of special characters + + flex.innerHTML = title; + + if (is$1.element(badge)) { + flex.appendChild(badge); + } - function injectSprite(data) { - // Check again incase of race condition - if (hasId && exists()) { - return; - } + menuItem.appendChild(flex); // Replicate radio button behaviour - // Inject content - this.innerHTML = data; + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get: function get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set: function set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children).filter(function (node) { + return matches(node, '[role="menuitemradio"]'); + }).forEach(function (node) { + return node.setAttribute('aria-checked', 'false'); + }); + } - // Inject the SVG to the body - document.body.insertBefore(this, document.body.childNodes[0]); + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + } + }); + this.listeners.bind(menuItem, 'click keyup', function (event) { + if (is$1.keyboardEvent(event) && event.which !== 32) { + return; } - // Only load once if ID set - if (!hasId || !exists()) { - // Create container - var container = document.createElement('div'); - utils.toggleHidden(container, true); - - if (hasId) { - container.setAttribute('id', id); - } - - // Check in cache - if (support.storage) { - var cached = window.localStorage.getItem(prefix + id); - isCached = cached !== null; + event.preventDefault(); + event.stopPropagation(); + menuItem.checked = true; - if (isCached) { - var data = JSON.parse(cached); - injectSprite.call(container, data.content); - return; - } - } + switch (type) { + case 'language': + _this2.currentTrack = Number(value); + break; - // Get the sprite - utils.fetch(url).then(function (result) { - if (utils.is.empty(result)) { - return; - } + case 'quality': + _this2.quality = value; + break; - if (support.storage) { - window.localStorage.setItem(prefix + id, JSON.stringify({ - content: result - })); - } + case 'speed': + _this2.speed = parseFloat(value); + break; - injectSprite.call(container, result); - }).catch(function () {}); + default: + break; } - }, - - // Generate a random ID - generateId: function generateId(prefix) { - return prefix + '-' + Math.floor(Math.random() * 10000); + controls.showMenuPanel.call(_this2, 'home', is$1.keyboardEvent(event)); + }, type, false); + controls.bindMenuItemShortcuts.call(this, menuItem, type); + list.appendChild(menuItem); }, + // Format a time for display + formatTime: function formatTime$$1() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + // Bail if the value isn't a number + if (!is$1.number(time)) { + return time; + } // Always display hours if duration is over an hour - // Wrap an element - wrap: function wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - var targets = elements.length ? elements : [elements]; - - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - Array.from(targets).reverse().forEach(function (element, index) { - var child = index > 0 ? wrapper.cloneNode(true) : wrapper; - - // Cache the current parent and sibling. - var parent = element.parentNode; - var sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - }); + var forceHours = getHours(this.duration) > 0; + return formatTime(time, forceHours, inverted); }, + // Update the displayed time + updateTimeDisplay: function updateTimeDisplay() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + // Bail if there's no element to display or the value isn't a number + if (!is$1.element(target) || !is$1.number(time)) { + return; + } // eslint-disable-next-line no-param-reassign - // Create a DocumentFragment - createElement: function createElement(type, attributes, text) { - // Create a new <element> - var element = document.createElement(type); - - // Set all passed attributes - if (utils.is.object(attributes)) { - utils.setAttributes(element, attributes); - } - - // Add text node - if (utils.is.string(text)) { - element.textContent = text; - } - // Return built element - return element; + target.innerText = controls.formatTime(time, inverted); }, + // Update volume UI and storage + updateVolume: function updateVolume() { + if (!this.supported.ui) { + return; + } // Update range - // Inaert an element after another - insertAfter: function insertAfter(element, target) { - target.parentNode.insertBefore(element, target.nextSibling); - }, + if (is$1.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } // Update mute state - // Insert a DocumentFragment - insertElement: function insertElement(type, parent, attributes, text) { - // Inject the new <element> - parent.appendChild(utils.createElement(type, attributes, text)); + if (is$1.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } }, + // Update seek value and lower fill + setRange: function setRange(target) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + if (!is$1.element(target)) { + return; + } // eslint-disable-next-line - // Remove element(s) - removeElement: function removeElement(element) { - if (utils.is.nodeList(element) || utils.is.array(element)) { - Array.from(element).forEach(utils.removeElement); - return; - } - if (!utils.is.element(element) || !utils.is.element(element.parentNode)) { - return; - } + target.value = value; // Webkit range fill - element.parentNode.removeChild(element); + controls.updateRangeFill.call(this, target); }, + // Update <progress> elements + updateProgress: function updateProgress(event) { + var _this3 = this; + if (!this.supported.ui || !is$1.event(event)) { + return; + } - // Remove all child elements - emptyElement: function emptyElement(element) { - var length = element.childNodes.length; + var value = 0; + var setProgress = function setProgress(target, input) { + var value = is$1.number(input) ? input : 0; + var progress = is$1.element(target) ? target : _this3.elements.display.buffer; // Update value and label - while (length > 0) { - element.removeChild(element.lastChild); - length -= 1; - } - }, + if (is$1.element(progress)) { + progress.value = value; // Update text label inside + var label = progress.getElementsByTagName('span')[0]; - // Replace element - replaceElement: function replaceElement(newChild, oldChild) { - if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) { - return null; + if (is$1.element(label)) { + label.childNodes[0].nodeValue = value; + } } + }; - oldChild.parentNode.replaceChild(newChild, oldChild); - - return newChild; - }, + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } - // Set attributes - setAttributes: function setAttributes(element, attributes) { - if (!utils.is.element(element) || utils.is.empty(attributes)) { - return; - } + break; + // Check buffer status - Object.entries(attributes).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + break; - element.setAttribute(key, value); - }); + default: + break; + } + } }, + // Webkit polyfill for lower fill range + updateRangeFill: function updateRangeFill(target) { + // Get range from event if event passed + var range = is$1.event(target) ? target.target : target; // Needs to be a valid <input type='range'> + if (!is$1.element(range) || range.getAttribute('type') !== 'range') { + return; + } // Set aria values for https://github.com/sampotts/plyr/issues/905 + + + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + var currentTime = controls.formatTime(this.currentTime); + var duration = controls.formatTime(this.duration); + var format$$1 = i18n.get('seekLabel', this.config); + range.setAttribute('aria-valuetext', format$$1.replace('{currentTime}', currentTime).replace('{duration}', duration)); + } else if (matches(range, this.config.selectors.inputs.volume)) { + var percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', "".concat(percent.toFixed(1), "%")); + } else { + range.setAttribute('aria-valuenow', range.value); + } // WebKit only - // Get an attribute object from a string selector - getAttributesFromSelector: function getAttributesFromSelector(sel, existingAttributes) { - // For example: - // '.test' to { class: 'test' } - // '#test' to { id: 'test' } - // '[data-test="test"]' to { 'data-test': 'test' } - if (!utils.is.string(sel) || utils.is.empty(sel)) { - return {}; - } + if (!browser.isWebkit) { + return; + } // Set CSS custom property - var attributes = {}; - var existing = existingAttributes; - sel.split(',').forEach(function (s) { - // Remove whitespace - var selector = s.trim(); - var className = selector.replace('.', ''); - var stripped = selector.replace(/[[\]]/g, ''); + range.style.setProperty('--value', "".concat(range.value / range.max * 100, "%")); + }, + // Update hover tooltip for seeking + updateSeekTooltip: function updateSeekTooltip(event) { + var _this4 = this; - // Get the parts and value - var parts = stripped.split('='); - var key = parts[0]; - var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; + // Bail if setting not true + if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) { + return; + } // Calculate percentage - // Get the first character - var start = selector.charAt(0); - switch (start) { - case '.': - // Add to existing classname - if (utils.is.object(existing) && utils.is.string(existing.class)) { - existing.class += ' ' + className; - } + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + var visible = "".concat(this.config.classNames.tooltip, "--visible"); - attributes.class = className; - break; + var toggle = function toggle(_toggle) { + toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + }; // Hide on touch - case '#': - // ID selector - attributes.id = selector.replace('#', ''); - break; - case '[': - // Attribute selector - attributes[key] = value; + if (this.touch) { + toggle(false); + return; + } // Determine percentage, if already visible - break; - default: - break; - } - }); + if (is$1.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } // Set bounds - return attributes; - }, + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } // Display the time a click would seek to - // Toggle hidden - toggleHidden: function toggleHidden(element, hidden) { - if (!utils.is.element(element)) { - return; - } - var hide = hidden; + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position - if (!utils.is.boolean(hide)) { - hide = !element.hasAttribute('hidden'); - } + this.elements.display.seekTooltip.style.left = "".concat(percent, "%"); // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds - if (hide) { - element.setAttribute('hidden', ''); - } else { - element.removeAttribute('hidden'); - } + if (is$1.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + toggle(event.type === 'mouseenter'); + } }, + // Handle time change event + timeUpdate: function timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + var invert = !is$1.element(this.elements.display.duration) && this.config.invertTime; // Duration + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking - // Toggle class on an element - toggleClass: function toggleClass(element, className, toggle) { - if (utils.is.element(element)) { - var contains = element.classList.contains(className); - - element.classList[toggle ? 'add' : 'remove'](className); + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } // Playing progress - return toggle && !contains || !toggle && contains; - } - return null; + controls.updateProgress.call(this, event); }, + // Show the duration on metadataloaded or durationchange events + durationUpdate: function durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || !this.config.invertTime && this.currentTime) { + return; + } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 - // Has class name - hasClass: function hasClass(element, className) { - return utils.is.element(element) && element.classList.contains(className); - }, + if (this.duration >= Math.pow(2, 32)) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } // Update ARIA values - // Element matches selector - matches: function matches(element, selector) { - var prototype = { Element: Element }; + if (is$1.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); + } // If there's a spot to display duration - function match() { - return Array.from(document.querySelectorAll(selector)).includes(this); - } - var matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; + var hasDuration = is$1.element(this.elements.display.duration); // If there's only one time display, display duration there - return matches.call(element, selector); - }, + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } // If there's a duration element, update content - // Find all elements - getElements: function getElements(selector) { - return this.elements.container.querySelectorAll(selector); - }, + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } // Update the tooltip (if visible) - // Find a single element - getElement: function getElement(selector) { - return this.elements.container.querySelector(selector); + controls.updateSeekTooltip.call(this); }, - - - // Get the focused element - getFocusElement: function getFocusElement() { - var focused = document.activeElement; - - if (!focused || focused === document.body) { - focused = null; - } else { - focused = document.querySelector(':focus'); - } - - return focused; + // Hide/show a tab + toggleMenuButton: function toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); }, + // Update the selected setting + updateSetting: function updateSetting(setting, container, input) { + var pane = this.elements.settings.panels[setting]; + var value = null; + var list = container; + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is$1.empty(input) ? input : this[setting]; // Get default - // Trap focus inside container - trapFocus: function trapFocus() { - var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (is$1.empty(value)) { + value = this.config[setting].default; + } // Unsupported value - if (!utils.is.element(element)) { - return; - } - var focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); - var first = focusable[0]; - var last = focusable[focusable.length - 1]; + if (!is$1.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn("Unsupported value of '".concat(value, "' for ").concat(setting)); + return; + } // Disabled value - var trap = function trap(event) { - // Bail if not tab key or not fullscreen - if (event.key !== 'Tab' || event.keyCode !== 9) { - return; - } - // Get the current focused element - var focused = utils.getFocusElement(); - - if (focused === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - first.focus(); - event.preventDefault(); - } else if (focused === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - last.focus(); - event.preventDefault(); - } - }; - - if (toggle) { - utils.on(this.elements.container, 'keydown', trap, false); - } else { - utils.off(this.elements.container, 'keydown', trap, false); + if (!this.config[setting].options.includes(value)) { + this.debug.warn("Disabled value of '".concat(value, "' for ").concat(setting)); + return; } - }, + } // Get the list if we need to - // Toggle event listener - toggleListener: function toggleListener(elements, event, callback) { - var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; - var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + if (!is$1.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } // If there's no list it means it's not been rendered... - // Bail if no elemetns, event, or callback - if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) { - return; - } - // If a nodelist is passed, call itself on each node - if (utils.is.nodeList(elements) || utils.is.array(elements)) { - // Create listener for each node - Array.from(elements).forEach(function (element) { - if (element instanceof Node) { - utils.toggleListener.call(null, element, event, callback, toggle, passive, capture); - } - }); - - return; - } + if (!is$1.element(list)) { + return; + } // Update the label - // Allow multiple events - var events = event.split(' '); - // Build options - // Default to just the capture boolean for browsers with no passive listener support - var options = capture; + var label = this.elements.settings.buttons[setting].querySelector(".".concat(this.config.classNames.menu.value)); + label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it - // If passive events listeners are supported - if (support.passiveListeners) { - options = { - // Whether the listener can be passive (i.e. default never prevented) - passive: passive, - // Whether the listener is a capturing listener or not - capture: capture - }; - } + var target = list && list.querySelector("[value=\"".concat(value, "\"]")); - // If a single node is passed, bind the event listener - events.forEach(function (type) { - elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); - }); + if (is$1.element(target)) { + target.checked = true; + } }, + // Translate a value into a nice label + getLabel: function getLabel(setting, value) { + switch (setting) { + case 'speed': + return value === 1 ? i18n.get('normal', this.config) : "".concat(value, "×"); + case 'quality': + if (is$1.number(value)) { + var label = i18n.get("qualityLabel.".concat(value), this.config); - // Bind event handler - on: function on(element) { - var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var callback = arguments[2]; - var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; - var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + if (!label.length) { + return "".concat(value, "p"); + } - utils.toggleListener(element, events, callback, true, passive, capture); - }, + return label; + } + return toTitleCase(value); - // Unbind event handler - off: function off(element) { - var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var callback = arguments[2]; - var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; - var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + case 'captions': + return captions.getLabel.call(this); - utils.toggleListener(element, events, callback, false, passive, capture); + default: + return null; + } }, + // Set the quality menu + setQualityMenu: function setQualityMenu(options) { + var _this5 = this; + // Menu required + if (!is$1.element(this.elements.settings.panels.quality)) { + return; + } - // Trigger event - dispatchEvent: function dispatchEvent(element) { - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; - - // Bail if no element - if (!utils.is.element(element) || utils.is.empty(type)) { - return; - } + var type = 'quality'; + var list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); // Set options if passed and filter based on uniqueness and config - // Create and dispatch the event - var event = new CustomEvent(type, { - bubbles: bubbles, - detail: Object.assign({}, detail, { - plyr: utils.is.plyr(this) ? this : null - }) + if (is$1.array(options)) { + this.options.quality = dedupe(options).filter(function (quality) { + return _this5.config.quality.options.includes(quality); }); + } // Toggle the pane and tab - // Dispatch the event - element.dispatchEvent(event); - }, + var toggle = !is$1.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - toggleState: function toggleState(element, input) { - // If multiple elements passed - if (utils.is.array(element) || utils.is.nodeList(element)) { - Array.from(element).forEach(function (target) { - return utils.toggleState(target, input); - }); - return; - } + emptyElement(list); // Check if we need to toggle the parent - // Bail if no target - if (!utils.is.element(element)) { - return; - } + controls.checkMenu.call(this); // If we're hiding, nothing more to do - // Get state - var pressed = element.getAttribute('aria-pressed') === 'true'; - var state = utils.is.boolean(input) ? input : !pressed; + if (!toggle) { + return; + } // Get the badge HTML for HD, 4K etc - // Set the attribute on target - element.setAttribute('aria-pressed', state); - }, + var getBadge = function getBadge(quality) { + var label = i18n.get("qualityBadge.".concat(quality), _this5.config); - // Format string - format: function format(input) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; + if (!label.length) { + return null; } - if (utils.is.empty(input)) { - return input; - } + return controls.createBadge.call(_this5, label); + }; // Sort options by the config and then render options + - return input.toString().replace(/{(\d+)}/g, function (match, i) { - return utils.is.string(args[i]) ? args[i] : ''; + this.options.quality.sort(function (a, b) { + var sorting = _this5.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }).forEach(function (quality) { + controls.createMenuItem.call(_this5, { + value: quality, + list: list, + type: type, + title: controls.getLabel.call(_this5, 'quality', quality), + badge: getBadge(quality) }); + }); + controls.updateSetting.call(this, type, list); }, + // Set the looping options - - // Get percentage - getPercentage: function getPercentage(current, max) { - if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { - return 0; + /* setLoopMenu() { + // Menu required + if (!is.element(this.elements.settings.panels.loop)) { + return; } + const options = ['start', 'end', 'all', 'reset']; + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); + // Show the pane and tab + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); + // Toggle the pane and tab + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); + // Empty the menu + emptyElement(list); + options.forEach(option => { + const item = createElement('li'); + const button = createElement( + 'button', + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { + type: 'button', + class: this.config.classNames.control, + 'data-plyr-loop-action': option, + }), + i18n.get(option, this.config) + ); + if (['start', 'end'].includes(option)) { + const badge = controls.createBadge.call(this, '00:00'); + button.appendChild(badge); + } + item.appendChild(button); + list.appendChild(item); + }); + }, */ + // Get current selected caption language + // TODO: rework this to user the getter in the API? + // Set a list of available captions languages + setCaptionsMenu: function setCaptionsMenu() { + var _this6 = this; - return (current / max * 100).toFixed(2); - }, - - - // Time helpers - getHours: function getHours(value) { - return parseInt(value / 60 / 60 % 60, 10); - }, - getMinutes: function getMinutes(value) { - return parseInt(value / 60 % 60, 10); - }, - getSeconds: function getSeconds(value) { - return parseInt(value % 60, 10); - }, + // Menu required + if (!is$1.element(this.elements.settings.panels.captions)) { + return; + } // TODO: Captions or language? Currently it's mixed - // Format time to UI friendly string - formatTime: function formatTime() { - var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var type = 'captions'; + var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + var tracks = captions.getTracks.call(this); + var toggle = Boolean(tracks.length); // Toggle the pane and tab - // Bail if the value isn't a number - if (!utils.is.number(time)) { - return this.formatTime(null, displayHours, inverted); - } + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - // Format time component to add leading zero - var format = function format(value) { - return ('0' + value).slice(-2); - }; + emptyElement(list); // Check if we need to toggle the parent - // Breakdown to hours, mins, secs - var hours = this.getHours(time); - var mins = this.getMinutes(time); - var secs = this.getSeconds(time); + controls.checkMenu.call(this); // If there's no captions, bail - // Do we need to display hours? - if (displayHours || hours > 0) { - hours = hours + ':'; - } else { - hours = ''; - } + if (!toggle) { + return; + } // Generate options data - // Render - return '' + (inverted ? '-' : '') + hours + format(mins) + ':' + format(secs); - }, + var options = tracks.map(function (track, value) { + return { + value: value, + checked: _this6.captions.toggled && _this6.currentTrack === value, + title: captions.getLabel.call(_this6, track), + badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + list: list, + type: 'language' + }; + }); // Add the "Disabled" option to turn off captions - // Replace all occurances of a string in a string - replaceAll: function replaceAll() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; - var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list: list, + type: 'language' + }); // Generate options - return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); + options.forEach(controls.createMenuItem.bind(this)); + controls.updateSetting.call(this, type, list); }, + // Set a list of available captions languages + setSpeedMenu: function setSpeedMenu(options) { + var _this7 = this; + // Menu required + if (!is$1.element(this.elements.settings.panels.speed)) { + return; + } - // Convert to title case - toTitleCase: function toTitleCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var type = 'speed'; + var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options - return input.toString().replace(/\w\S*/g, function (text) { - return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); - }); - }, + if (is$1.array(options)) { + this.options.speed = options; + } else if (this.isHTML5 || this.isVimeo) { + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + } // Set options if passed and filter based on config - // Convert string to pascalCase - toPascalCase: function toPascalCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + this.options.speed = this.options.speed.filter(function (speed) { + return _this7.config.speed.options.includes(speed); + }); // Toggle the pane and tab - var string = input.toString(); + var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - // Convert kebab case - string = utils.replaceAll(string, '-', ' '); + emptyElement(list); // Check if we need to toggle the parent - // Convert snake case - string = utils.replaceAll(string, '_', ' '); + controls.checkMenu.call(this); // If we're hiding, nothing more to do - // Convert to title case - string = utils.toTitleCase(string); + if (!toggle) { + return; + } // Create items - // Convert to pascal case - return utils.replaceAll(string, ' ', ''); - }, + this.options.speed.forEach(function (speed) { + controls.createMenuItem.call(_this7, { + value: speed, + list: list, + type: type, + title: controls.getLabel.call(_this7, 'speed', speed) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Check if we need to hide/show the settings menu + checkMenu: function checkMenu() { + var buttons = this.elements.settings.buttons; + var visible = !is$1.empty(buttons) && Object.values(buttons).some(function (button) { + return !button.hidden; + }); + toggleHidden(this.elements.settings.menu, !visible); + }, + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem: function focusFirstMenuItem(pane) { + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - // Convert string to pascalCase - toCamelCase: function toCamelCase() { - var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + if (this.elements.settings.popup.hidden) { + return; + } - var string = input.toString(); + var target = pane; - // Convert to pascal case - string = utils.toPascalCase(string); + if (!is$1.element(target)) { + target = Object.values(this.elements.settings.panels).find(function (pane) { + return !pane.hidden; + }); + } - // Convert first character to lowercase - return string.charAt(0).toLowerCase() + string.slice(1); + var firstItem = target.querySelector('[role^="menuitem"]'); + setFocus.call(this, firstItem, tabFocus); }, + // Show/hide menu + toggleMenu: function toggleMenu(input) { + var popup = this.elements.settings.popup; + var button = this.elements.buttons.settings; // Menu and button are required + if (!is$1.element(popup) || !is$1.element(button)) { + return; + } // True toggle by default - // Deep extend destination object with N more objects - extend: function extend() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - for (var _len2 = arguments.length, sources = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - sources[_key2 - 1] = arguments[_key2]; - } + var hidden = popup.hidden; + var show = hidden; - if (!sources.length) { - return target; + if (is$1.boolean(input)) { + show = input; + } else if (is$1.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is$1.event(input)) { + var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) + + if (isMenuItem || !isMenuItem && input.target !== button && show) { + return; } + } // Set button attributes - var source = sources.shift(); - if (!utils.is.object(source)) { - return target; - } + button.setAttribute('aria-expanded', show); // Show the actual popup - Object.keys(source).forEach(function (key) { - if (utils.is.object(source[key])) { - if (!Object.keys(target).includes(key)) { - Object.assign(target, defineProperty$1({}, key, {})); - } + toggleHidden(popup, !show); // Add class hook - utils.extend(target[key], source[key]); - } else { - Object.assign(target, defineProperty$1({}, key, source[key])); - } - }); + toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction - return utils.extend.apply(utils, [target].concat(toConsumableArray(sources))); + if (show && is$1.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is$1.keyboardEvent(input)); + } }, + // Get the natural size of a menu panel + getMenuSize: function getMenuSize(tab) { + var clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.removeAttribute('hidden'); // Append to parent so we get the "real" size + tab.parentNode.appendChild(clone); // Get the sizes before we remove - // Remove duplicates in an array - dedupe: function dedupe(array) { - if (!utils.is.array(array)) { - return array; - } + var width = clone.scrollWidth; + var height = clone.scrollHeight; // Remove from the DOM - return array.filter(function (item, index) { - return array.indexOf(item) === index; - }); + removeElement(clone); + return { + width: width, + height: height + }; }, + // Show a panel in the menu + showMenuPanel: function showMenuPanel() { + var _this8 = this; + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail - // Get the closest value in an array - closest: function closest(array, value) { - if (!utils.is.array(array) || !array.length) { - return null; - } + if (!is$1.element(target)) { + return; + } // Hide all other panels - return array.reduce(function (prev, curr) { - return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; - }); - }, + var container = target.parentNode; + var current = Array.from(container.children).find(function (node) { + return !node.hidden; + }); // If we can do fancy animations, we'll animate the height/width - // Get the provider for a given URL - getProviderByUrl: function getProviderByUrl(url) { - // YouTube - if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/.test(url)) { - return providers.youtube; - } + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = "".concat(current.scrollWidth, "px"); + container.style.height = "".concat(current.scrollHeight, "px"); // Get potential sizes - // Vimeo - if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { - return providers.vimeo; - } + var size = controls.getMenuSize.call(this, target); // Restore auto height/width - return null; - }, + var restore = function restore(event) { + // We're only bothered about height and width on the container + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { + return; + } // Revert back to auto - // Parse YouTube ID from URL - parseYouTubeId: function parseYouTubeId(url) { - if (utils.is.empty(url)) { - return null; - } + container.style.width = ''; + container.style.height = ''; // Only listen once - var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; - return url.match(regex) ? RegExp.$2 : url; - }, + off.call(_this8, container, transitionEndEvent, restore); + }; // Listen for the transition finishing and restore auto height/width - // Parse Vimeo ID from URL - parseVimeoId: function parseVimeoId(url) { - if (utils.is.empty(url)) { - return null; - } + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target - if (utils.is.number(Number(url))) { - return url; - } + container.style.width = "".concat(size.width, "px"); + container.style.height = "".concat(size.height, "px"); + } // Set attributes on current tab - var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; - return url.match(regex) ? RegExp.$2 : url; - }, + toggleHidden(current, true); // Set attributes on target + + toggleHidden(target, false); // Focus the first item - // Convert a URL to a location object - parseUrl: function parseUrl(url) { - var parser = document.createElement('a'); - parser.href = url; - return parser; + controls.focusFirstMenuItem.call(this, target, tabFocus); }, + // Set the download link + setDownloadLink: function setDownloadLink() { + var button = this.elements.buttons.download; // Bail if no button + if (!is$1.element(button)) { + return; + } // Set download link - // Get URL query parameters - getUrlParams: function getUrlParams(input) { - var search = input; - // Parse URL if needed - if (input.startsWith('http://') || input.startsWith('https://')) { - var _parseUrl = this.parseUrl(input); + button.setAttribute('href', this.download); + }, + // Build the default HTML + // TODO: Set order based on order in the config.controls array? + create: function create(data) { + var _this9 = this; - search = _parseUrl.search; - } + // Create the container + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button - if (this.is.empty(search)) { - return null; - } + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } // Rewind button - var hashes = search.slice(search.indexOf('?') + 1).split('&'); - return hashes.reduce(function (params, hash) { - var _hash$split = hash.split('='), - _hash$split2 = slicedToArray(_hash$split, 2), - key = _hash$split2[0], - val = _hash$split2[1]; + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } // Play/Pause button - return Object.assign(params, defineProperty$1({}, key, decodeURIComponent(val))); - }, {}); - }, + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + } // Fast forward button - // Convert object to URL parameters - buildUrlParams: function buildUrlParams(input) { - if (!utils.is.object(input)) { - return ''; - } - return Object.keys(input).map(function (key) { - return encodeURIComponent(key) + '=' + encodeURIComponent(input[key]); - }).join('&'); - }, + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } // Progress - // Remove HTML from a string - stripHTML: function stripHTML(source) { - var fragment = document.createDocumentFragment(); - var element = document.createElement('div'); - fragment.appendChild(element); - element.innerHTML = source; - return fragment.firstChild.innerText; - }, + if (this.config.controls.includes('progress')) { + var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider + progress.appendChild(controls.createRange.call(this, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress - // Get aspect ratio for dimensions - getAspectRatio: function getAspectRatio(width, height) { - var getRatio = function getRatio(w, h) { - return h === 0 ? w : getRatio(h, w % h); - }; - var ratio = getRatio(width, height); - return width / ratio + ':' + height / ratio; - }, + progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip + if (this.config.tooltips.seek) { + var tooltip = createElement('span', { + class: this.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; + } - // Get the transition end event - get transitionEndEvent() { - var element = document.createElement('span'); + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } // Media current time display - var events = { - WebkitTransition: 'webkitTransitionEnd', - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd otransitionend', - transition: 'transitionend' - }; - var type = Object.keys(events).find(function (event) { - return element.style[event] !== undefined; - }); + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } // Media duration display - return utils.is.string(type) ? events[type] : false; - }, - // Force repaint of element - repaint: function repaint(element) { - setTimeout(function () { - utils.toggleHidden(element, true); - element.offsetHeight; // eslint-disable-line - utils.toggleHidden(element, false); - }, 0); - } -}; + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } // Volume controls -// ========================================================================== -// Check for feature support -var support = { - // Basic support - audio: 'canPlayType' in document.createElement('audio'), - video: 'canPlayType' in document.createElement('video'), + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + var volume = createElement('div', { + class: 'plyr__volume' + }); // Toggle mute button - // Check for support - // Basic functionality vs full UI - check: function check(type, provider, playsinline) { - var api = false; - var ui = false; - var browser = utils.getBrowser(); - var canPlayInline = browser.isIPhone && playsinline && support.playsinline; - - switch (provider + ':' + type) { - case 'html5:video': - api = support.video; - ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline); - break; + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } // Volume range control - case 'html5:audio': - api = support.audio; - ui = api && support.rangeInput; - break; - case 'youtube:video': - case 'vimeo:video': - api = true; - ui = support.rangeInput && (!browser.isIPhone || canPlayInline); - break; + if (this.config.controls.includes('volume')) { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: this.config.volume + }; // Create the volume range slider - default: - api = support.audio && support.video; - ui = api && support.rangeInput; + volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + this.elements.volume = volume; } - return { - api: api, - ui: ui - }; - }, + container.appendChild(volume); + } // Toggle captions button - // Picture-in-picture support - // Safari only currently - pip: function () { - var browser = utils.getBrowser(); - return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode); - }(), + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } // Settings button / menu - // Airplay support - // Safari only currently - airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent), - // Inline playback support - // https://webkit.org/blog/6784/new-video-policies-for-ios/ - playsinline: 'playsInline' in document.createElement('video'), + if (this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { + var control = createElement('div', { + class: 'plyr__menu', + hidden: '' + }); + control.appendChild(controls.createButton.call(this, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu - // Check for mime type support against a player instance - // Credits: http://diveintohtml5.info/everything.html - // Related: http://www.leanbackplayer.com/test/h5mt.html - mime: function mime(type) { - var media = this.media; + var menu = createElement('div', { + role: 'menu' + }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; // Build the menu items + + this.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + controls.showMenuPanel.call(_this9, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this9.config)); + var value = createElement('span', { + class: _this9.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this9.config))); // Screen reader label + backButton.appendChild(createElement('span', { + class: _this9.config.classNames.hidden + }, i18n.get('menuBack', _this9.config))); // Go back via keyboard - try { - // Bail if no checking function - if (!this.isHTML5 || !utils.is.function(media.canPlayType)) { - return false; - } + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek - // Check directly if codecs specified - if (type.includes('codecs=')) { - return media.canPlayType(type).replace(/no/, ''); - } - // Type specific checks - if (this.isVideo) { - switch (type) { - case 'video/webm': - return media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''); + event.preventDefault(); + event.stopPropagation(); // Show the respective menu - case 'video/mp4': - return media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''); + controls.showMenuPanel.call(_this9, 'home', true); + }, false); // Go back via button click - case 'video/ogg': - return media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''); + on(backButton, 'click', function () { + controls.showMenuPanel.call(_this9, 'home', false); + }); // Add to pane - default: - return false; - } - } else if (this.isAudio) { - switch (type) { - case 'audio/mpeg': - return media.canPlayType('audio/mpeg;').replace(/no/, ''); + pane.appendChild(backButton); // Menu - case 'audio/ogg': - return media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''); + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this9.elements.settings.buttons[type] = menuItem; + _this9.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); + this.elements.settings.popup = popup; + this.elements.settings.menu = control; + } // Picture in picture button - case 'audio/wav': - return media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''); - default: - return false; - } - } - } catch (e) { - return false; - } + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } // Airplay button - // If we got this far, we're stuffed - return false; - }, + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } // Download button - // Check for textTracks support - textTracks: 'textTracks' in document.createElement('video'), - // Check for passive event listener support - // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - // https://www.youtube.com/watch?v=NPM6172J22g - passiveListeners: function () { - // Test via a getter in the options object to see if the passive property is accessed - var supported = false; - try { - var options = Object.defineProperty({}, 'passive', { - get: function get() { - supported = true; - return null; - } - }); - window.addEventListener('test', null, options); - } catch (e) { - // Do nothing + if (this.config.controls.includes('download')) { + var _attributes = { + element: 'a', + href: this.download, + target: '_blank' + }; + var download = this.config.urls.download; + + if (!is$1.url(download) && this.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(this.provider), + label: this.provider + }); } - return supported; - }(), + container.appendChild(controls.createButton.call(this, 'download', _attributes)); + } // Toggle fullscreen button - // <input type="range"> Sliders - rangeInput: function () { - var range = document.createElement('input'); - range.type = 'range'; - return range.type === 'range'; - }(), - // Touch - // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event - touch: 'ontouchstart' in document.documentElement, + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } // Larger overlaid play button - // Detect transitions support - transitions: utils.transitionEndEvent !== false, - // Reduced motion iOS & MacOS setting - // https://webkit.org/blog/7551/responsive-design-for-motion/ - reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches -}; + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } -// ========================================================================== + this.elements.controls = container; // Set available quality levels -var html5 = { - getSources: function getSources() { - if (!this.isHTML5) { - return null; - } + if (this.isHTML5) { + controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + } - return this.media.querySelectorAll('source'); + controls.setSpeedMenu.call(this); + return container; }, + // Insert controls + inject: function inject() { + var _this10 = this; + // Sprite + if (this.config.loadSprite) { + var icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX - // Get quality levels - getQualityOptions: function getQualityOptions() { - if (!this.isHTML5) { - return null; + if (icon.cors) { + loadSprite(icon.url, 'sprite-plyr'); } + } // Create a unique ID - // Get sources - var sources = html5.getSources.call(this); - if (utils.is.empty(sources)) { - return null; - } + this.id = Math.floor(Math.random() * 10000); // Null by default - // Get <source> with size attribute - var sizes = Array.from(sources).filter(function (source) { - return !utils.is.empty(source.getAttribute('size')); - }); + var container = null; + this.elements.controls = null; // Set template properties - // If none, bail - if (utils.is.empty(sizes)) { - return null; - } + var props = { + id: this.id, + seektime: this.config.seekTime, + title: this.config.title + }; + var update = true; // If function, run it and use output - // Reduce to unique list - return utils.dedupe(sizes.map(function (source) { - return Number(source.getAttribute('size')); - })); - }, - extend: function extend() { - if (!this.isHTML5) { - return; - } + if (is$1.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } // Convert falsy controls to empty array (primarily for empty strings) - var player = this; - // Quality - Object.defineProperty(player.media, 'quality', { - get: function get() { - // Get sources - var sources = html5.getSources.call(player); + if (!this.config.controls) { + this.config.controls = []; + } - if (utils.is.empty(sources)) { - return null; - } + if (is$1.element(this.config.controls) || is$1.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option + container = this.config.controls; + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: captions.getLabel.call(this) // TODO: Looping + // loop: 'None', - var matches = Array.from(sources).filter(function (source) { - return source.getAttribute('src') === player.source; - }); + }); + update = false; + } // Replace props with their value - if (utils.is.empty(matches)) { - return null; - } - return Number(matches[0].getAttribute('size')); - }, - set: function set(input) { - // Get sources - var sources = html5.getSources.call(player); + var replace = function replace(input) { + var result = input; + Object.entries(props).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + value = _ref3[1]; - if (utils.is.empty(sources)) { - return; - } + result = replaceAll(result, "{".concat(key, "}"), value); + }); + return result; + }; // Update markup - // Get matches for requested size - var matches = Array.from(sources).filter(function (source) { - return Number(source.getAttribute('size')) === input; - }); - // No matches for requested size - if (utils.is.empty(matches)) { - return; - } + if (update) { + if (is$1.string(this.config.controls)) { + container = replace(container); + } else if (is$1.element(container)) { + container.innerHTML = replace(container.innerHTML); + } + } // Controls container - // Get supported sources - var supported = matches.filter(function (source) { - return support.mime.call(player, source.getAttribute('type')); - }); - // No supported sources - if (utils.is.empty(supported)) { - return; - } + var target; // Inject to custom location - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality: input - }); + if (is$1.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } // Inject into the container by default - // Get current state - var currentTime = player.currentTime, - playing = player.playing; - // Set new source + if (!is$1.element(target)) { + target = this.elements.container; + } // Inject controls HTML (needs to be before captions, hence "afterbegin") - player.media.src = supported[0].getAttribute('src'); - // Load new source - player.media.load(); + var insertMethod = is$1.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be - // Resume playing - if (playing) { - player.play(); - } + if (!is$1.element(this.elements.controls)) { + controls.findElements.call(this); + } // Add pressed property to buttons - // Restore time - player.currentTime = currentTime; - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { - quality: input - }); + if (!is$1.empty(this.elements.buttons)) { + var addProperty = function addProperty(button) { + var className = _this10.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get: function get() { + return hasClass(button, className); + }, + set: function set() { + var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + toggleClass(button, className, pressed); } - }); - }, + }); + }; // Toggle classname when pressed property is set - // Cancel current network requests - // See https://github.com/sampotts/plyr/issues/174 - cancelRequests: function cancelRequests() { - if (!this.isHTML5) { - return; - } + Object.values(this.elements.buttons).filter(Boolean).forEach(function (button) { + if (is$1.array(button) || is$1.nodeList(button)) { + Array.from(button).filter(Boolean).forEach(addProperty); + } else { + addProperty(button); + } + }); + } // Edge sometimes doesn't finish the paint so force a repaint - // Remove child sources - utils.removeElement(html5.getSources()); - // Set blank video src attribute - // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error - // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection - this.media.setAttribute('src', this.config.blankVideo); + if (browser.isEdge) { + repaint(target); + } // Setup tooltips - // Load the new empty source - // This will cancel existing requests - // See https://github.com/sampotts/plyr/issues/174 - this.media.load(); - // Debugging - this.debug.log('Cancelled network requests'); + if (this.config.tooltips.controls) { + var _this$config = this.config, + classNames = _this$config.classNames, + selectors = _this$config.selectors; + var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); + var labels = getElements.call(this, selector); + Array.from(labels).forEach(function (label) { + toggleClass(label, _this10.config.classNames.hidden, false); + toggleClass(label, _this10.config.classNames.tooltip, true); + }); + } } -}; + }; -// ========================================================================== + /** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ -var i18n = { - get: function get() { - var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + function parseUrl(input) { + var safe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var url = input; - if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) { - return ''; - } - - var string = config.i18n[key]; + if (safe) { + var parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } - var replace = { - '{seektime}': config.seekTime, - '{title}': config.title - }; + try { + return new URL(url); + } catch (e) { + return null; + } + } // Convert object to URLSearchParams - Object.entries(replace).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + function buildUrlParams(input) { + var params = new URLSearchParams(); - string = utils.replaceAll(string, key, value); - }); + if (is$1.object(input)) { + Object.entries(input).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; - return string; + params.set(key, value); + }); } -}; -// ========================================================================== - -// Sniff out the browser -var browser = utils.getBrowser(); + return params; + } -var ui = { - addStyleHook: function addStyleHook() { - utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); - utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); - }, + var captions = { + // Setup captions + setup: function setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } // Only Vimeo and HTML5 video supported at this point - // Toggle native HTML5 media controls - toggleNativeControls: function toggleNativeControls() { - var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - if (toggle && this.isHTML5) { - this.media.setAttribute('controls', ''); - } else { - this.media.removeAttribute('controls'); + if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { + // Clear menu and hide + if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); } - }, + return; + } // Inject the container - // Setup the UI - build: function build() { - var _this = this; - // Re-attach media element listeners - // TODO: Use event bubbling? - this.listeners.media(); + if (!is$1.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); + insertAfter(this.elements.captions, this.elements.wrapper); + } // Fix IE captions if CORS is used + // Fetch captions and inject as blobs instead (data URIs not supported!) - // Don't setup interface if no support - if (!this.supported.ui) { - this.debug.warn('Basic support only for ' + this.provider + ' ' + this.type); - // Restore native controls - ui.toggleNativeControls.call(this, true); + if (browser.isIE && window.URL) { + var elements = this.media.querySelectorAll('track'); + Array.from(elements).forEach(function (track) { + var src = track.getAttribute('src'); + var url = parseUrl(src); - // Bail - return; - } + if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + fetch(src, 'blob').then(function (blob) { + track.setAttribute('src', window.URL.createObjectURL(blob)); + }).catch(function () { + removeElement(track); + }); + } + }); + } // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state - // Inject custom controls if not present - if (!utils.is.element(this.elements.controls)) { - // Inject custom controls - controls.inject.call(this); - // Re-attach control listeners - this.listeners.controls(); - } + var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + var languages = dedupe(browserLanguages.map(function (language) { + return language.split('-')[0]; + })); + var language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto' - // Remove native controls - ui.toggleNativeControls.call(this); + if (language === 'auto') { + var _languages = _slicedToArray(languages, 1); - // Captions - captions.setup.call(this); + language = _languages[0]; + } - // Reset volume - this.volume = null; + var active = this.storage.get('captions'); - // Reset mute state - this.muted = null; + if (!is$1.boolean(active)) { + active = this.config.captions.active; + } - // Reset speed - this.speed = null; + Object.assign(this.captions, { + toggled: false, + active: active, + language: language, + languages: languages + }); // Watch changes to textTracks and update captions menu - // Reset loop state - this.loop = null; + if (this.isHTML5) { + var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); + } // Update available languages in list next tick (the event must not be triggered before the listeners) - // Reset quality setting - this.quality = null; - // Reset volume display - ui.updateVolume.call(this); + setTimeout(captions.update.bind(this), 0); + }, + // Update available language options in settings based on tracks + update: function update() { + var _this = this; - // Reset time display - ui.timeUpdate.call(this); + var tracks = captions.getTracks.call(this, true); // Get the wanted language - // Update the UI - ui.checkPlaying.call(this); + var _this$captions = this.captions, + active = _this$captions.active, + language = _this$captions.language, + meta = _this$captions.meta, + currentTrackNode = _this$captions.currentTrackNode; + var languageExists = Boolean(tracks.find(function (track) { + return track.language === language; + })); // Handle tracks (add event listener and "pseudo"-default) - // Check for picture-in-picture support - utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); + if (this.isHTML5 && this.isVideo) { + tracks.filter(function (track) { + return !meta.get(track); + }).forEach(function (track) { + _this.debug.log('Track added', track); // Attempt to store if the original dom element was "default" - // Check for airplay support - utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); - // Add iOS class - utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); + meta.set(track, { + default: track.mode === 'showing' + }); // Turn off native caption rendering to avoid double captions - // Add touch class - utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); + track.mode = 'hidden'; // Add event listener for cue changes - // Ready for API calls - this.ready = true; + on.call(_this, track, 'cuechange', function () { + return captions.updateCues.call(_this); + }); + }); + } // Update language first time it matches, or if the previous matching track was removed - // Ready event at end of execution stack - setTimeout(function () { - utils.dispatchEvent.call(_this, _this.media, 'ready'); - }, 0); - // Set the title - ui.setTitle.call(this); + if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } // Enable or disable captions based on track length - // Set the poster image - ui.setPoster.call(this); - }, + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list - // Setup aria attribute for play and iframe title - setTitle: function setTitle() { - // Find the current text - var label = i18n.get('play', this.config); + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + }, + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle: function toggle(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - // If there's a media title set, use that for the label - if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) { - label += ', ' + this.config.title; + // If there's no full support + if (!this.supported.ui) { + return; + } - // Set container label - this.elements.container.setAttribute('aria-label', this.config.title); - } + var toggled = this.captions.toggled; // Current state - // If there's a play button, set label - if (utils.is.nodeList(this.elements.buttons.play)) { - Array.from(this.elements.buttons.play).forEach(function (button) { - button.setAttribute('aria-label', label); - }); - } + var activeClass = this.config.classNames.captions.active; // Get the next state + // If the method is called without parameter, toggle based on current value - // Set iframe title - // https://github.com/sampotts/plyr/issues/124 - if (this.isEmbed) { - var iframe = utils.getElement.call(this, 'iframe'); + var active = is$1.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event - if (!utils.is.element(iframe)) { - return; - } + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ + captions: active + }); + } // Force language if the call isn't passive and there is no matching language to toggle to - // Default to media type - var title = !utils.is.empty(this.config.title) ? this.config.title : 'video'; - var format = i18n.get('frameTitle', this.config); - iframe.setAttribute('title', format.replace('{title}', title)); - } - }, + if (!this.language && active && !passive) { + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [this.captions.language].concat(_toConsumableArray(this.captions.languages)), true); // Override user preferences to avoid switching languages if a matching track is added + this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference - // Set the poster image - setPoster: function setPoster() { - if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) { - return; - } + captions.set.call(this, tracks.indexOf(track)); + return; + } // Toggle button if it's enabled - // Set the inline style - var posters = this.poster.split(','); - this.elements.poster.style.backgroundImage = posters.map(function (p) { - return 'url(\'' + p + '\')'; - }).join(','); - }, + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } // Add class hook - // Check playing state - checkPlaying: function checkPlaying(event) { - // Class hooks - utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing); - utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused); - utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); - // Set ARIA state - utils.toggleState(this.elements.buttons.play, this.playing); + toggleClass(this.elements.container, activeClass, active); + this.captions.toggled = active; // Update settings menu - // Only update controls on non timeupdate events - if (utils.is.event(event) && event.type === 'timeupdate') { - return; - } + controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) - // Toggle controls - this.toggleControls(!this.playing); + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } }, + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set: function set(index) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var tracks = captions.getTracks.call(this); // Disable captions if setting to -1 + if (index === -1) { + captions.toggle.call(this, false, passive); + return; + } - // Check if media is loading - checkLoading: function checkLoading(event) { - var _this2 = this; + if (!is$1.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } - this.loading = ['stalled', 'waiting'].includes(event.type); + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; + } - // Clear timer - clearTimeout(this.timers.loading); + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + var track = tracks[index]; - // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(function () { - // Toggle container class hook - utils.toggleClass(_this2.elements.container, _this2.config.classNames.loading, _this2.loading); + var _ref = track || {}, + language = _ref.language; // Store reference to node for invalidation on remove - // Show controls if loading, hide if done - _this2.toggleControls(_this2.loading); - }, this.loading ? 250 : 0); - }, + this.captions.currentTrackNode = track; // Update settings menu - // Check if media failed to load - checkFailed: function checkFailed() { - var _this3 = this; + controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences - // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState - this.failed = this.media.networkState === 3; + if (!passive) { + this.captions.language = language; + this.storage.set({ + language: language + }); + } // Handle Vimeo captions - if (this.failed) { - utils.toggleClass(this.elements.container, this.config.classNames.loading, false); - utils.toggleClass(this.elements.container, this.config.classNames.error, true); - } - // Clear timer - clearTimeout(this.timers.failed); + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } // Trigger event - // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(function () { - // Toggle container class hook - utils.toggleClass(_this3.elements.container, _this3.config.classNames.loading, _this3.loading); - // Show controls if loading, hide if done - _this3.toggleControls(_this3.loading); - }, this.loading ? 250 : 0); - }, + triggerEvent.call(this, this.media, 'languagechange'); + } // Show captions - // Update volume UI and storage - updateVolume: function updateVolume() { - if (!this.supported.ui) { - return; - } + captions.toggle.call(this, true, passive); - // Update range - if (utils.is.element(this.elements.inputs.volume)) { - ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); - } - - // Update mute state - if (utils.is.element(this.elements.buttons.mute)) { - utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); - } + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } }, + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage: function setLanguage(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + if (!is$1.string(input)) { + this.debug.warn('Invalid language argument', input); + return; + } // Normalize - // Update seek value and lower fill - setRange: function setRange(target) { - var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - if (!utils.is.element(target)) { - return; - } + var language = input.toLowerCase(); + this.captions.language = language; // Set currentTrack - // eslint-disable-next-line - target.value = value; + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks: function getTracks() { + var _this2 = this; - // Webkit range fill - controls.updateRangeFill.call(this, target); + var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + // Handle media or textTracks missing or null + var tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + + return tracks.filter(function (track) { + return !_this2.isHTML5 || update || _this2.captions.meta.has(track); + }).filter(function (track) { + return ['captions', 'subtitles'].includes(track.kind); + }); }, + // Match tracks based on languages and get the first + findTrack: function findTrack(languages) { + var _this3 = this; + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var tracks = captions.getTracks.call(this); - // Set <progress> value - setProgress: function setProgress(target, input) { - var value = utils.is.number(input) ? input : 0; - var progress = utils.is.element(target) ? target : this.elements.display.buffer; + var sortIsDefault = function sortIsDefault(track) { + return Number((_this3.captions.meta.get(track) || {}).default); + }; - // Update value and label - if (utils.is.element(progress)) { - progress.value = value; + var sorted = Array.from(tracks).sort(function (a, b) { + return sortIsDefault(b) - sortIsDefault(a); + }); + var track; + languages.every(function (language) { + track = sorted.find(function (track) { + return track.language === language; + }); + return !track; // Break iteration if there is a match + }); // If no match is found but is required, get first - // Update text label inside - var label = progress.getElementsByTagName('span')[0]; - if (utils.is.element(label)) { - label.childNodes[0].nodeValue = value; - } - } + return track || (force ? sorted[0] : undefined); + }, + // Get the current track + getCurrentTrack: function getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; }, + // Get UI label for track + getLabel: function getLabel(track) { + var currentTrack = track; + if (!is$1.track(currentTrack) && support.textTracks && this.captions.toggled) { + currentTrack = captions.getCurrentTrack.call(this); + } - // Update <progress> elements - updateProgress: function updateProgress(event) { - if (!this.supported.ui || !utils.is.event(event)) { - return; + if (is$1.track(currentTrack)) { + if (!is$1.empty(currentTrack.label)) { + return currentTrack.label; } - var value = 0; + if (!is$1.empty(currentTrack.language)) { + return track.language.toUpperCase(); + } - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - value = utils.getPercentage(this.currentTime, this.duration); + return i18n.get('enabled', this.config); + } - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate') { - ui.setRange.call(this, this.elements.inputs.seek, value); - } + return i18n.get('disabled', this.config); + }, + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues: function updateCues(input) { + // Requires UI + if (!this.supported.ui) { + return; + } - break; + if (!is$1.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; + } // Only accept array or empty input - // Check buffer status - case 'playing': - case 'progress': - ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100); - break; + if (!is$1.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); + return; + } - default: - break; - } - } - }, + var cues = input; // Get cues from track + if (!cues) { + var track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []).map(function (cue) { + return cue.getCueAsHTML(); + }).map(getHTML); + } // Set new caption text - // Update the displayed time - updateTimeDisplay: function updateTimeDisplay() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - // Bail if there's no element to display or the value isn't a number - if (!utils.is.element(target) || !utils.is.number(time)) { - return; - } + var content = cues.map(function (cueText) { + return cueText.trim(); + }).join('\n'); + var changed = content !== this.elements.captions.innerHTML; - // Always display hours if duration is over an hour - var forceHours = utils.getHours(this.duration) > 0; + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + var caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); // Trigger event + + triggerEvent.call(this, this.media, 'cuechange'); + } + } + }; - // eslint-disable-next-line no-param-reassign - target.textContent = utils.formatTime(time, forceHours, inverted); + // ========================================================================== + // Plyr default config + // ========================================================================== + var defaults = { + // Disable + enabled: true, + // Custom media title + title: '', + // Logging to console + debug: false, + // Auto play (if supported) + autoplay: false, + // Only allow one media playing at once (vimeo only) + autopause: true, + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, + // Default time to skip when rewind/fast forward + seekTime: 10, + // Default volume + volume: 1, + muted: false, + // Pass a custom duration + duration: null, + // Display the media duration on load in the current time position + // If you have opted to display both duration and currentTime, this is ignored + displayDuration: true, + // Invert the current time to be a countdown + invertTime: true, + // Clicking the currentTime inverts it's value to show time left rather than elapsed + toggleInvert: true, + // Aspect ratio (for embeds) + ratio: '16:9', + // Click video container to play/pause + clickToPlay: true, + // Auto hide the controls + hideControls: true, + // Reset to start when playback ended + resetOnEnd: false, + // Disable the standard context menu + disableContextMenu: true, + // Sprite (for icons) + loadSprite: true, + iconPrefix: 'plyr', + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', + // Blank video (used to prevent errors on source change) + blankVideo: 'https://cdn.plyr.io/static/blank.mp4', + // Quality default + quality: { + default: 576, + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] }, + // Set loops + loop: { + active: false // start: null, + // end: null, + }, + // Speed default and options to display + speed: { + selected: 1, + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] + }, + // Keyboard shortcut settings + keyboard: { + focused: true, + global: false + }, + // Display tooltips + tooltips: { + controls: false, + seek: true + }, + // Captions settings + captions: { + active: false, + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false + }, + // Fullscreen settings + fullscreen: { + enabled: true, + // Allow fullscreen? + fallback: true, + // Fallback using full viewport/window + iosNative: false // Use the native fullscreen in iOS (disables custom controls) - // Handle time change event - timeUpdate: function timeUpdate(event) { - // Only invert if only one time element is displayed and used for both duration and currentTime - var invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime; + }, + // Local storage + storage: { + enabled: true, + key: 'plyr' + }, + // Default controls + controls: ['play-large', // 'restart', + // 'rewind', + 'play', // 'fast-forward', + 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download', + 'fullscreen'], + settings: ['captions', 'quality', 'speed'], + // Localisation + i18n: { + restart: 'Restart', + rewind: 'Rewind {seektime}s', + play: 'Play', + pause: 'Pause', + fastForward: 'Forward {seektime}s', + seek: 'Seek', + seekLabel: '{currentTime} of {duration}', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + download: 'Download', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + menuBack: 'Go back to previous menu', + speed: 'Speed', + normal: 'Normal', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + disabled: 'Disabled', + enabled: 'Enabled', + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } + }, + // URLs + urls: { + download: null, + vimeo: { + sdk: 'https://player.vimeo.com/api/player.js', + iframe: 'https://player.vimeo.com/video/{0}?{1}', + api: 'https://vimeo.com/api/v2/video/{0}.json' + }, + youtube: { + sdk: 'https://www.youtube.com/iframe_api', + api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + }, + googleIMA: { + sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' + } + }, + // Custom control listeners + listeners: { + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + fastForward: null, + mute: null, + volume: null, + captions: null, + download: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null + }, + // Events to watch and bubble + events: [// Events to watch on HTML5 media elements and bubble + // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events + 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube + 'statechange', // Quality + 'qualitychange', // Ads + 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], + // Selectors + // Change these to match your template if using custom HTML + selectors: { + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls' + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + fastForward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]' + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]' + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', + // Used later + volume: '.plyr__volume--display' + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + caption: '.plyr__caption', + menu: { + quality: '.js-plyr__menu__list--quality' + } + }, + // Class hooks added to the player in different states + classNames: { + type: 'plyr--{0}', + provider: 'plyr--{0}', + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + embedContainer: 'plyr__video-embed__container', + poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', + ads: 'plyr__ads', + control: 'plyr__control', + controlPressed: 'plyr__control--pressed', + playing: 'plyr--playing', + paused: 'plyr--paused', + stopped: 'plyr--stopped', + loading: 'plyr--loading', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + cues: 'plyr__cues', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time' + }, + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open' + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active' + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback' + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active' + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active' + }, + tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' + } + }, + // Embed attributes + attributes: { + embed: { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id' + } + }, + // API keys + keys: { + google: null + }, + // Advertisements plugin + // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio + ads: { + enabled: false, + publisherId: '', + tagUrl: '' + }, + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '' + }, + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false + }, + // YouTube plugin + youtube: { + noCookie: false, + // Whether to use an alternative version of YouTube without cookies + rel: 0, + // No related vids + showinfo: 0, + // Hide info + iv_load_policy: 3, + // Hide annotations + modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) - // Duration - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); + } + }; - // Ignore updates while seeking - if (event && event.type === 'timeupdate' && this.media.seeking) { - return; - } + // ========================================================================== + // Plyr states + // ========================================================================== + var pip = { + active: 'picture-in-picture', + inactive: 'inline' + }; - // Playing progress - ui.updateProgress.call(this, event); - }, + // ========================================================================== + // Plyr supported types and providers + // ========================================================================== + var providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo' + }; + var types = { + audio: 'audio', + video: 'video' + }; + /** + * Get provider by URL + * @param {String} url + */ + function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } // Vimeo - // Show the duration on metadataloaded - durationUpdate: function durationUpdate() { - if (!this.supported.ui) { - return; - } - // If there's a spot to display duration - var hasDuration = utils.is.element(this.elements.display.duration); + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; + } - // If there's only one time display, display duration there - if (!hasDuration && this.config.displayDuration && this.paused) { - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); - } + return null; + } - // If there's a duration element, update content - if (hasDuration) { - ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); - } + // ========================================================================== + // Console wrapper + // ========================================================================== + var noop = function noop() {}; - // Update the tooltip (if visible) - controls.updateSeekTooltip.call(this); - } -}; + var Console = + /*#__PURE__*/ + function () { + function Console() { + var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; -// ========================================================================== + _classCallCheck(this, Console); -// Sniff out the browser -var browser$1 = utils.getBrowser(); + this.enabled = window.console && enabled; -var controls = { - // Webkit polyfill for lower fill range - updateRangeFill: function updateRangeFill(target) { - // Get range from event if event passed - var range = utils.is.event(target) ? target.target : target; + if (this.enabled) { + this.log('Debugging enabled'); + } + } - // Needs to be a valid <input type='range'> - if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { - return; - } + _createClass(Console, [{ + key: "log", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + }, { + key: "warn", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + }, { + key: "error", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } + }]); - // Set aria value for https://github.com/sampotts/plyr/issues/905 - range.setAttribute('aria-valuenow', range.value); + return Console; + }(); - // WebKit only - if (!browser$1.isWebkit) { - return; - } + function onChange() { + if (!this.enabled) { + return; + } // Update toggle button - // Set CSS custom property - range.style.setProperty('--value', range.value / range.max * 100 + '%'); - }, + var button = this.player.elements.buttons.fullscreen; - // Get icon URL - getIconUrl: function getIconUrl() { - var url = new URL(this.config.iconUrl, window.location); - var cors = url.host !== window.location.host || browser$1.isIE && !window.svg4everybody; + if (is$1.element(button)) { + button.pressed = this.active; + } // Trigger an event - return { - url: this.config.iconUrl, - cors: cors - }; - }, + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container - // Find the UI controls and store references in custom controls - // TODO: Allow settings menus with custom controls - findElements: function findElements() { - try { - this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper); - - // Buttons - this.elements.buttons = { - play: utils.getElements.call(this, this.config.selectors.buttons.play), - pause: utils.getElement.call(this, this.config.selectors.buttons.pause), - restart: utils.getElement.call(this, this.config.selectors.buttons.restart), - rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind), - fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward), - mute: utils.getElement.call(this, this.config.selectors.buttons.mute), - pip: utils.getElement.call(this, this.config.selectors.buttons.pip), - airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay), - settings: utils.getElement.call(this, this.config.selectors.buttons.settings), - captions: utils.getElement.call(this, this.config.selectors.buttons.captions), - fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen) - }; + if (!browser.isIos) { + trapFocus.call(this.player, this.target, this.active); + } + } - // Progress - this.elements.progress = utils.getElement.call(this, this.config.selectors.progress); + function toggleFallback() { + var _this = this; - // Inputs - this.elements.inputs = { - seek: utils.getElement.call(this, this.config.selectors.inputs.seek), - volume: utils.getElement.call(this, this.config.selectors.inputs.volume) - }; + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - // Display - this.elements.display = { - buffer: utils.getElement.call(this, this.config.selectors.display.buffer), - currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime), - duration: utils.getElement.call(this, this.config.selectors.display.duration) - }; + // Store or restore scroll position + if (toggle) { + this.scrollPosition = { + x: window.scrollX || 0, + y: window.scrollY || 0 + }; + } else { + window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + } // Toggle scroll - // Seek tooltip - if (utils.is.element(this.elements.progress)) { - this.elements.display.seekTooltip = this.elements.progress.querySelector('.' + this.config.classNames.tooltip); - } - return true; - } catch (error) { - // Log it - this.debug.warn('It looks like there is a problem with your custom controls HTML', error); + document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook - // Restore native video controls - this.toggleNativeControls(true); + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+ - return false; - } - }, + if (browser.isIos) { + var viewport = document.head.querySelector('meta[name="viewport"]'); + var property = 'viewport-fit=cover'; // Inject the viewport meta if required + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } // Check if the property already exists - // Create <svg> icon - createIcon: function createIcon(type, attributes) { - var namespace = 'http://www.w3.org/2000/svg'; - var iconUrl = controls.getIconUrl.call(this); - var iconPath = (!iconUrl.cors ? iconUrl.url : '') + '#' + this.config.iconPrefix; - - // Create <svg> - var icon = document.createElementNS(namespace, 'svg'); - utils.setAttributes(icon, utils.extend(attributes, { - role: 'presentation', - focusable: 'false' - })); - // Create the <use> to reference sprite - var use = document.createElementNS(namespace, 'use'); - var path = iconPath + '-' + type; + var hasProperty = is$1.string(viewport.content) && viewport.content.includes(property); - // Set `href` attributes - // https://github.com/sampotts/plyr/issues/460 - // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href - if ('href' in use) { - use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); - } else { - use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); + if (toggle) { + this.cleanupViewport = !hasProperty; + + if (!hasProperty) { + viewport.content += ",".concat(property); } + } else if (this.cleanupViewport) { + viewport.content = viewport.content.split(',').filter(function (part) { + return part.trim() !== property; + }).join(','); + } // Force a repaint as sometimes Safari doesn't want to fill the screen - // Add <use> to <svg> - icon.appendChild(use); - return icon; - }, + setTimeout(function () { + return repaint(_this.target); + }, 100); + } // Toggle button and fire events - // Create hidden text label - createLabel: function createLabel(type, attr) { - var text = i18n.get(type, this.config); - var attributes = Object.assign({}, attr); + onChange.call(this); + } - switch (type) { - case 'pip': - text = 'PIP'; - break; + var Fullscreen = + /*#__PURE__*/ + function () { + function Fullscreen(player) { + var _this2 = this; - case 'airplay': - text = 'AirPlay'; - break; + _classCallCheck(this, Fullscreen); - default: - break; - } + // Keep reference to parent + this.player = player; // Get prefix - if ('class' in attributes) { - attributes.class += ' ' + this.config.classNames.hidden; - } else { - attributes.class = this.config.classNames.hidden; - } + this.prefix = Fullscreen.prefix; + this.property = Fullscreen.property; // Scroll position - return utils.createElement('span', attributes, text); - }, + this.scrollPosition = { + x: 0, + y: 0 + }; // Force the use of 'full window/browser' rather than fullscreen + this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners + // Handle event (incase user presses escape etc) - // Create a badge - createBadge: function createBadge(text) { - if (utils.is.empty(text)) { - return null; + on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { + // TODO: Filter for target?? + onChange.call(_this2); + }); // Fullscreen toggle on double click + + on.call(this.player, this.player.elements.container, 'dblclick', function (event) { + // Ignore double click in controls + if (is$1.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) { + return; } - var badge = utils.createElement('span', { - class: this.config.classNames.menu.value - }); + _this2.toggle(); + }); // Update the UI - badge.appendChild(utils.createElement('span', { - class: this.config.classNames.menu.badge - }, text)); + this.update(); + } // Determine if native supported - return badge; - }, + _createClass(Fullscreen, [{ + key: "update", + // Update UI + value: function update() { + if (this.enabled) { + var mode; - // Create a <button> - createButton: function createButton(buttonType, attr) { - var button = utils.createElement('button'); - var attributes = Object.assign({}, attr); - var type = utils.toCamelCase(buttonType); - - var toggle = false; - var label = void 0; - var icon = void 0; - var labelPressed = void 0; - var iconPressed = void 0; - - if (!('type' in attributes)) { - attributes.type = 'button'; - } + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } - if ('class' in attributes) { - if (attributes.class.includes(this.config.classNames.control)) { - attributes.class += ' ' + this.config.classNames.control; - } + this.player.debug.log("".concat(mode, " fullscreen enabled")); } else { - attributes.class = this.config.classNames.control; - } + this.player.debug.log('Fullscreen not supported and fallback disabled'); + } // Add styling hook to show button - // Large play button - switch (buttonType) { - case 'play': - toggle = true; - label = 'play'; - labelPressed = 'pause'; - icon = 'play'; - iconPressed = 'pause'; - break; - case 'mute': - toggle = true; - label = 'mute'; - labelPressed = 'unmute'; - icon = 'volume'; - iconPressed = 'muted'; - break; - - case 'captions': - toggle = true; - label = 'enableCaptions'; - labelPressed = 'disableCaptions'; - icon = 'captions-off'; - iconPressed = 'captions-on'; - break; + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + } // Make an element fullscreen - case 'fullscreen': - toggle = true; - label = 'enterFullscreen'; - labelPressed = 'exitFullscreen'; - icon = 'enter-fullscreen'; - iconPressed = 'exit-fullscreen'; - break; + }, { + key: "enter", + value: function enter() { + if (!this.enabled) { + return; + } // iOS native fullscreen doesn't need the request step - case 'play-large': - attributes.class += ' ' + this.config.classNames.control + '--overlaid'; - type = 'play'; - label = 'play'; - icon = 'play'; - break; - default: - label = type; - icon = buttonType; + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, true); + } else if (!this.prefix) { + this.target.requestFullscreen(); + } else if (!is$1.empty(this.prefix)) { + this.target["".concat(this.prefix, "Request").concat(this.property)](); } + } // Bail from fullscreen - // Setup toggle icon and labels - if (toggle) { - // Icon - button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' })); - button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' })); - - // Label/Tooltip - button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' })); - button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' })); + }, { + key: "exit", + value: function exit() { + if (!this.enabled) { + return; + } // iOS native fullscreen + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitExitFullscreen(); + this.player.play(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, false); + } else if (!this.prefix) { + (document.cancelFullScreen || document.exitFullscreen).call(document); + } else if (!is$1.empty(this.prefix)) { + var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; + document["".concat(this.prefix).concat(action).concat(this.property)](); + } + } // Toggle state - // Add aria attributes - attributes['aria-pressed'] = false; + }, { + key: "toggle", + value: function toggle() { + if (!this.active) { + this.enter(); } else { - button.appendChild(controls.createIcon.call(this, icon)); - button.appendChild(controls.createLabel.call(this, label)); + this.exit(); } + } + }, { + key: "usingNative", + // If we're actually using native + get: function get() { + return Fullscreen.native && !this.forceFallback; + } // Get the prefix for handlers - // Merge attributes - utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + }, { + key: "enabled", + // Determine if fullscreen is enabled + get: function get() { + return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + } // Get active state - utils.setAttributes(button, attributes); + }, { + key: "active", + get: function get() { + if (!this.enabled) { + return false; + } // Fallback using classname - // We have multiple play buttons - if (type === 'play') { - if (!utils.is.array(this.elements.buttons[type])) { - this.elements.buttons[type] = []; - } - this.elements.buttons[type].push(button); - } else { - this.elements.buttons[type] = button; + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); } - return button; - }, + var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; + return element === this.target; + } // Get target element + }, { + key: "target", + get: function get() { + return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + } + }], [{ + key: "native", + get: function get() { + return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + } + }, { + key: "prefix", + get: function get() { + // No prefix + if (is$1.function(document.exitFullscreen)) { + return ''; + } // Check for fullscreen support by vendor prefix + + + var value = ''; + var prefixes = ['webkit', 'moz', 'ms']; + prefixes.some(function (pre) { + if (is$1.function(document["".concat(pre, "ExitFullscreen")]) || is$1.function(document["".concat(pre, "CancelFullScreen")])) { + value = pre; + return true; + } - // Create an <input type='range'> - createRange: function createRange(type, attributes) { - // Seek label - var label = utils.createElement('label', { - for: attributes.id, - id: attributes.id + '-label', - class: this.config.classNames.hidden - }, i18n.get(type, this.config)); - - // Seek input - var input = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { - type: 'range', - min: 0, - max: 100, - step: 0.01, - value: 0, - autocomplete: 'off', - // A11y fixes for https://github.com/sampotts/plyr/issues/905 - role: 'slider', - 'aria-labelledby': attributes.id + '-label', - 'aria-valuemin': 0, - 'aria-valuemax': 100, - 'aria-valuenow': 0 - }, attributes)); - - this.elements.inputs[type] = input; - - // Set the fill for webkit now - controls.updateRangeFill.call(this, input); - - return { - label: label, - input: input - }; - }, + return false; + }); + return value; + } + }, { + key: "property", + get: function get() { + return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + } + }]); + return Fullscreen; + }(); - // Create a <progress> - createProgress: function createProgress(type, attributes) { - var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), { - min: 0, - max: 100, - value: 0, - role: 'presentation', - 'aria-hidden': true - }, attributes)); + // 20.2.2.28 Math.sign(x) + var _mathSign = Math.sign || function sign(x) { + // eslint-disable-next-line no-self-compare + return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1; + }; - // Create the label inside - if (type !== 'volume') { - progress.appendChild(utils.createElement('span', null, '0')); + // 20.2.2.28 Math.sign(x) - var suffix = ''; - switch (type) { - case 'played': - suffix = i18n.get('played', this.config); - break; - case 'buffer': - suffix = i18n.get('buffered', this.config); - break; + _export(_export.S, 'Math', { sign: _mathSign }); - default: - break; - } + // ========================================================================== + // Load image avoiding xhr/fetch CORS issues + // Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded + // By default it checks if it is at least 1px, but you can add a second argument to change this + // ========================================================================== + function loadImage(src) { + var minWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return new Promise(function (resolve, reject) { + var image = new Image(); - progress.textContent = '% ' + suffix.toLowerCase(); - } + var handler = function handler() { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; - this.elements.display[type] = progress; + Object.assign(image, { + onload: handler, + onerror: handler, + src: src + }); + }); + } - return progress; + var ui = { + addStyleHook: function addStyleHook() { + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); }, + // Toggle native HTML5 media controls + toggleNativeControls: function toggleNativeControls() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + // Setup the UI + build: function build() { + var _this = this; - // Create time display - createTime: function createTime(type) { - var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]); + // Re-attach media element listeners + // TODO: Use event bubbling? + this.listeners.media(); // Don't setup interface if no support - var container = utils.createElement('div', utils.extend(attributes, { - class: 'plyr__time ' + attributes.class, - 'aria-label': i18n.get(type, this.config) - }), '00:00'); + if (!this.supported.ui) { + this.debug.warn("Basic support only for ".concat(this.provider, " ").concat(this.type)); // Restore native controls - // Reference for updates - this.elements.display[type] = container; + ui.toggleNativeControls.call(this, true); // Bail - return container; - }, + return; + } // Inject custom controls if not present - // Create a settings menu item - createMenuItem: function createMenuItem(value, list, type, title) { - var badge = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - var checked = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + if (!is$1.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); // Re-attach control listeners - var item = utils.createElement('li'); + this.listeners.controls(); + } // Remove native controls - var label = utils.createElement('label', { - class: this.config.classNames.control - }); - var radio = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { - type: 'radio', - name: 'plyr-' + type, - value: value, - checked: checked, - class: 'plyr__sr-only' - })); + ui.toggleNativeControls.call(this); // Setup captions for HTML5 - var faux = utils.createElement('span', { hidden: '' }); + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume - label.appendChild(radio); - label.appendChild(faux); - label.insertAdjacentHTML('beforeend', title); - if (utils.is.element(badge)) { - label.appendChild(badge); - } + this.volume = null; // Reset mute state - item.appendChild(label); - list.appendChild(item); - }, + this.muted = null; // Reset speed + this.speed = null; // Reset loop state - // Update hover tooltip for seeking - updateSeekTooltip: function updateSeekTooltip(event) { - var _this = this; + this.loop = null; // Reset quality setting - // Bail if setting not true - if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) { - return; - } + this.quality = null; // Reset volume display - // Calculate percentage - var percent = 0; - var clientRect = this.elements.inputs.seek.getBoundingClientRect(); - var visible = this.config.classNames.tooltip + '--visible'; + controls.updateVolume.call(this); // Reset time display - var toggle = function toggle(_toggle) { - utils.toggleClass(_this.elements.display.seekTooltip, visible, _toggle); - }; + controls.timeUpdate.call(this); // Update the UI - // Hide on touch - if (this.touch) { - toggle(false); - return; - } + ui.checkPlaying.call(this); // Check for picture-in-picture support - // Determine percentage, if already visible - if (utils.is.event(event)) { - percent = 100 / clientRect.width * (event.pageX - clientRect.left); - } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { - percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); - } else { - return; - } + toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support - // Set bounds - if (percent < 0) { - percent = 0; - } else if (percent > 100) { - percent = 100; - } + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class - // Display the time a click would seek to - ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class - // Set position - this.elements.display.seekTooltip.style.left = percent + '%'; + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls - // Show/hide the tooltip - // If the event is a moues in/out and percentage is inside bounds - if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { - toggle(event.type === 'mouseenter'); - } - }, + this.ready = true; // Ready event at end of execution stack + setTimeout(function () { + triggerEvent.call(_this, _this.media, 'ready'); + }, 0); // Set the title - // Hide/show a tab - toggleTab: function toggleTab(setting, toggle) { - utils.toggleHidden(this.elements.settings.tabs[setting], !toggle); - }, + ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(function () {}); + } // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) - // Set the quality menu - // TODO: Vimeo support - setQualityMenu: function setQualityMenu(options) { - var _this2 = this; - // Menu required - if (!utils.is.element(this.elements.settings.panes.quality)) { - return; - } + if (this.config.duration) { + controls.durationUpdate.call(this); + } + }, + // Setup aria attribute for play and iframe title + setTitle: function setTitle() { + // Find the current text + var label = i18n.get('play', this.config); // If there's a media title set, use that for the label - var type = 'quality'; - var list = this.elements.settings.panes.quality.querySelector('ul'); + if (is$1.string(this.config.title) && !is$1.empty(this.config.title)) { + label += ", ".concat(this.config.title); + } // If there's a play button, set label - // Set options if passed and filter based on config - if (utils.is.array(options)) { - this.options.quality = options.filter(function (quality) { - return _this2.config.quality.options.includes(quality); - }); - } - // Toggle the pane and tab - var toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1; - controls.toggleTab.call(this, type, toggle); + Array.from(this.elements.buttons.play || []).forEach(function (button) { + button.setAttribute('aria-label', label); + }); // Set iframe title + // https://github.com/sampotts/plyr/issues/124 - // Check if we need to toggle the parent - controls.checkMenu.call(this); + if (this.isEmbed) { + var iframe = getElement.call(this, 'iframe'); - // If we're hiding, nothing more to do - if (!toggle) { - return; - } + if (!is$1.element(iframe)) { + return; + } // Default to media type - // Empty the menu - utils.emptyElement(list); - // Get the badge HTML for HD, 4K etc - var getBadge = function getBadge(quality) { - var label = ''; + var title = !is$1.empty(this.config.title) ? this.config.title : 'video'; + var format = i18n.get('frameTitle', this.config); + iframe.setAttribute('title', format.replace('{title}', title)); + } + }, + // Toggle poster + togglePoster: function togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster: function setPoster(poster) { + var _this2 = this; - switch (quality) { - case 2160: - label = '4K'; - break; + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - case 1440: - case 1080: - case 720: - label = 'HD'; - break; + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); + } // Set property synchronously to respect the call order - case 576: - case 480: - label = 'SD'; - break; - default: - break; - } + this.media.setAttribute('poster', poster); // Wait until ui is ready - if (!label.length) { - return null; - } + return ready.call(this) // Load image + .then(function () { + return loadImage(poster); + }).catch(function (err) { + // Hide poster on error unless it's been set by another call + if (poster === _this2.poster) { + ui.togglePoster.call(_this2, false); + } // Rethrow - return controls.createBadge.call(_this2, label); - }; - // Sort options by the config and then render options - this.options.quality.sort(function (a, b) { - var sorting = _this2.config.quality.options; - return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; - }).forEach(function (quality) { - var label = controls.getLabel.call(_this2, 'quality', quality); - controls.createMenuItem.call(_this2, quality, list, type, label, getBadge(quality)); + throw err; + }).then(function () { + // Prevent race conditions + if (poster !== _this2.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }).then(function () { + Object.assign(_this2.elements.poster.style, { + backgroundImage: "url('".concat(poster, "')"), + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '' }); - - controls.updateSetting.call(this, type, list); + ui.togglePoster.call(_this2, true); + return poster; + }); }, + // Check playing state + checkPlaying: function checkPlaying(event) { + var _this3 = this; + // Class hooks + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state - // Translate a value into a nice label - // TODO: Localisation - getLabel: function getLabel(setting, value) { - switch (setting) { - case 'speed': - return value === 1 ? i18n.get('normal', this.config) : value + '×'; - - case 'quality': - if (utils.is.number(value)) { - return value + 'p'; - } + Array.from(this.elements.buttons.play || []).forEach(function (target) { + target.pressed = _this3.playing; + }); // Only update controls on non timeupdate events - return utils.toTitleCase(value); + if (is$1.event(event) && event.type === 'timeupdate') { + return; + } // Toggle controls - case 'captions': - return captions.getLabel.call(this); - default: - return null; - } + ui.toggleControls.call(this); }, + // Check if media is loading + checkLoading: function checkLoading(event) { + var _this4 = this; + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer - // Update the selected setting - updateSetting: function updateSetting(setting, container, input) { - var pane = this.elements.settings.panes[setting]; - var value = null; - var list = container; - - switch (setting) { - case 'captions': - if (this.captions.active) { - if (this.options.captions.length > 2 || !this.options.captions.some(function (lang) { - return lang === 'enabled'; - })) { - value = this.captions.language; - } else { - value = 'enabled'; - } - } else { - value = ''; - } + clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking - break; + this.timers.loading = setTimeout(function () { + // Update progress bar loading class state + toggleClass(_this4.elements.container, _this4.config.classNames.loading, _this4.loading); // Update controls visibility - default: - value = !utils.is.empty(input) ? input : this[setting]; + ui.toggleControls.call(_this4); + }, this.loading ? 250 : 0); + }, + // Toggle controls based on state and `force` argument + toggleControls: function toggleControls(force) { + var controls$$1 = this.elements.controls; - // Get default - if (utils.is.empty(value)) { - value = this.config[setting].default; - } + if (controls$$1 && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide - // Unsupported value - if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) { - this.debug.warn('Unsupported value of \'' + value + '\' for ' + setting); - return; - } + this.toggleControls(Boolean(force || this.loading || this.paused || controls$$1.pressed || controls$$1.hover || recentTouchSeek)); + } + } + }; - // Disabled value - if (!this.config[setting].options.includes(value)) { - this.debug.warn('Disabled value of \'' + value + '\' for ' + setting); - return; - } + /* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; + } */ + // Set aspect ratio for responsive container - break; - } + function setAspectRatio(input) { + var ratio = input; - // Get the list if we need to - if (!utils.is.element(list)) { - list = pane && pane.querySelector('ul'); - } + if (!is$1.string(ratio) && !is$1.nullOrUndefined(this.embed)) { + ratio = this.embed.ratio; + } - // If there's no list it means it's not been rendered... - if (!utils.is.element(list)) { - return; - } + if (!is$1.string(ratio)) { + ratio = this.config.ratio; + } - // Update the label - var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value); - label.innerHTML = controls.getLabel.call(this, setting, value); + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + x = _ratio$split$map2[0], + y = _ratio$split$map2[1]; - // Find the radio option and check it - var target = list && list.querySelector('input[value="' + value + '"]'); + var padding = 100 / x * y; + this.elements.wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI - if (utils.is.element(target)) { - target.checked = true; - } - }, + if (this.isVimeo && this.supported.ui) { + var height = 240; + var offset = (height - padding) / (height / 50); + this.media.style.transform = "translateY(-".concat(offset, "%)"); + } + return { + padding: padding, + ratio: ratio + }; + } - // Set the looping options - /* setLoopMenu() { - // Menu required - if (!utils.is.element(this.elements.settings.panes.loop)) { - return; - } - const options = ['start', 'end', 'all', 'reset']; - const list = this.elements.settings.panes.loop.querySelector('ul'); - // Show the pane and tab - utils.toggleHidden(this.elements.settings.tabs.loop, false); - utils.toggleHidden(this.elements.settings.panes.loop, false); - // Toggle the pane and tab - const toggle = !utils.is.empty(this.loop.options); - controls.toggleTab.call(this, 'loop', toggle); - // Empty the menu - utils.emptyElement(list); - options.forEach(option => { - const item = utils.createElement('li'); - const button = utils.createElement( - 'button', - utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), { - type: 'button', - class: this.config.classNames.control, - 'data-plyr-loop-action': option, - }), - i18n.get(option, this.config) - ); - if (['start', 'end'].includes(option)) { - const badge = controls.createBadge.call(this, '00:00'); - button.appendChild(badge); - } - item.appendChild(button); - list.appendChild(item); - }); - }, */ + var Listeners = + /*#__PURE__*/ + function () { + function Listeners(player) { + _classCallCheck(this, Listeners); - // Get current selected caption language - // TODO: rework this to user the getter in the API? + this.player = player; + this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; + this.handleKey = this.handleKey.bind(this); + this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); + this.firstTouch = this.firstTouch.bind(this); + } // Handle key presses - // Set a list of available captions languages - setCaptionsMenu: function setCaptionsMenu() { - var _this3 = this; - // TODO: Captions or language? Currently it's mixed - var type = 'captions'; - var list = this.elements.settings.panes.captions.querySelector('ul'); + _createClass(Listeners, [{ + key: "handleKey", + value: function handleKey(event) { + var player = this.player; + var elements = player.elements; + var code = event.keyCode ? event.keyCode : event.which; + var pressed = event.type === 'keydown'; + var repeat = pressed && code === this.lastKey; // Bail if a modifier key is set - // Toggle the pane and tab - var toggle = captions.getTracks.call(this).length; - controls.toggleTab.call(this, type, toggle); + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason - // Empty the menu - utils.emptyElement(list); - // Check if we need to toggle the parent - controls.checkMenu.call(this); + if (!is$1.number(code)) { + return; + } // Seek by the number keys - // If there's no captions, bail - if (!toggle) { - return; - } - // Re-map the tracks into just the data we need - var tracks = captions.getTracks.call(this).map(function (track) { - return { - language: !utils.is.empty(track.language) ? track.language : 'enabled', - label: captions.getLabel.call(_this3, track) - }; - }); + var seekByKey = function seekByKey() { + // Divide the max duration into 10th's and times by the number value + player.currentTime = player.duration / 10 * (code - 48); + }; // Handle the key on keydown + // Reset on keyup - // Add the "Disabled" option to turn off captions - tracks.unshift({ - language: '', - label: i18n.get('disabled', this.config) - }); - // Generate options - tracks.forEach(function (track) { - controls.createMenuItem.call(_this3, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this3, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this3.captions.language.toLowerCase()); - }); + if (pressed) { + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + var focused = document.activeElement; - // Store reference - this.options.captions = tracks.map(function (track) { - return track.language; - }); + if (is$1.element(focused)) { + var editable = player.config.selectors.editable; + var seek = elements.inputs.seek; - controls.updateSetting.call(this, type, list); - }, + if (focused !== seek && matches(focused, editable)) { + return; + } + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } + } // Which keycodes should we prevent default - // Set a list of available captions languages - setSpeedMenu: function setSpeedMenu(options) { - var _this4 = this; - // Do nothing if not selected - if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) { - return; - } + var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows) - // Menu required - if (!utils.is.element(this.elements.settings.panes.speed)) { - return; - } + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } - var type = 'speed'; + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + player.togglePlay(); + } + + break; + + case 38: + // Arrow up + player.increaseVolume(0.1); + break; + + case 40: + // Arrow down + player.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + player.muted = !player.muted; + } + + break; + + case 39: + // Arrow forward + player.forward(); + break; + + case 37: + // Arrow back + player.rewind(); + break; + + case 70: + // F key + player.fullscreen.toggle(); + break; + + case 67: + // C key + if (!repeat) { + player.toggleCaptions(); + } + + break; + + case 76: + // L key + player.loop = !player.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ - // Set the speed options - if (utils.is.array(options)) { - this.options.speed = options; - } else if (this.isHTML5 || this.isVimeo) { - this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; - } + default: + break; + } // Escape is handle natively when in full screen + // So we only need to worry about non native - // Set options if passed and filter based on config - this.options.speed = this.options.speed.filter(function (speed) { - return _this4.config.speed.options.includes(speed); - }); - // Toggle the pane and tab - var toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1; - controls.toggleTab.call(this, type, toggle); + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); + } // Store last code for next cycle - // Check if we need to toggle the parent - controls.checkMenu.call(this); - // If we're hiding, nothing more to do - if (!toggle) { - return; + this.lastKey = code; + } else { + this.lastKey = null; } + } // Toggle menu - // Get the list to populate - var list = this.elements.settings.panes.speed.querySelector('ul'); - - // Empty the menu - utils.emptyElement(list); - - // Create items - this.options.speed.forEach(function (speed) { - var label = controls.getLabel.call(_this4, 'speed', speed); - controls.createMenuItem.call(_this4, speed, list, type, label); - }); - - controls.updateSetting.call(this, type, list); - }, - - - // Check if we need to hide/show the settings menu - checkMenu: function checkMenu() { - var tabs = this.elements.settings.tabs; - - var visible = !utils.is.empty(tabs) && Object.values(tabs).some(function (tab) { - return !tab.hidden; - }); - - utils.toggleHidden(this.elements.settings.menu, !visible); - }, + }, { + key: "toggleMenu", + value: function toggleMenu(event) { + controls.toggleMenu.call(this.player, event); + } // Device is touch enabled + }, { + key: "firstTouch", + value: function firstTouch() { + var player = this.player; + var elements = player.elements; + player.touch = true; // Add touch class - // Show/hide menu - toggleMenu: function toggleMenu(event) { - var form = this.elements.settings.form; + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + }, { + key: "setTabFocus", + value: function setTabFocus(event) { + var player = this.player; + var elements = player.elements; + clearTimeout(this.focusTimer); // Ignore any key other than tab - var button = this.elements.buttons.settings; + if (event.type === 'keydown' && event.which !== 9) { + return; + } // Store reference to event timeStamp - // Menu and button are required - if (!utils.is.element(form) || !utils.is.element(button)) { - return; - } - var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden'); + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } // Remove current classes - if (utils.is.event(event)) { - var isMenuItem = utils.is.element(form) && form.contains(event.target); - var isButton = event.target === this.elements.buttons.settings; - // If the click was inside the form or if the click - // wasn't the button or menu item and we're trying to - // show the menu (a doc click shouldn't show the menu) - if (isMenuItem || !isMenuItem && !isButton && show) { - return; - } + var removeCurrent = function removeCurrent() { + var className = player.config.classNames.tabFocus; + var current = getElements.call(player, ".".concat(className)); + toggleClass(current, className, false); + }; // Determine if a key was pressed to trigger this event - // Prevent the toggle being caught by the doc listener - if (isButton) { - event.stopPropagation(); - } - } - // Set form and button attributes - if (utils.is.element(button)) { - button.setAttribute('aria-expanded', show); - } + var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior - if (utils.is.element(form)) { - utils.toggleHidden(form, !show); - utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); + if (event.type === 'focus' && !wasKeyDown) { + return; + } // Remove all current - if (show) { - form.removeAttribute('tabindex'); - } else { - form.setAttribute('tabindex', -1); - } - } - }, + removeCurrent(); // Delay the adding of classname until the focus has changed + // This event fires before the focusin event - // Get the natural size of a tab - getTabSize: function getTabSize(tab) { - var clone = tab.cloneNode(true); - clone.style.position = 'absolute'; - clone.style.opacity = 0; - clone.removeAttribute('hidden'); + this.focusTimer = setTimeout(function () { + var focused = document.activeElement; // Ignore if current focus element isn't inside the player - // Prevent input's being unchecked due to the name being identical - Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) { - var name = input.getAttribute('name'); - input.setAttribute('name', name + '-clone'); - }); + if (!elements.container.contains(focused)) { + return; + } - // Append to parent so we get the "real" size - tab.parentNode.appendChild(clone); + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); + } // Global window & document listeners - // Get the sizes before we remove - var width = clone.scrollWidth; - var height = clone.scrollHeight; + }, { + key: "global", + value: function global() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var player = this.player; // Keyboard shortcuts - // Remove from the DOM - utils.removeElement(clone); + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); + } // Click anywhere closes menu - return { - width: width, - height: height - }; - }, + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events - // Toggle Menu - showTab: function showTab() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - var menu = this.elements.settings.menu; + once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection - var pane = document.getElementById(target); + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); + } // Container listeners - // Nothing to show, bail - if (!utils.is.element(pane)) { - return; - } + }, { + key: "container", + value: function container() { + var player = this.player; + var config = player.config, + elements = player.elements, + timers = player.timers; // Keyboard shortcuts - // Are we targetting a tab? If not, bail - var isTab = pane.getAttribute('role') === 'tabpanel'; - if (!isTab) { - return; - } + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); + } // Toggle controls on mouse events and entering fullscreen - // Hide all other tabs - // Get other tabs - var current = menu.querySelector('[role="tabpanel"]:not([hidden])'); - var container = current.parentNode; - // Set other toggles to be expanded false - Array.from(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]')).forEach(function (toggle) { - toggle.setAttribute('aria-expanded', false); - }); + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen - // If we can do fancy animations, we'll animate the height/width - if (support.transitions && !support.reducedMotion) { - // Set the current width as a base - container.style.width = current.scrollWidth + 'px'; - container.style.height = current.scrollHeight + 'px'; + if (controls$$1 && event.type === 'enterfullscreen') { + controls$$1.pressed = false; + controls$$1.hover = false; + } // Show, then hide after a timeout unless another control event occurs - // Get potential sizes - var size = controls.getTabSize.call(this, pane); - // Restore auto height/width - var restore = function restore(e) { - // We're only bothered about height and width on the container - if (e.target !== container || !['width', 'height'].includes(e.propertyName)) { - return; - } + var show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + var delay = 0; - // Revert back to auto - container.style.width = ''; - container.style.height = ''; + if (show) { + ui.toggleControls.call(player, true); // Use longer timeout for touch devices - // Only listen once - utils.off(container, utils.transitionEndEvent, restore); - }; + delay = player.touch ? 3000 : 2000; + } // Clear timer - // Listen for the transition finishing and restore auto height/width - utils.on(container, utils.transitionEndEvent, restore); - // Set dimensions to target - container.style.width = size.width + 'px'; - container.style.height = size.height + 'px'; - } + clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking - // Set attributes on current tab - utils.toggleHidden(current, true); - current.setAttribute('tabindex', -1); + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen - // Set attributes on target - utils.toggleHidden(pane, false); + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); + }); + } */ + // Set a gutter for Vimeo - var tabs = utils.getElements.call(this, '[aria-controls="' + target + '"]'); - Array.from(tabs).forEach(function (tab) { - tab.setAttribute('aria-expanded', true); - }); - pane.removeAttribute('tabindex'); + var setGutter = function setGutter(ratio, padding, toggle) { + if (!player.isVimeo) { + return; + } - // Focus the first item - pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus(); - }, + var target = player.elements.wrapper.firstChild; + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + height = _ratio$split$map2[1]; - // Build the default HTML - // TODO: Set order based on order in the config.controls array? - create: function create(data) { - var _this5 = this; + var _player$embed$ratio$s = player.embed.ratio.split(':').map(Number), + _player$embed$ratio$s2 = _slicedToArray(_player$embed$ratio$s, 2), + videoWidth = _player$embed$ratio$s2[0], + videoHeight = _player$embed$ratio$s2[1]; - // Do nothing if we want no controls - if (utils.is.empty(this.config.controls)) { - return null; - } + target.style.maxWidth = toggle ? "".concat(height / videoHeight * videoWidth, "px") : null; + target.style.margin = toggle ? '0 auto' : null; + }; // Resize on fullscreen change - // Create the container - var container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper)); - // Restart button - if (this.config.controls.includes('restart')) { - container.appendChild(controls.createButton.call(this, 'restart')); - } + var setPlayerSize = function setPlayerSize(measure) { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } - // Rewind button - if (this.config.controls.includes('rewind')) { - container.appendChild(controls.createButton.call(this, 'rewind')); - } + var rect = elements.container.getBoundingClientRect(); + var width = rect.width, + height = rect.height; + return setAspectRatio.call(player, "".concat(width, ":").concat(height)); + }; - // Play/Pause button - if (this.config.controls.includes('play')) { - container.appendChild(controls.createButton.call(this, 'play')); - } + var resized = function resized() { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; - // Fast forward button - if (this.config.controls.includes('fast-forward')) { - container.appendChild(controls.createButton.call(this, 'fast-forward')); - } + on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) { + var _player$fullscreen = player.fullscreen, + target = _player$fullscreen.target, + usingNative = _player$fullscreen.usingNative; // Ignore for iOS native - // Progress - if (this.config.controls.includes('progress')) { - var progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress)); + if (!player.isEmbed || target !== elements.container) { + return; + } - // Seek range slider - var seek = controls.createRange.call(this, 'seek', { - id: 'plyr-seek-' + data.id - }); - progress.appendChild(seek.label); - progress.appendChild(seek.input); + var isEnter = event.type === 'enterfullscreen'; // Set the player size when entering fullscreen to viewport size - // Buffer progress - progress.appendChild(controls.createProgress.call(this, 'buffer')); + var _setPlayerSize = setPlayerSize(isEnter), + padding = _setPlayerSize.padding, + ratio = _setPlayerSize.ratio; // Set Vimeo gutter - // TODO: Add loop display indicator - // Seek tooltip - if (this.config.tooltips.seek) { - var tooltip = utils.createElement('span', { - role: 'tooltip', - class: this.config.classNames.tooltip - }, '00:00'); + setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport - progress.appendChild(tooltip); - this.elements.display.seekTooltip = tooltip; + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); } + } + }); + } // Listen for media events - this.elements.progress = progress; - container.appendChild(this.elements.progress); - } - - // Media current time display - if (this.config.controls.includes('current-time')) { - container.appendChild(controls.createTime.call(this, 'currentTime')); - } - - // Media duration display - if (this.config.controls.includes('duration')) { - container.appendChild(controls.createTime.call(this, 'duration')); - } + }, { + key: "media", + value: function media() { + var _this = this; - // Toggle mute button - if (this.config.controls.includes('mute')) { - container.appendChild(controls.createButton.call(this, 'mute')); - } + var player = this.player; + var elements = player.elements; // Time change on media - // Volume range control - if (this.config.controls.includes('volume')) { - var volume = utils.createElement('div', { - class: 'plyr__volume' - }); + on.call(player, player.media, 'timeupdate seeking seeked', function (event) { + return controls.timeUpdate.call(player, event); + }); // Display duration - // Set the attributes - var attributes = { - max: 1, - step: 0.05, - value: this.config.volume - }; + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) { + return controls.durationUpdate.call(player, event); + }); // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point - // Create the volume range slider - var range = controls.createRange.call(this, 'volume', utils.extend(attributes, { - id: 'plyr-volume-' + data.id - })); - volume.appendChild(range.label); - volume.appendChild(range.input); + on.call(player, player.media, 'canplay loadeddata', function () { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); + }); // Handle the media finishing - this.elements.volume = volume; + on.call(player, player.media, 'ended', function () { + // Show poster on end + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { + // Restart + player.restart(); + } + }); // Check for buffer progress - container.appendChild(volume); - } + on.call(player, player.media, 'progress playing seeking seeked', function (event) { + return controls.updateProgress.call(player, event); + }); // Handle volume changes - // Toggle captions button - if (this.config.controls.includes('captions')) { - container.appendChild(controls.createButton.call(this, 'captions')); - } + on.call(player, player.media, 'volumechange', function (event) { + return controls.updateVolume.call(player, event); + }); // Handle play/pause - // Settings button / menu - if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { - var menu = utils.createElement('div', { - class: 'plyr__menu', - hidden: '' - }); + on.call(player, player.media, 'playing play pause ended emptied timeupdate', function (event) { + return ui.checkPlaying.call(player, event); + }); // Loading state - menu.appendChild(controls.createButton.call(this, 'settings', { - id: 'plyr-settings-toggle-' + data.id, - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id, - 'aria-expanded': false - })); - - var form = utils.createElement('form', { - class: 'plyr__menu__container', - id: 'plyr-settings-' + data.id, - hidden: '', - 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, - role: 'tablist', - tabindex: -1 - }); + on.call(player, player.media, 'waiting canplay seeked playing', function (event) { + return ui.checkLoading.call(player, event); + }); // If autoplay, then load advertisement if required + // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows - var inner = utils.createElement('div'); + on.call(player, player.media, 'playing', function () { + if (!player.ads) { + return; + } // If ads are enabled, wait for them first - var home = utils.createElement('div', { - id: 'plyr-settings-' + data.id + '-home', - 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, - role: 'tabpanel' - }); - // Create the tab list - var tabs = utils.createElement('ul', { - role: 'tablist' + if (player.ads.enabled && !player.ads.initialized) { + // Wait for manager response + player.ads.managerPromise.then(function () { + return player.ads.play(); + }).catch(function () { + return player.play(); }); + } + }); // Click video - // Build the tabs - this.config.settings.forEach(function (type) { - var tab = utils.createElement('li', { - role: 'tab', - hidden: '' - }); + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { + // Re-fetch the wrapper + var wrapper = getElement.call(player, ".".concat(player.config.classNames.video)); // Bail if there's no wrapper (this should never happen) - var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this5.config.selectors.buttons.settings), { - type: 'button', - class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--forward', - id: 'plyr-settings-' + data.id + '-' + type + '-tab', - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id + '-' + type, - 'aria-expanded': false - }), i18n.get(type, _this5.config)); - - var value = utils.createElement('span', { - class: _this5.config.classNames.menu.value - }); + if (!is$1.element(wrapper)) { + return; + } // On click play, pause or restart - // Speed contains HTML entities - value.innerHTML = data[type]; - button.appendChild(value); - tab.appendChild(button); - tabs.appendChild(tab); + on.call(player, elements.container, 'click', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper - _this5.elements.settings.tabs[type] = tab; - }); + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } // Touch devices will just show controls (if hidden) - home.appendChild(tabs); - inner.appendChild(home); - - // Build the panes - this.config.settings.forEach(function (type) { - var pane = utils.createElement('div', { - id: 'plyr-settings-' + data.id + '-' + type, - hidden: '', - 'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab', - role: 'tabpanel', - tabindex: -1 - }); - var back = utils.createElement('button', { - type: 'button', - class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--back', - 'aria-haspopup': true, - 'aria-controls': 'plyr-settings-' + data.id + '-home', - 'aria-expanded': false - }, i18n.get(type, _this5.config)); + if (player.touch && player.config.hideControls) { + return; + } - pane.appendChild(back); + if (player.ended) { + _this.proxy(event, player.restart, 'restart'); - var options = utils.createElement('ul'); + _this.proxy(event, player.play, 'play'); + } else { + _this.proxy(event, player.togglePlay, 'play'); + } + }); + } // Disable right click - pane.appendChild(options); - inner.appendChild(pane); - _this5.elements.settings.panes[type] = pane; - }); + if (player.supported.ui && player.config.disableContextMenu) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { + event.preventDefault(); + }, false); + } // Volume change - form.appendChild(inner); - menu.appendChild(form); - container.appendChild(menu); - this.elements.settings.form = form; - this.elements.settings.menu = menu; - } + on.call(player, player.media, 'volumechange', function () { + // Save to storage + player.storage.set({ + volume: player.volume, + muted: player.muted + }); + }); // Speed change - // Picture in picture button - if (this.config.controls.includes('pip') && support.pip) { - container.appendChild(controls.createButton.call(this, 'pip')); - } + on.call(player, player.media, 'ratechange', function () { + // Update UI + controls.updateSetting.call(player, 'speed'); // Save to storage - // Airplay button - if (this.config.controls.includes('airplay') && support.airplay) { - container.appendChild(controls.createButton.call(this, 'airplay')); - } - // Toggle fullscreen button - if (this.config.controls.includes('fullscreen')) { - container.appendChild(controls.createButton.call(this, 'fullscreen')); - } + player.storage.set({ + speed: player.speed + }); + }); // Quality change - // Larger overlaid play button - if (this.config.controls.includes('play-large')) { - this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); - } + on.call(player, player.media, 'qualitychange', function (event) { + // Update UI + controls.updateSetting.call(player, 'quality', null, event.detail.quality); + }); // Update download link when ready and if quality changes - this.elements.controls = container; + on.call(player, player.media, 'ready qualitychange', function () { + controls.setDownloadLink.call(player); + }); // Proxy events to container + // Bubble up key events for Edge - if (this.isHTML5) { - controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); - } + var proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + on.call(player, player.media, proxyEvents, function (event) { + var _event$detail = event.detail, + detail = _event$detail === void 0 ? {} : _event$detail; // Get error details from media - controls.setSpeedMenu.call(this); + if (event.type === 'error') { + detail = player.media.error; + } - return container; - }, + triggerEvent.call(player, elements.container, event.type, true, detail); + }); + } // Run default and custom handlers + }, { + key: "proxy", + value: function proxy(event, defaultHandler, customHandlerKey) { + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is$1.function(customHandler); + var returned = true; // Execute custom handler - // Insert controls - inject: function inject() { - var _this6 = this; + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } // Only call default handler if not prevented in custom handler - // Sprite - if (this.config.loadSprite) { - var icon = controls.getIconUrl.call(this); - // Only load external sprite using AJAX - if (icon.cors) { - utils.loadSprite(icon.url, 'sprite-plyr'); - } + if (returned && is$1.function(defaultHandler)) { + defaultHandler.call(player, event); } + } // Trigger custom and default handlers - // Create a unique ID - this.id = Math.floor(Math.random() * 10000); - - // Null by default - var container = null; - this.elements.controls = null; - - // Set template properties - var props = { - id: this.id, - seektime: this.config.seekTime, - title: this.config.title - }; - var update = true; - - if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { - // String or HTMLElement passed as the option - container = this.config.controls; - } else if (utils.is.function(this.config.controls)) { - // A custom function to build controls - // The function can return a HTMLElement or String - container = this.config.controls.call(this, props); - } else { - // Create controls - container = controls.create.call(this, { - id: this.id, - seektime: this.config.seekTime, - speed: this.speed, - quality: this.quality, - captions: captions.getLabel.call(this) - // TODO: Looping - // loop: 'None', - }); - update = false; - } + }, { + key: "bind", + value: function bind(element, type, defaultHandler, customHandlerKey) { + var _this2 = this; - // Replace props with their value - var replace = function replace(input) { - var result = input; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is$1.function(customHandler); + on.call(player, element, type, function (event) { + return _this2.proxy(event, defaultHandler, customHandlerKey); + }, passive && !hasCustomHandler); + } // Listen for control events - Object.entries(props).forEach(function (_ref) { - var _ref2 = slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + }, { + key: "controls", + value: function controls$$1() { + var _this3 = this; - result = utils.replaceAll(result, '{' + key + '}', value); - }); + var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change - return result; - }; + var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle - // Update markup - if (update) { - if (utils.is.string(this.config.controls)) { - container = replace(container); - } else if (utils.is.element(container)) { - container.innerHTML = replace(container.innerHTML); - } - } + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { + _this3.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause - // Controls container - var target = void 0; - // Inject to custom location - if (utils.is.string(this.config.selectors.controls.container)) { - target = document.querySelector(this.config.selectors.controls.container); - } + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind - // Inject into the container by default - if (!utils.is.element(target)) { - target = this.elements.container; - } + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind - // Inject controls HTML - if (utils.is.element(container)) { - target.appendChild(container); - } else if (container) { - target.insertAdjacentHTML('beforeend', container); - } + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle - // Find the elements if need be - if (!utils.is.element(this.elements.controls)) { - controls.findElements.call(this); - } + this.bind(elements.buttons.mute, 'click', function () { + player.muted = !player.muted; + }, 'mute'); // Captions toggle - // Edge sometimes doesn't finish the paint so force a redraw - if (window.navigator.userAgent.includes('Edge')) { - utils.repaint(target); - } + this.bind(elements.buttons.captions, 'click', function () { + return player.toggleCaptions(); + }); // Download - // Setup tooltips - if (this.config.tooltips.controls) { - var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join('')); + this.bind(elements.buttons.download, 'click', function () { + triggerEvent.call(player, player.media, 'download'); + }, 'download'); // Fullscreen toggle - Array.from(labels).forEach(function (label) { - utils.toggleClass(label, _this6.config.classNames.hidden, false); - utils.toggleClass(label, _this6.config.classNames.tooltip, true); - label.setAttribute('role', 'tooltip'); - }); - } - } -}; + this.bind(elements.buttons.fullscreen, 'click', function () { + player.fullscreen.toggle(); + }, 'fullscreen'); // Picture-in-Picture -// ========================================================================== + this.bind(elements.buttons.pip, 'click', function () { + player.pip = 'toggle'; + }, 'pip'); // Airplay -var captions = { - // Setup captions - setup: function setup() { - // Requires UI support - if (!this.supported.ui) { - return; - } + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle - // Set default language if not set - var stored = this.storage.get('language'); + this.bind(elements.buttons.settings, 'click', function (event) { + // Prevent the document click listener closing the menu + event.stopPropagation(); - if (!utils.is.empty(stored)) { - this.captions.language = stored; - } + controls.toggleMenu.call(player, event); + }); // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 - if (utils.is.empty(this.captions.language)) { - this.captions.language = this.config.captions.language.toLowerCase(); - } + this.bind(elements.buttons.settings, 'keyup', function (event) { + var code = event.which; // We only care about space and return - // Set captions enabled state if not set - if (!utils.is.boolean(this.captions.active)) { - var active = this.storage.get('captions'); + if (![13, 32].includes(code)) { + return; + } // Because return triggers a click anyway, all we need to do is set focus - if (utils.is.boolean(active)) { - this.captions.active = active; - } else { - this.captions.active = this.config.captions.active; - } - } - // Only Vimeo and HTML5 video supported at this point - if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { - // Clear menu and hide - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { - controls.setCaptionsMenu.call(this); - } + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); return; - } + } // Prevent scroll - // Inject the container - if (!utils.is.element(this.elements.captions)) { - this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions)); - utils.insertAfter(this.elements.captions, this.elements.wrapper); - } + event.preventDefault(); // Prevent playing video (Firefox) - // Set the class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); + event.stopPropagation(); // Toggle menu - // Get tracks - var tracks = captions.getTracks.call(this); + controls.toggleMenu.call(player, event); + }, null, false // Can't be passive as we're preventing default + ); // Escape closes menu - // If no caption file exists, hide container for caption text - if (utils.is.empty(tracks)) { - return; - } + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); // Set range input alternative "value", which matches the tooltip time (#954) - // Get browser info - var browser = utils.getBrowser(); + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); + var percent = 100 / rect.width * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); // Pause while seeking - // Fix IE captions if CORS is used - // Fetch captions and inject as blobs instead (data URIs not supported!) - if (browser.isIE && window.URL) { - var elements = this.media.querySelectorAll('track'); + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var attribute = 'play-on-seeked'; - Array.from(elements).forEach(function (track) { - var src = track.getAttribute('src'); - var href = utils.parseUrl(src); + if (is$1.keyboardEvent(event) && code !== 39 && code !== 37) { + return; + } // Record seek time so we can prevent hiding controls for a few seconds after seek - if (href.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(href.protocol)) { - utils.fetch(src, 'blob').then(function (blob) { - track.setAttribute('src', window.URL.createObjectURL(blob)); - }).catch(function () { - utils.removeElement(track); - }); - } - }); - } - // Set language - captions.setLanguage.call(this); + player.lastSeekTime = Date.now(); // Was playing before? - // Enable UI - captions.show.call(this); + var play = seek.hasAttribute(attribute); // Done seeking - // Set available languages in list - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { - controls.setCaptionsMenu.call(this); - } - }, + var done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); + } + }); // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + + if (browser.isIos) { + var inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(function (input) { + return _this3.bind(input, inputEvent, function (event) { + return repaint(event.target); + }); + }); + } // Seek - // Set the captions language - setLanguage: function setLanguage() { - var _this = this; - // Setup HTML5 track rendering - if (this.isHTML5 && this.isVideo) { - captions.getTracks.call(this).forEach(function (track) { - // Show track - utils.on(track, 'cuechange', function (event) { - return captions.setCue.call(_this, event); - }); + this.bind(elements.inputs.seek, inputEvent, function (event) { + var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) - // Turn off native caption rendering to avoid double captions - // eslint-disable-next-line - track.mode = 'hidden'; - }); + var seekTo = seek.getAttribute('seek-value'); - // Get current track - var currentTrack = captions.getCurrentTrack.call(this); + if (is$1.empty(seekTo)) { + seekTo = seek.value; + } - // Check if suported kind - if (utils.is.track(currentTrack)) { - // If we change the active track while a cue is already displayed we need to update it - if (Array.from(currentTrack.activeCues || []).length) { - captions.setCue.call(this, currentTrack); - } - } - } else if (this.isVimeo && this.captions.active) { - this.embed.enableTextTrack(this.language); - } - }, + seek.removeAttribute('seek-value'); + player.currentTime = seekTo / seek.max * player.duration; + }, 'seek'); // Seek tooltip + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this - // Get the tracks - getTracks: function getTracks() { - // Return empty array at least - if (utils.is.nullOrUndefined(this.media)) { - return []; - } + this.bind(elements.progress, 'mousemove touchmove', function (event) { + var previewThumbnails = player.previewThumbnails; - // Only get accepted kinds - return Array.from(this.media.textTracks || []).filter(function (track) { - return ['captions', 'subtitles'].includes(track.kind); - }); - }, + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + this.bind(elements.progress, 'mouseleave click', function () { + var previewThumbnails = player.previewThumbnails; - // Get the current track for the current language - getCurrentTrack: function getCurrentTrack() { - var _this2 = this; - - var tracks = captions.getTracks.call(this); + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); // Show scrubbing preview - if (!tracks.length) { - return null; - } + this.bind(elements.progress, 'mousedown touchstart', function (event) { + var previewThumbnails = player.previewThumbnails; - // Get track based on current language - var track = tracks.find(function (track) { - return track.language.toLowerCase() === _this2.language; + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } }); + this.bind(elements.progress, 'mouseup touchend', function (event) { + var previewThumbnails = player.previewThumbnails; - // Get the <track> with default attribute - if (!track) { - track = utils.getElement.call(this, 'track[default]'); - } - - // Get the first track - if (!track) { - var _tracks = slicedToArray(tracks, 1); + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); // Polyfill for lower fill in <input type="range"> for webkit - track = _tracks[0]; - } + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this3.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); + }); + }); + } // Current time invert + // Only if one time element is used for both currentTime and duration - return track; - }, + if (player.config.toggleInvert && !is$1.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { + // Do nothing if we're at the start + if (player.currentTime === 0) { + return; + } - // Get UI label for track - getLabel: function getLabel(track) { - var currentTrack = track; + player.config.invertTime = !player.config.invertTime; - if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) { - currentTrack = captions.getCurrentTrack.call(this); - } + controls.timeUpdate.call(player); + }); + } // Volume - if (utils.is.track(currentTrack)) { - if (!utils.is.empty(currentTrack.label)) { - return currentTrack.label; - } - if (!utils.is.empty(currentTrack.language)) { - return track.language.toUpperCase(); - } + this.bind(elements.inputs.volume, inputEvent, function (event) { + player.volume = event.target.value; + }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) - return i18n.get('enabled', this.config); - } + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) - return i18n.get('disabled', this.config); - }, + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); // Show controls when they receive focus (e.g., when using keyboard tab key) + this.bind(elements.controls, 'focusin', function () { + var config = player.config, + elements = player.elements, + timers = player.timers; // Skip transition to prevent focus from scrolling the parent element - // Display active caption if it contains text - setCue: function setCue(input) { - // Get the track from the event if needed - var track = utils.is.event(input) ? input.target : input; - var activeCues = track.activeCues; + toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle - var active = activeCues.length && activeCues[0]; - var currentTrack = captions.getCurrentTrack.call(this); + ui.toggleControls.call(player, true); // Restore transition - // Only display current track - if (track !== currentTrack) { - return; - } + setTimeout(function () { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); // Delay a little more for mouse users - // Display a cue, if there is one - if (utils.is.cue(active)) { - captions.setText.call(this, active.getCueAsHTML()); - } else { - captions.setText.call(this, null); - } + var delay = _this3.touch ? 3000 : 4000; // Clear timer - utils.dispatchEvent.call(this, this.media, 'cuechange'); - }, + clearTimeout(timers.controls); // Hide again after delay + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Mouse wheel for volume - // Set the current caption - setText: function setText(input) { - // Requires UI - if (!this.supported.ui) { - return; - } + this.bind(elements.inputs.volume, 'wheel', function (event) { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + var inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true - if (utils.is.element(this.elements.captions)) { - var content = utils.createElement('span'); + var _map = [event.deltaX, -event.deltaY].map(function (value) { + return inverted ? -value : value; + }), + _map2 = _slicedToArray(_map, 2), + x = _map2[0], + y = _map2[1]; // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) - // Empty the container - utils.emptyElement(this.elements.captions); - // Default to empty - var caption = !utils.is.nullOrUndefined(input) ? input : ''; + var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2% - // Set the span content - if (utils.is.string(caption)) { - content.textContent = caption.trim(); - } else { - content.appendChild(caption); - } + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min - // Set new caption text - this.elements.captions.appendChild(content); - } else { - this.debug.warn('No captions element to render to'); - } - }, + var volume = player.media.volume; + if (direction === 1 && volume < 1 || direction === -1 && volume > 0) { + event.preventDefault(); + } + }, 'volume', false); + } + }]); - // Display captions container and button (for initialization) - show: function show() { - // Try to load the value from storage - var active = this.storage.get('captions'); + return Listeners; + }(); - // Otherwise fall back to the default config - if (!utils.is.boolean(active)) { - active = this.config.captions.active; - } else { - this.captions.active = active; - } + var dP$3 = _objectDp.f; + var FProto = Function.prototype; + var nameRE = /^\s*function ([^ (]*)/; + var NAME$1 = 'name'; - if (active) { - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true); - utils.toggleState(this.elements.buttons.captions, true); - } + // 19.2.4.2 name + NAME$1 in FProto || _descriptors && dP$3(FProto, NAME$1, { + configurable: true, + get: function () { + try { + return ('' + this).match(nameRE)[1]; + } catch (e) { + return ''; + } } -}; + }); -// ========================================================================== -// Console wrapper -// ========================================================================== + // @@match logic + _fixReWks('match', 1, function (defined, MATCH, $match, maybeCallNative) { + return [ + // `String.prototype.match` method + // https://tc39.github.io/ecma262/#sec-string.prototype.match + function match(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[MATCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); + }, + // `RegExp.prototype[@@match]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match + function (regexp) { + var res = maybeCallNative($match, regexp, this); + if (res.done) return res.value; + var rx = _anObject(regexp); + var S = String(this); + if (!rx.global) return _regexpExecAbstract(rx, S); + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + var A = []; + var n = 0; + var result; + while ((result = _regexpExecAbstract(rx, S)) !== null) { + var matchStr = String(result[0]); + A[n] = matchStr; + if (matchStr === '') rx.lastIndex = _advanceStringIndex(S, _toLength(rx.lastIndex), fullUnicode); + n++; + } + return n === 0 ? null : A; + } + ]; + }); -var noop = function noop() {}; + var loadjs_umd = createCommonjsModule(function (module, exports) { + (function(root, factory) { + { + module.exports = factory(); + } + }(commonjsGlobal, function() { + /** + * Global dependencies. + * @global {Object} document - DOM + */ + + var devnull = function() {}, + bundleIdCache = {}, + bundleResultCache = {}, + bundleCallbackQueue = {}; + + + /** + * Subscribe to bundle load event. + * @param {string[]} bundleIds - Bundle ids + * @param {Function} callbackFn - The callback function + */ + function subscribe(bundleIds, callbackFn) { + // listify + bundleIds = bundleIds.push ? bundleIds : [bundleIds]; + + var depsNotFound = [], + i = bundleIds.length, + numWaiting = i, + fn, + bundleId, + r, + q; + + // define callback function + fn = function (bundleId, pathsNotFound) { + if (pathsNotFound.length) depsNotFound.push(bundleId); + + numWaiting--; + if (!numWaiting) callbackFn(depsNotFound); + }; -var Console = function () { - function Console() { - var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - classCallCheck(this, Console); + // register callback + while (i--) { + bundleId = bundleIds[i]; - this.enabled = window.console && enabled; + // execute callback if in result cache + r = bundleResultCache[bundleId]; + if (r) { + fn(bundleId, r); + continue; + } - if (this.enabled) { - this.log('Debugging enabled'); - } + // add to callback queue + q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; + q.push(fn); } + } - createClass(Console, [{ - key: 'log', - get: function get() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; - } - }, { - key: 'warn', - get: function get() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; - } - }, { - key: 'error', - get: function get() { - // eslint-disable-next-line no-console - return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; - } - }]); - return Console; -}(); - -// ========================================================================== -// Plyr default config -// ========================================================================== -var defaults$1 = { - // Disable - enabled: true, - - // Custom media title - title: '', + /** + * Publish bundle load event. + * @param {string} bundleId - Bundle id + * @param {string[]} pathsNotFound - List of files not found + */ + function publish(bundleId, pathsNotFound) { + // exit if id isn't defined + if (!bundleId) return; - // Logging to console - debug: false, + var q = bundleCallbackQueue[bundleId]; - // Auto play (if supported) - autoplay: false, + // cache result + bundleResultCache[bundleId] = pathsNotFound; - // Only allow one media playing at once (vimeo only) - autopause: true, + // exit if queue is empty + if (!q) return; - // Default time to skip when rewind/fast forward - seekTime: 10, + // empty callback queue + while (q.length) { + q[0](bundleId, pathsNotFound); + q.splice(0, 1); + } + } - // Default volume - volume: 1, - muted: false, - // Pass a custom duration - duration: null, + /** + * Execute callbacks. + * @param {Object or Function} args - The callback args + * @param {string[]} depsNotFound - List of dependencies not found + */ + function executeCallbacks(args, depsNotFound) { + // accept function as argument + if (args.call) args = {success: args}; - // Display the media duration on load in the current time position - // If you have opted to display both duration and currentTime, this is ignored - displayDuration: true, + // success and error callbacks + if (depsNotFound.length) (args.error || devnull)(depsNotFound); + else (args.success || devnull)(args); + } - // Invert the current time to be a countdown - invertTime: true, - // Clicking the currentTime inverts it's value to show time left rather than elapsed - toggleInvert: true, + /** + * Load individual file. + * @param {string} path - The file path + * @param {Function} callbackFn - The callback function + */ + function loadFile(path, callbackFn, args, numTries) { + var doc = document, + async = args.async, + maxTries = (args.numRetries || 0) + 1, + beforeCallbackFn = args.before || devnull, + pathStripped = path.replace(/^(css|img)!/, ''), + isCss, + e; + + numTries = numTries || 0; + + if (/(^css!|\.css$)/.test(path)) { + isCss = true; + + // css + e = doc.createElement('link'); + e.rel = 'stylesheet'; + e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix + } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { + // image + e = doc.createElement('img'); + e.src = pathStripped; + } else { + // javascript + e = doc.createElement('script'); + e.src = path; + e.async = async === undefined ? true : async; + } - // Aspect ratio (for embeds) - ratio: '16:9', + e.onload = e.onerror = e.onbeforeload = function (ev) { + var result = ev.type[0]; - // Click video container to play/pause - clickToPlay: true, + // Note: The following code isolates IE using `hideFocus` and treats empty + // stylesheets as failures to get around lack of onerror support + if (isCss && 'hideFocus' in e) { + try { + if (!e.sheet.cssText.length) result = 'e'; + } catch (x) { + // sheets objects created from load errors don't allow access to + // `cssText` (unless error is Code:18 SecurityError) + if (x.code != 18) result = 'e'; + } + } - // Auto hide the controls - hideControls: true, + // handle retries in case of load failure + if (result == 'e') { + // increment counter + numTries += 1; - // Reset to start when playback ended - resetOnEnd: false, + // exit function and try again + if (numTries < maxTries) { + return loadFile(path, callbackFn, args, numTries); + } + } - // Disable the standard context menu - disableContextMenu: true, + // execute callback + callbackFn(path, result, ev.defaultPrevented); + }; - // Sprite (for icons) - loadSprite: true, - iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg', + // add to document (unless callback returns `false`) + if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); + } - // Blank video (used to prevent errors on source change) - blankVideo: 'https://cdn.plyr.io/static/blank.mp4', - // Quality default - quality: { - default: 576, - options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default'] - }, + /** + * Load multiple files. + * @param {string[]} paths - The file paths + * @param {Function} callbackFn - The callback function + */ + function loadFiles(paths, callbackFn, args) { + // listify paths + paths = paths.push ? paths : [paths]; + + var numWaiting = paths.length, + x = numWaiting, + pathsNotFound = [], + fn, + i; + + // define callback function + fn = function(path, result, defaultPrevented) { + // handle error + if (result == 'e') pathsNotFound.push(path); + + // handle beforeload event. If defaultPrevented then that means the load + // will be blocked (ex. Ghostery/ABP on Safari) + if (result == 'b') { + if (defaultPrevented) pathsNotFound.push(path); + else return; + } - // Set loops - loop: { - active: false - // start: null, - // end: null, - }, + numWaiting--; + if (!numWaiting) callbackFn(pathsNotFound); + }; - // Speed default and options to display - speed: { - selected: 1, - options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] - }, + // load scripts + for (i=0; i < x; i++) loadFile(paths[i], fn, args); + } - // Keyboard shortcut settings - keyboard: { - focused: true, - global: false - }, - // Display tooltips - tooltips: { - controls: false, - seek: true - }, + /** + * Initiate script load and register bundle. + * @param {(string|string[])} paths - The file paths + * @param {(string|Function)} [arg1] - The bundleId or success callback + * @param {Function} [arg2] - The success or error callback + * @param {Function} [arg3] - The error callback + */ + function loadjs(paths, arg1, arg2) { + var bundleId, + args; - // Captions settings - captions: { - active: false, - language: (navigator.language || navigator.userLanguage).split('-')[0] - }, + // bundleId (if string) + if (arg1 && arg1.trim) bundleId = arg1; - // Fullscreen settings - fullscreen: { - enabled: true, // Allow fullscreen? - fallback: true, // Fallback for vintage browsers - iosNative: false // Use the native fullscreen in iOS (disables custom controls) - }, + // args (default is {}) + args = (bundleId ? arg2 : arg1) || {}; - // Local storage - storage: { - enabled: true, - key: 'plyr' - }, + // throw error if bundle is already defined + if (bundleId) { + if (bundleId in bundleIdCache) { + throw "LoadJS"; + } else { + bundleIdCache[bundleId] = true; + } + } - // Default controls - controls: ['play-large', - // 'restart', - // 'rewind', - 'play', - // 'fast-forward', - 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen'], - settings: ['captions', 'quality', 'speed'], + // load scripts + loadFiles(paths, function (pathsNotFound) { + // execute callbacks + executeCallbacks(args, pathsNotFound); - // Localisation - i18n: { - restart: 'Restart', - rewind: 'Rewind {seektime}s', - play: 'Play', - pause: 'Pause', - fastForward: 'Forward {seektime}s', - seek: 'Seek', - played: 'Played', - buffered: 'Buffered', - currentTime: 'Current time', - duration: 'Duration', - volume: 'Volume', - mute: 'Mute', - unmute: 'Unmute', - enableCaptions: 'Enable captions', - disableCaptions: 'Disable captions', - enterFullscreen: 'Enter fullscreen', - exitFullscreen: 'Exit fullscreen', - frameTitle: 'Player for {title}', - captions: 'Captions', - settings: 'Settings', - speed: 'Speed', - normal: 'Normal', - quality: 'Quality', - loop: 'Loop', - start: 'Start', - end: 'End', - all: 'All', - reset: 'Reset', - disabled: 'Disabled', - enabled: 'Enabled', - advertisement: 'Ad' - }, + // publish bundle load event + publish(bundleId, pathsNotFound); + }, args); + } - // URLs - urls: { - vimeo: { - sdk: 'https://player.vimeo.com/api/player.js', - iframe: 'https://player.vimeo.com/video/{0}?{1}', - api: 'https://vimeo.com/api/v2/video/{0}.json' - }, - youtube: { - sdk: 'https://www.youtube.com/iframe_api', - api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', - poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg' - }, - googleIMA: { - sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' - } - }, - // Custom control listeners - listeners: { - seek: null, - play: null, - pause: null, - restart: null, - rewind: null, - fastForward: null, - mute: null, - volume: null, - captions: null, - fullscreen: null, - pip: null, - airplay: null, - speed: null, - quality: null, - loop: null, - language: null - }, + /** + * Execute callbacks when dependencies have been satisfied. + * @param {(string|string[])} deps - List of bundle ids + * @param {Object} args - success/error arguments + */ + loadjs.ready = function ready(deps, args) { + // subscribe to bundle load event + subscribe(deps, function (depsNotFound) { + // execute callbacks + executeCallbacks(args, depsNotFound); + }); - // Events to watch and bubble - events: [ - // Events to watch on HTML5 media elements and bubble - // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events - 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', + return loadjs; + }; - // Custom events - 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', - // YouTube - 'statechange', 'qualitychange', 'qualityrequested', + /** + * Manually satisfy bundle dependencies. + * @param {string} bundleId - The bundle id + */ + loadjs.done = function done(bundleId) { + publish(bundleId, []); + }; - // Ads - 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], - // Selectors - // Change these to match your template if using custom HTML - selectors: { - editable: 'input, textarea, select, [contenteditable]', - container: '.plyr', - controls: { - container: null, - wrapper: '.plyr__controls' - }, - labels: '[data-plyr]', - buttons: { - play: '[data-plyr="play"]', - pause: '[data-plyr="pause"]', - restart: '[data-plyr="restart"]', - rewind: '[data-plyr="rewind"]', - fastForward: '[data-plyr="fast-forward"]', - mute: '[data-plyr="mute"]', - captions: '[data-plyr="captions"]', - fullscreen: '[data-plyr="fullscreen"]', - pip: '[data-plyr="pip"]', - airplay: '[data-plyr="airplay"]', - settings: '[data-plyr="settings"]', - loop: '[data-plyr="loop"]' - }, - inputs: { - seek: '[data-plyr="seek"]', - volume: '[data-plyr="volume"]', - speed: '[data-plyr="speed"]', - language: '[data-plyr="language"]', - quality: '[data-plyr="quality"]' - }, - display: { - currentTime: '.plyr__time--current', - duration: '.plyr__time--duration', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played', - loop: '.plyr__progress--loop', - volume: '.plyr__volume--display' - }, - progress: '.plyr__progress', - captions: '.plyr__captions', - menu: { - quality: '.js-plyr__menu__list--quality' - } - }, + /** + * Reset loadjs dependencies statuses + */ + loadjs.reset = function reset() { + bundleIdCache = {}; + bundleResultCache = {}; + bundleCallbackQueue = {}; + }; - // Class hooks added to the player in different states - classNames: { - type: 'plyr--{0}', - provider: 'plyr--{0}', - video: 'plyr__video-wrapper', - embed: 'plyr__video-embed', - embedContainer: 'plyr__video-embed__container', - poster: 'plyr__poster', - ads: 'plyr__ads', - control: 'plyr__control', - playing: 'plyr--playing', - paused: 'plyr--paused', - stopped: 'plyr--stopped', - loading: 'plyr--loading', - error: 'plyr--has-error', - hover: 'plyr--hover', - tooltip: 'plyr__tooltip', - cues: 'plyr__cues', - hidden: 'plyr__sr-only', - hideControls: 'plyr--hide-controls', - isIos: 'plyr--is-ios', - isTouch: 'plyr--is-touch', - uiSupported: 'plyr--full-ui', - noTransition: 'plyr--no-transition', - menu: { - value: 'plyr__menu__value', - badge: 'plyr__badge', - open: 'plyr--menu-open' - }, - captions: { - enabled: 'plyr--captions-enabled', - active: 'plyr--captions-active' - }, - fullscreen: { - enabled: 'plyr--fullscreen-enabled', - fallback: 'plyr--fullscreen-fallback' - }, - pip: { - supported: 'plyr--pip-supported', - active: 'plyr--pip-active' - }, - airplay: { - supported: 'plyr--airplay-supported', - active: 'plyr--airplay-active' - }, - tabFocus: 'plyr__tab-focus' - }, - // Embed attributes - attributes: { - embed: { - provider: 'data-plyr-provider', - id: 'data-plyr-embed-id' - } - }, + /** + * Determine if bundle has already been defined + * @param String} bundleId - The bundle id + */ + loadjs.isDefined = function isDefined(bundleId) { + return bundleId in bundleIdCache; + }; - // API keys - keys: { - google: null - }, - // Advertisements plugin - // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio - ads: { - enabled: false, - publisherId: '' - } -}; + // export + return loadjs; -// ========================================================================== + })); + }); -var browser$2 = utils.getBrowser(); + function loadScript(url) { + return new Promise(function (resolve, reject) { + loadjs_umd(url, { + success: resolve, + error: reject + }); + }); + } -function onChange() { - if (!this.enabled) { - return; + function parseId(url) { + if (is$1.empty(url)) { + return null; } - // Update toggle button - var button = this.player.elements.buttons.fullscreen; - if (utils.is.element(button)) { - utils.toggleState(button, this.active); + if (is$1.number(Number(url))) { + return url; } - // Trigger an event - utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); + var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) - // Trap focus in container - if (!browser$2.isIos) { - utils.trapFocus.call(this.player, this.target, this.active); - } -} -function toggleFallback() { - var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - // Store or restore scroll position - if (toggle) { - this.scrollPosition = { - x: window.scrollX || 0, - y: window.scrollY || 0 - }; - } else { - window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; } - // Toggle scroll - document.body.style.overflow = toggle ? 'hidden' : ''; - - // Toggle class hook - utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); - - // Toggle button and fire events - onChange.call(this); -} + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } -var Fullscreen = function () { - function Fullscreen(player) { - var _this = this; + var vimeo = { + setup: function setup() { + var _this = this; - classCallCheck(this, Fullscreen); + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio - // Keep reference to parent - this.player = player; + setAspectRatio.call(this); // Load the API if not already - // Get prefix - this.prefix = Fullscreen.prefix; - this.property = Fullscreen.property; + if (!is$1.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk).then(function () { + vimeo.ready.call(_this); + }).catch(function (error) { + _this.debug.warn('Vimeo API failed to load', error); + }); + } else { + vimeo.ready.call(this); + } + }, + // API Ready + ready: function ready$$1() { + var _this2 = this; - // Scroll position - this.scrollPosition = { x: 0, y: 0 }; + var player = this; + var config = player.config.vimeo; // Get Vimeo params for the iframe - // Register event listeners - // Handle event (incase user presses escape etc) - utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : this.prefix + 'fullscreenchange', function () { - // TODO: Filter for target?? - onChange.call(_this); - }); + var params = buildUrlParams(extend({}, { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative + }, config)); // Get the source URL or ID - // Fullscreen toggle on double click - utils.on(this.player.elements.container, 'dblclick', function (event) { - // Ignore double click in controls - if (utils.is.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) { - return; - } + var source = player.media.getAttribute('src'); // Get from <div> if needed - _this.toggle(); - }); + if (is$1.empty(source)) { + source = player.media.getAttribute(player.config.attributes.embed.id); + } - // Update the UI - this.update(); - } + var id = parseId(source); // Build an iframe - // Determine if native supported + var iframe = createElement('iframe'); + var src = format(player.config.urls.vimeo.iframe, id, params); + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + iframe.setAttribute('allowtransparency', ''); + iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set + var poster = player.poster; // Inject the package - createClass(Fullscreen, [{ - key: 'update', + var wrapper = createElement('div', { + poster: poster, + class: player.config.classNames.embedContainer + }); + wrapper.appendChild(iframe); + player.media = replaceElement(wrapper, player.media); // Get poster image + fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { + if (is$1.empty(response)) { + return; + } // Get the URL for thumbnail - // Update UI - value: function update() { - if (this.enabled) { - this.player.debug.log((Fullscreen.native ? 'Native' : 'Fallback') + ' fullscreen enabled'); - } else { - this.player.debug.log('Fullscreen not supported and fallback disabled'); - } - // Add styling hook to show button - utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); - } + var url = new URL(response[0].thumbnail_large); // Get original image - // Make an element fullscreen + url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster - }, { - key: 'enter', - value: function enter() { - if (!this.enabled) { - return; - } + ui.setPoster.call(player, url.href).catch(function () {}); + }); // Setup instance + // https://github.com/vimeo/player.js - // iOS native fullscreen doesn't need the request step - if (browser$2.isIos && this.player.config.fullscreen.iosNative) { - if (this.player.playing) { - this.target.webkitEnterFullscreen(); - } - } else if (!Fullscreen.native) { - toggleFallback.call(this, true); - } else if (!this.prefix) { - this.target.requestFullscreen(); - } else if (!utils.is.empty(this.prefix)) { - this.target[this.prefix + 'Request' + this.property](); - } - } + player.embed = new window.Vimeo.Player(iframe, { + autopause: player.config.autopause, + muted: player.muted + }); + player.media.paused = true; + player.media.currentTime = 0; // Disable native text track rendering - // Bail from fullscreen + if (player.supported.ui) { + player.embed.disableTextTrack(); + } // Create a faux HTML5 API using the Vimeo API - }, { - key: 'exit', - value: function exit() { - if (!this.enabled) { - return; - } - // iOS native fullscreen - if (browser$2.isIos && this.player.config.fullscreen.iosNative) { - this.target.webkitExitFullscreen(); - this.player.play(); - } else if (!Fullscreen.native) { - toggleFallback.call(this, false); - } else if (!this.prefix) { - (document.cancelFullScreen || document.exitFullscreen).call(document); - } else if (!utils.is.empty(this.prefix)) { - var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; - document['' + this.prefix + action + this.property](); - } - } + player.media.play = function () { + assurePlaybackState.call(player, true); + return player.embed.play(); + }; - // Toggle state + player.media.pause = function () { + assurePlaybackState.call(player, false); + return player.embed.pause(); + }; - }, { - key: 'toggle', - value: function toggle() { - if (!this.active) { - this.enter(); - } else { - this.exit(); - } - } - }, { - key: 'enabled', + player.media.stop = function () { + player.pause(); + player.currentTime = 0; + }; // Seeking - // Determine if fullscreen is enabled + var currentTime = player.media.currentTime; + Object.defineProperty(player.media, 'currentTime', { get: function get() { - return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + return currentTime; + }, + set: function set(time) { + // Vimeo will automatically play on seek if the video hasn't been played before + // Get current paused state and volume etc + var embed = player.embed, + media = player.media, + paused = player.paused, + volume = player.volume; + var restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event + + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete + + Promise.resolve(restorePause && embed.setVolume(0)) // Seek + .then(function () { + return embed.setCurrentTime(time); + }) // Restore paused + .then(function () { + return restorePause && embed.pause(); + }) // Restore volume + .then(function () { + return restorePause && embed.setVolume(volume); + }).catch(function () {// Do nothing + }); } + }); // Playback speed - // Get active state - - }, { - key: 'active', + var speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { get: function get() { - if (!this.enabled) { - return false; - } - - // Fallback using classname - if (!Fullscreen.native) { - return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + return speed; + }, + set: function set(input) { + player.embed.setPlaybackRate(input).then(function () { + speed = input; + triggerEvent.call(player, player.media, 'ratechange'); + }).catch(function (error) { + // Hide menu item (and menu if empty) + if (error.name === 'Error') { + controls.setSpeedMenu.call(player, []); } - - var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.property + 'Element']; - - return element === this.target; + }); } + }); // Volume - // Get target element - - }, { - key: 'target', + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { get: function get() { - return browser$2.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + return volume; + }, + set: function set(input) { + player.embed.setVolume(input).then(function () { + volume = input; + triggerEvent.call(player, player.media, 'volumechange'); + }); } - }], [{ - key: 'native', + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { get: function get() { - return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + return muted; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : false; + player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { + muted = toggle; + triggerEvent.call(player, player.media, 'volumechange'); + }); } + }); // Loop - // Get the prefix for handlers - - }, { - key: 'prefix', + var loop = player.config.loop; + Object.defineProperty(player.media, 'loop', { get: function get() { - // No prefix - if (utils.is.function(document.exitFullscreen)) { - return ''; - } - - // Check for fullscreen support by vendor prefix - var value = ''; - var prefixes = ['webkit', 'moz', 'ms']; - - prefixes.some(function (pre) { - if (utils.is.function(document[pre + 'ExitFullscreen']) || utils.is.function(document[pre + 'CancelFullScreen'])) { - value = pre; - return true; - } - - return false; - }); - - return value; + return loop; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : player.config.loop.active; + player.embed.setLoop(toggle).then(function () { + loop = toggle; + }); } - }, { - key: 'property', + }); // Source + + var currentSrc; + player.embed.getVideoUrl().then(function (value) { + currentSrc = value; + controls.setDownloadLink.call(player); + }).catch(function (error) { + _this2.debug.warn(error); + }); + Object.defineProperty(player.media, 'currentSrc', { get: function get() { - return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + return currentSrc; } - }]); - return Fullscreen; -}(); + }); // Ended -// ========================================================================== + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Set aspect ratio based on video size -// Sniff out the browser -var browser$3 = utils.getBrowser(); + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { + var _dimensions = _slicedToArray(dimensions, 2), + width = _dimensions[0], + height = _dimensions[1]; -var Listeners = function () { - function Listeners(player) { - classCallCheck(this, Listeners); + player.embed.ratio = "".concat(width, ":").concat(height); + setAspectRatio.call(_this2, player.embed.ratio); + }); // Set autopause - this.player = player; - this.lastKey = null; + player.embed.setAutopause(player.config.autopause).then(function (state) { + player.config.autopause = state; + }); // Get title - this.handleKey = this.handleKey.bind(this); - this.toggleMenu = this.toggleMenu.bind(this); - this.firstTouch = this.firstTouch.bind(this); - } + player.embed.getVideoTitle().then(function (title) { + player.config.title = title; + ui.setTitle.call(_this2); + }); // Get current time - // Handle key presses + player.embed.getCurrentTime().then(function (value) { + currentTime = value; + triggerEvent.call(player, player.media, 'timeupdate'); + }); // Get duration + player.embed.getDuration().then(function (value) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + }); // Get captions - createClass(Listeners, [{ - key: 'handleKey', - value: function handleKey(event) { - var _this = this; + player.embed.getTextTracks().then(function (tracks) { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + player.embed.on('cuechange', function (_ref) { + var _ref$cues = _ref.cues, + cues = _ref$cues === void 0 ? [] : _ref$cues; + var strippedCues = cues.map(function (cue) { + return stripHTML(cue.text); + }); + captions.updateCues.call(player, strippedCues); + }); + player.embed.on('loaded', function () { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(function (paused) { + assurePlaybackState.call(player, !paused); - var code = event.keyCode ? event.keyCode : event.which; - var pressed = event.type === 'keydown'; - var repeat = pressed && code === this.lastKey; + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); - // Bail if a modifier key is set - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return; - } + if (is$1.element(player.embed.element) && player.supported.ui) { + var frame = player.embed.element; // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 - // If the event is bubbled from the media element - // Firefox doesn't get the keycode for whatever reason - if (!utils.is.number(code)) { - return; - } + frame.setAttribute('tabindex', -1); + } + }); + player.embed.on('play', function () { + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); + }); + player.embed.on('pause', function () { + assurePlaybackState.call(player, false); + }); + player.embed.on('timeupdate', function (data) { + player.media.seeking = false; + currentTime = data.seconds; + triggerEvent.call(player, player.media, 'timeupdate'); + }); + player.embed.on('progress', function (data) { + player.media.buffered = data.percent; + triggerEvent.call(player, player.media, 'progress'); // Check all loaded - // Seek by the number keys - var seekByKey = function seekByKey() { - // Divide the max duration into 10th's and times by the number value - _this.player.currentTime = _this.player.duration / 10 * (code - 48); - }; + if (parseInt(data.percent, 10) === 1) { + triggerEvent.call(player, player.media, 'canplaythrough'); + } // Get duration as if we do it before load, it gives an incorrect value + // https://github.com/sampotts/plyr/issues/891 - // Handle the key on keydown - // Reset on keyup - if (pressed) { - // Which keycodes should we prevent default - var preventDefault = [48, 49, 50, 51, 52, 53, 54, 56, 57, 32, 75, 38, 40, 77, 39, 37, 70, 67, 73, 76, 79]; - - // Check focused element - // and if the focused element is not editable (e.g. text input) - // and any that accept key input http://webaim.org/techniques/keyboard/ - var focused = utils.getFocusElement(); - if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) { - return; - } - // If the code is found prevent default (e.g. prevent scrolling for arrows) - if (preventDefault.includes(code)) { - event.preventDefault(); - event.stopPropagation(); - } + player.embed.getDuration().then(function (value) { + if (value !== player.media.duration) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + } + }); + }); + player.embed.on('seeked', function () { + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + }); + player.embed.on('ended', function () { + player.media.paused = true; + triggerEvent.call(player, player.media, 'ended'); + }); + player.embed.on('error', function (detail) { + player.media.error = detail; + triggerEvent.call(player, player.media, 'error'); + }); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 0); + } + }; - switch (code) { - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: - // 0-9 - if (!repeat) { - seekByKey(); - } - break; - - case 32: - case 75: - // Space and K key - if (!repeat) { - this.player.togglePlay(); - } - break; - - case 38: - // Arrow up - this.player.increaseVolume(0.1); - break; - - case 40: - // Arrow down - this.player.decreaseVolume(0.1); - break; - - case 77: - // M key - if (!repeat) { - this.player.muted = !this.player.muted; - } - break; - - case 39: - // Arrow forward - this.player.forward(); - break; - - case 37: - // Arrow back - this.player.rewind(); - break; - - case 70: - // F key - this.player.fullscreen.toggle(); - break; - - case 67: - // C key - if (!repeat) { - this.player.toggleCaptions(); - } - break; - - case 76: - // L key - this.player.loop = !this.player.loop; - break; - - /* case 73: - this.setLoop('start'); - break; - case 76: - this.setLoop(); - break; - case 79: - this.setLoop('end'); - break; */ - - default: - break; - } + function parseId$1(url) { + if (is$1.empty(url)) { + return null; + } - // Escape is handle natively when in full screen - // So we only need to worry about non native - if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) { - this.player.fullscreen.toggle(); - } + var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; + } // Set playback state and trigger change (only on actual change) - // Store last code for next cycle - this.lastKey = code; - } else { - this.lastKey = null; - } - } - // Toggle menu + function assurePlaybackState$1(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } - }, { - key: 'toggleMenu', - value: function toggleMenu(event) { - controls.toggleMenu.call(this.player, event); - } + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } + } - // Device is touch enabled + var youtube = { + setup: function setup() { + var _this = this; - }, { - key: 'firstTouch', - value: function firstTouch() { - this.player.touch = true; + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio - // Add touch class - utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true); + setAspectRatio.call(this); // Setup API - // Clean up - utils.off(document.body, 'touchstart', this.firstTouch); - } + if (is$1.object(window.YT) && is$1.function(window.YT.Player)) { + youtube.ready.call(this); + } else { + // Load the API + loadScript(this.config.urls.youtube.sdk).catch(function (error) { + _this.debug.warn('YouTube API failed to load', error); + }); // Setup callback for the API + // YouTube has it's own system of course... - // Global window & document listeners + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue - }, { - key: 'global', - value: function global() { - var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + window.onYouTubeReadyCallbacks.push(function () { + youtube.ready.call(_this); + }); // Set callback to process queue - // Keyboard shortcuts - if (this.player.config.keyboard.global) { - utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false); - } + window.onYouTubeIframeAPIReady = function () { + window.onYouTubeReadyCallbacks.forEach(function (callback) { + callback(); + }); + }; + } + }, + // Get the media title + getTitle: function getTitle(videoId) { + var _this2 = this; - // Click anywhere closes menu - utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (is$1.function(this.embed.getVideoData)) { + var _this$embed$getVideoD = this.embed.getVideoData(), + title = _this$embed$getVideoD.title; - // Detect touch by events - utils.on(document.body, 'touchstart', this.firstTouch); + if (is$1.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; } + } // Or via Google API - // Container listeners - }, { - key: 'container', - value: function container() { - var _this2 = this; + var key = this.config.keys.google; - // Keyboard shortcuts - if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) { - utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false); - } + if (is$1.string(key) && !is$1.empty(key)) { + var url = format(this.config.urls.youtube.api, videoId, key); + fetch(url).then(function (result) { + if (is$1.object(result)) { + _this2.config.title = result.items[0].snippet.title; + ui.setTitle.call(_this2); + } + }).catch(function () {}); + } + }, + // API ready + ready: function ready$$1() { + var player = this; // Ignore already setup (race condition) - // Detect tab focus - // Remove class on blur/focusout - utils.on(this.player.elements.container, 'focusout', function (event) { - utils.toggleClass(event.target, _this2.player.config.classNames.tabFocus, false); - }); + var currentId = player.media.getAttribute('id'); - // Add classname to tabbed elements - utils.on(this.player.elements.container, 'keydown', function (event) { - if (event.keyCode !== 9) { - return; - } + if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) { + return; + } // Get the source URL or ID - // Delay the adding of classname until the focus has changed - // This event fires before the focusin event - setTimeout(function () { - utils.toggleClass(utils.getFocusElement(), _this2.player.config.classNames.tabFocus, true); - }, 0); - }); - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', function (event) { - _this2.player.toggleControls(event); - }); - } - } + var source = player.media.getAttribute('src'); // Get from <div> if needed - // Listen for media events + if (is$1.empty(source)) { + source = player.media.getAttribute(this.config.attributes.embed.id); + } // Replace the <iframe> with a <div> due to YouTube API issues - }, { - key: 'media', - value: function media() { - var _this3 = this; - // Time change on media - utils.on(this.player.media, 'timeupdate seeking', function (event) { - return ui.timeUpdate.call(_this3.player, event); - }); + var videoId = parseId$1(source); + var id = generateId(player.provider); // Get poster, if already set - // Display duration - utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', function (event) { - return ui.durationUpdate.call(_this3.player, event); - }); + var poster = player.poster; // Replace media element - // Check for audio tracks on load - // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point - utils.on(this.player.media, 'loadeddata', function () { - utils.toggleHidden(_this3.player.elements.volume, !_this3.player.hasAudio); - utils.toggleHidden(_this3.player.elements.buttons.mute, !_this3.player.hasAudio); - }); + var container = createElement('div', { + id: id, + poster: poster + }); + player.media = replaceElement(container, player.media); // Id to poster wrapper + + var posterSrc = function posterSrc(format$$1) { + return "https://img.youtube.com/vi/".concat(videoId, "/").concat(format$$1, "default.jpg"); + }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + + + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(function () { + return loadImage(posterSrc('sd'), 121); + }) // 480p padded 4:3 + .catch(function () { + return loadImage(posterSrc('hq')); + }) // 360p padded 4:3. Always exists + .then(function (image) { + return ui.setPoster.call(player, image.src); + }).then(function (posterSrc) { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }).catch(function () {}); + var config = player.config.youtube; // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + + player.embed = new window.YT.Player(id, { + videoId: videoId, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend({}, { + autoplay: player.config.autoplay ? 1 : 0, + // Autoplay + hl: player.config.hl, + // iframe interface language + controls: player.supported.ui ? 0 : 1, + // Only show controls if not fully supported + disablekb: 1, + // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, + // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null + }, config), + events: { + onError: function onError(event) { + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + var code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + + var message = { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.' + }[code] || 'An unknown error occured'; + player.media.error = { + code: code, + message: message + }; + triggerEvent.call(player, player.media, 'error'); + } + }, + onPlaybackRateChange: function onPlaybackRateChange(event) { + // Get the instance + var instance = event.target; // Get current speed + + player.media.playbackRate = instance.getPlaybackRate(); + triggerEvent.call(player, player.media, 'ratechange'); + }, + onReady: function onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is$1.function(player.media.play)) { + return; + } // Get the instance + + + var instance = event.target; // Get the title + + youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API + + player.media.play = function () { + assurePlaybackState$1.call(player, true); + instance.playVideo(); + }; - // Handle the media finishing - utils.on(this.player.media, 'ended', function () { - // Show poster on end - if (_this3.player.isHTML5 && _this3.player.isVideo && _this3.player.config.resetOnEnd) { - // Restart - _this3.player.restart(); - } - }); + player.media.pause = function () { + assurePlaybackState$1.call(player, false); + instance.pauseVideo(); + }; - // Check for buffer progress - utils.on(this.player.media, 'progress playing', function (event) { - return ui.updateProgress.call(_this3.player, event); - }); + player.media.stop = function () { + instance.stopVideo(); + }; - // Handle volume changes - utils.on(this.player.media, 'volumechange', function (event) { - return ui.updateVolume.call(_this3.player, event); - }); + player.media.duration = instance.getDuration(); + player.media.paused = true; // Seeking - // Handle play/pause - utils.on(this.player.media, 'playing play pause ended emptied timeupdate', function (event) { - return ui.checkPlaying.call(_this3.player, event); - }); + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return Number(instance.getCurrentTime()); + }, + set: function set(time) { + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } // Set seeking state and trigger event - // Loading state - utils.on(this.player.media, 'waiting canplay seeked playing', function (event) { - return ui.checkLoading.call(_this3.player, event); - }); - // Check if media failed to load - // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event)); + player.media.seeking = true; + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent + + instance.seekTo(time); + } + }); // Playback speed + + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return instance.getPlaybackRate(); + }, + set: function set(input) { + instance.setPlaybackRate(input); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + volume = input; + instance.setVolume(volume * 100); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Source + + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return instance.getVideoUrl(); + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Get available speeds - // If autoplay, then load advertisement if required - // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows - utils.on(this.player.media, 'playing', function () { - if (!_this3.player.ads) { - return; - } + player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe - // If ads are enabled, wait for them first - if (_this3.player.ads.enabled && !_this3.player.ads.initialized) { - // Wait for manager response - _this3.player.ads.managerPromise.then(function () { - return _this3.player.ads.play(); - }).catch(function () { - return _this3.player.play(); - }); - } - }); + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } - // Click video - if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) { - // Re-fetch the wrapper - var wrapper = utils.getElement.call(this.player, '.' + this.player.config.classNames.video); + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer - // Bail if there's no wrapper (this should never happen) - if (!utils.is.element(wrapper)) { - return; - } + clearInterval(player.timers.buffering); // Setup buffering - // On click play, pause ore restart - utils.on(wrapper, 'click', function () { - // Touch devices will just show controls (if we're hiding controls) - if (_this3.player.config.hideControls && _this3.player.touch && !_this3.player.paused) { - return; - } - - if (_this3.player.paused) { - _this3.player.play(); - } else if (_this3.player.ended) { - _this3.player.restart(); - _this3.player.play(); - } else { - _this3.player.pause(); - } - }); - } + player.timers.buffering = setInterval(function () { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something - // Disable right click - if (this.player.supported.ui && this.player.config.disableContextMenu) { - utils.on(this.player.elements.wrapper, 'contextmenu', function (event) { - event.preventDefault(); - }, false); - } + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + triggerEvent.call(player, player.media, 'progress'); + } // Set last buffer point - // Volume change - utils.on(this.player.media, 'volumechange', function () { - // Save to storage - _this3.player.storage.set({ volume: _this3.player.volume, muted: _this3.player.muted }); - }); - // Speed change - utils.on(this.player.media, 'ratechange', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'speed'); + player.media.lastBuffered = player.media.buffered; // Bail if we're at 100% - // Save to storage - _this3.player.storage.set({ speed: _this3.player.speed }); - }); + if (player.media.buffered === 1) { + clearInterval(player.timers.buffering); // Trigger event - // Quality request - utils.on(this.player.media, 'qualityrequested', function (event) { - // Save to storage - _this3.player.storage.set({ quality: event.detail.quality }); - }); + triggerEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); // Rebuild UI - // Quality change - utils.on(this.player.media, 'qualitychange', function (event) { - // Update UI - controls.updateSetting.call(_this3.player, 'quality', null, event.detail.quality); - }); + setTimeout(function () { + return ui.build.call(player); + }, 50); + }, + onStateChange: function onStateChange(event) { + // Get the instance + var instance = event.target; // Reset timer - // Caption language change - utils.on(this.player.media, 'languagechange', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'captions'); + clearInterval(player.timers.playing); + var seeked = player.media.seeking && [1, 2].includes(event.data); - // Save to storage - _this3.player.storage.set({ language: _this3.player.language }); - }); + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued - // Captions toggle - utils.on(this.player.media, 'captionsenabled captionsdisabled', function () { - // Update UI - controls.updateSetting.call(_this3.player, 'captions'); - // Save to storage - _this3.player.storage.set({ captions: _this3.player.captions.active }); - }); + switch (event.data) { + case -1: + // Update scrubber + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube - // Proxy events to container - // Bubble up key events for Edge - utils.on(this.player.media, this.player.config.events.concat(['keyup', 'keydown']).join(' '), function (event) { - var detail = {}; + player.media.buffered = instance.getVideoLoadedFraction(); + triggerEvent.call(player, player.media, 'progress'); + break; - // Get error details from media - if (event.type === 'error') { - detail = _this3.player.media.error; + case 0: + assurePlaybackState$1.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. + + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + triggerEvent.call(player, player.media, 'ended'); } - utils.dispatchEvent.call(_this3.player, _this3.player.elements.container, event.type, true, detail); - }); - } + break; - // Listen for control events + case 1: + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState$1.call(player, true); + triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress - }, { - key: 'controls', - value: function controls$$1() { - var _this4 = this; - - // IE doesn't support input event, so we fallback to change - var inputEvent = browser$3.isIE ? 'change' : 'input'; - - // Run default and custom handlers - var proxy = function proxy(event, defaultHandler, customHandlerKey) { - var customHandler = _this4.player.config.listeners[customHandlerKey]; - var hasCustomHandler = utils.is.function(customHandler); - var returned = true; - - // Execute custom handler - if (hasCustomHandler) { - returned = customHandler.call(_this4.player, event); - } + player.timers.playing = setInterval(function () { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - // Only call default handler if not prevented in custom handler - if (returned && utils.is.function(defaultHandler)) { - defaultHandler.call(_this4.player, event); + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + triggerEvent.call(player, player.media, 'durationchange'); + } } - }; - // Trigger custom and default handlers - var on = function on(element, type, defaultHandler, customHandlerKey) { - var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + break; - var customHandler = _this4.player.config.listeners[customHandlerKey]; - var hasCustomHandler = utils.is.function(customHandler); + case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } - utils.on(element, type, function (event) { - return proxy(event, defaultHandler, customHandlerKey); - }, passive && !hasCustomHandler); - }; + assurePlaybackState$1.call(player, false); + break; - // Play/pause toggle - on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play'); + default: + break; + } - // Pause - on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart'); + triggerEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data + }); + } + } + }); + } + }; - // Rewind - on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind'); + var media = { + // Setup media + setup: function setup() { + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } // Add type class - // Rewind - on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward'); - // Mute toggle - on(this.player.elements.buttons.mute, 'click', function () { - _this4.player.muted = !_this4.player.muted; - }, 'mute'); + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class - // Captions toggle - on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions); + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds + // This will require changes if audio embeds are added - // Fullscreen toggle - on(this.player.elements.buttons.fullscreen, 'click', function () { - _this4.player.fullscreen.toggle(); - }, 'fullscreen'); + if (this.isEmbed) { + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } // Inject the player wrapper - // Picture-in-Picture - on(this.player.elements.buttons.pip, 'click', function () { - _this4.player.pip = 'toggle'; - }, 'pip'); - // Airplay - on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay'); + if (this.isVideo) { + // Create the wrapper div + this.elements.wrapper = createElement('div', { + class: this.config.classNames.video + }); // Wrap the video in a container - // Settings menu - on(this.player.elements.buttons.settings, 'click', function (event) { - controls.toggleMenu.call(_this4.player, event); - }); + wrap(this.media, this.elements.wrapper); // Faux poster container - // Settings menu - on(this.player.elements.settings.form, 'click', function (event) { - event.stopPropagation(); - - // Go back to home tab on click - var showHomeTab = function showHomeTab() { - var id = 'plyr-settings-' + _this4.player.id + '-home'; - controls.showTab.call(_this4.player, id); - }; - - // Settings menu items - use event delegation as items are added/removed - if (utils.matches(event.target, _this4.player.config.selectors.inputs.language)) { - proxy(event, function () { - _this4.player.language = event.target.value; - showHomeTab(); - }, 'language'); - } else if (utils.matches(event.target, _this4.player.config.selectors.inputs.quality)) { - proxy(event, function () { - _this4.player.quality = event.target.value; - showHomeTab(); - }, 'quality'); - } else if (utils.matches(event.target, _this4.player.config.selectors.inputs.speed)) { - proxy(event, function () { - _this4.player.speed = parseFloat(event.target.value); - showHomeTab(); - }, 'speed'); - } else { - var tab = event.target; - controls.showTab.call(_this4.player, tab.getAttribute('aria-controls')); - } - }); + this.elements.poster = createElement('div', { + class: this.config.classNames.poster + }); + this.elements.wrapper.appendChild(this.elements.poster); + } - // Seek - on(this.player.elements.inputs.seek, inputEvent, function (event) { - _this4.player.currentTime = event.target.value / event.target.max * _this4.player.duration; - }, 'seek'); - - // Current time invert - // Only if one time element is used for both currentTime and duration - if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) { - on(this.player.elements.display.currentTime, 'click', function () { - // Do nothing if we're at the start - if (_this4.player.currentTime === 0) { - return; - } - - _this4.player.config.invertTime = !_this4.player.config.invertTime; - ui.timeUpdate.call(_this4.player); - }); - } + if (this.isHTML5) { + html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); + } + } + }; - // Volume - on(this.player.elements.inputs.volume, inputEvent, function (event) { - _this4.player.volume = event.target.value; - }, 'volume'); + var Ads = + /*#__PURE__*/ + function () { + /** + * Ads constructor. + * @param {object} player + * @return {Ads} + */ + function Ads(player) { + var _this = this; - // Polyfill for lower fill in <input type="range"> for webkit - if (browser$3.isWebkit) { - on(utils.getElements.call(this.player, 'input[type="range"]'), 'input', function (event) { - controls.updateRangeFill.call(_this4.player, event.target); - }); - } + _classCallCheck(this, Ads); - // Seek tooltip - on(this.player.elements.progress, 'mouseenter mouseleave mousemove', function (event) { - return controls.updateSeekTooltip.call(_this4.player, event); - }); + this.player = player; + this.config = player.config.ads; + this.playing = false; + this.initialized = false; + this.elements = { + container: null, + displayContainer: null + }; + this.manager = null; + this.loader = null; + this.cuePoints = null; + this.events = {}; + this.safetyTimer = null; + this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mouseenter mouseleave', function (event) { - _this4.player.elements.controls.hover = !_this4.player.touch && event.type === 'mouseenter'; - }); + this.managerPromise = new Promise(function (resolve, reject) { + // The ad is loaded and ready + _this.on('loaded', resolve); // Ads failed - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { - _this4.player.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); - }); - // Focus in/out on controls - on(this.player.elements.controls, 'focusin focusout', function (event) { - _this4.player.toggleControls(event); - }); - } + _this.on('error', reject); + }); + this.load(); + } - // Mouse wheel for volume - on(this.player.elements.inputs.volume, 'wheel', function (event) { - // Detect "natural" scroll - suppored on OS X Safari only - // Other browsers on OS X will be inverted until support improves - var inverted = event.webkitDirectionInvertedFromDevice; - var step = 1 / 50; - var direction = 0; - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - _this4.player.decreaseVolume(step); - direction = -1; - } else { - _this4.player.increaseVolume(step); - direction = 1; - } - } + _createClass(Ads, [{ + key: "load", - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - _this4.player.increaseVolume(step); - direction = 1; - } else { - _this4.player.decreaseVolume(step); - direction = -1; - } - } + /** + * Load the IMA SDK + */ + value: function load() { + var _this2 = this; - // Don't break page scrolling at max and min - if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) { - event.preventDefault(); - } - }, 'volume', false); + if (this.enabled) { + // Check if the Google IMA3 SDK is loaded or load it ourselves + if (!is$1.object(window.google) || !is$1.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); + } } - - // Reset on destroy + } + /** + * Get the ads instance ready + */ }, { - key: 'clear', - value: function clear() { - this.global(false); - } - }]); - return Listeners; -}(); - -// ========================================================================== - -var vimeo = { - setup: function setup() { - var _this = this; + key: "ready", + value: function ready$$1() { + var _this3 = this; - // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + // Start ticking our safety timer. If the whole advertisement + // thing doesn't resolve within our set time; we bail + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer - // Set intial ratio - vimeo.setAspectRatio.call(this); + this.managerPromise.then(function () { + _this3.clearSafetyTimer('onAdsManagerLoaded()'); + }); // Set listeners on the Plyr instance - // Load the API if not already - if (!utils.is.object(window.Vimeo)) { - utils.loadScript(this.config.urls.vimeo.sdk).then(function () { - vimeo.ready.call(_this); - }).catch(function (error) { - _this.debug.warn('Vimeo API failed to load', error); - }); - } else { - vimeo.ready.call(this); - } - }, + this.listeners(); // Setup the IMA SDK + this.setupIMA(); + } // Build the tag URL - // Set aspect ratio - // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI - setAspectRatio: function setAspectRatio(input) { - var ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':'); - var padding = 100 / ratio[0] * ratio[1]; - this.elements.wrapper.style.paddingBottom = padding + '%'; + }, { + key: "setupIMA", + + /** + * In order for the SDK to display ads for our video, we need to tell it where to put them, + * so here we define our ad container. This div is set up to render on top of the video player. + * Using the code below, we tell the SDK to render ads within that div. We also provide a + * handle to the content video player - the SDK will poll the current time of our player to + * properly place mid-rolls. After we create the ad display container, we initialize it. On + * mobile devices, this initialization is done as the result of a user action. + */ + value: function setupIMA() { + // Create the container for our advertisements + this.elements.container = createElement('div', { + class: this.player.config.classNames.ads + }); + this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2 - if (this.supported.ui) { - var height = 240; - var offset = (height - padding) / (height / 50); + google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language - this.media.style.transform = 'translateY(-' + offset + '%)'; - } - }, + google.ima.settings.setLocale(this.player.config.ads.language); // We assume the adContainer is the video container of the plyr element + // that will house the ads + this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); // Request video ads to be pre-loaded - // API Ready - ready: function ready() { - var _this2 = this; + this.requestAds(); + } + /** + * Request advertisements + */ - var player = this; - - // Get Vimeo params for the iframe - var options = { - loop: player.config.loop.active, - autoplay: player.autoplay, - // muted: player.muted, - byline: false, - portrait: false, - title: false, - speed: true, - transparent: 0, - gesture: 'media', - playsinline: !this.config.fullscreen.iosNative - }; - var params = utils.buildUrlParams(options); + }, { + key: "requestAds", + value: function requestAds() { + var _this4 = this; - // Get the source URL or ID - var source = player.media.getAttribute('src'); + var container = this.player.elements.container; - // Get from <div> if needed - if (utils.is.empty(source)) { - source = player.media.getAttribute(player.config.attributes.embed.id); - } + try { + // Create ads loader + this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events - var id = utils.parseVimeoId(source); - - // Build an iframe - var iframe = utils.createElement('iframe'); - var src = utils.format(player.config.urls.vimeo.iframe, id, params); - iframe.setAttribute('src', src); - iframe.setAttribute('allowfullscreen', ''); - iframe.setAttribute('allowtransparency', ''); - iframe.setAttribute('allow', 'autoplay'); - - // Inject the package - var wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer }); - wrapper.appendChild(iframe); - player.media = utils.replaceElement(wrapper, player.media); - - // Get poster image - utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(function (response) { - if (utils.is.empty(response)) { - return; - } + this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { + return _this4.onAdsManagerLoaded(event); + }, false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this4.onAdError(error); + }, false); // Request video ads - // Get the URL for thumbnail - var url = new URL(response[0].thumbnail_large); + var request = new google.ima.AdsRequest(); + request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK + // to select the correct creative if multiple are returned - // Get original image - url.pathname = url.pathname.split('_')[0] + '.jpg'; + request.linearAdSlotWidth = container.offsetWidth; + request.linearAdSlotHeight = container.offsetHeight; + request.nonLinearAdSlotWidth = container.offsetWidth; + request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video. - // Set attribute - player.media.setAttribute('poster', url.href); + request.forceNonLinearFullSlot = false; // Mute based on current state - // Update - ui.setPoster.call(player); - }); + request.setAdWillPlayMuted(!this.player.muted); + this.loader.requestAds(request); + } catch (e) { + this.onAdError(e); + } + } + /** + * Update the ad countdown + * @param {boolean} start + */ - // Setup instance - // https://github.com/vimeo/player.js - player.embed = new window.Vimeo.Player(iframe, { - autopause: player.config.autopause, - muted: player.muted - }); + }, { + key: "pollCountdown", + value: function pollCountdown() { + var _this5 = this; - player.media.paused = true; - player.media.currentTime = 0; + var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - // Disable native text track rendering - if (player.supported.ui) { - player.embed.disableTextTrack(); + if (!start) { + clearInterval(this.countdownTimer); + this.elements.container.removeAttribute('data-badge-text'); + return; } - // Create a faux HTML5 API using the Vimeo API - player.media.play = function () { - player.embed.play().then(function () { - player.media.paused = false; - }); - }; + var update = function update() { + var time = formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); + var label = "".concat(i18n.get('advertisement', _this5.player.config), " - ").concat(time); - player.media.pause = function () { - player.embed.pause().then(function () { - player.media.paused = true; - }); + _this5.elements.container.setAttribute('data-badge-text', label); }; - player.media.stop = function () { - player.pause(); - player.currentTime = 0; - }; - - // Seeking - var currentTime = player.media.currentTime; - - Object.defineProperty(player.media, 'currentTime', { - get: function get() { - return currentTime; - }, - set: function set(time) { - // Get current paused state - // Vimeo will automatically play on seek - var paused = player.media.paused; - - // Set seeking flag - - player.media.seeking = true; - - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); - - // Seek after events - player.embed.setCurrentTime(time).catch(function () { - // Do nothing - }); - - // Restore pause state - if (paused) { - player.pause(); - } - } - }); + this.countdownTimer = setInterval(update, 100); + } + /** + * This method is called whenever the ads are ready inside the AdDisplayContainer + * @param {Event} adsManagerLoadedEvent + */ - // Playback speed - var speed = player.config.speed.selected; - Object.defineProperty(player.media, 'playbackRate', { - get: function get() { - return speed; - }, - set: function set(input) { - player.embed.setPlaybackRate(input).then(function () { - speed = input; - utils.dispatchEvent.call(player, player.media, 'ratechange'); - }).catch(function (error) { - // Hide menu item (and menu if empty) - if (error.name === 'Error') { - controls.setSpeedMenu.call(player, []); - } - }); - } - }); + }, { + key: "onAdsManagerLoaded", + value: function onAdsManagerLoaded(event) { + var _this6 = this; - // Volume - var volume = player.config.volume; + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } // Get the ads manager - Object.defineProperty(player.media, 'volume', { - get: function get() { - return volume; - }, - set: function set(input) { - player.embed.setVolume(input).then(function () { - volume = input; - utils.dispatchEvent.call(player, player.media, 'volumechange'); - }); - } - }); - // Muted - var muted = player.config.muted; + var settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf - Object.defineProperty(player.media, 'muted', { - get: function get() { - return muted; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : false; + settings.restoreCustomPlaybackStateOnAdBreakComplete = true; + settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration + // so it can determine when to start the mid- and post-roll - player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { - muted = toggle; - utils.dispatchEvent.call(player, player.media, 'volumechange'); - }); - } - }); + this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll - // Loop - var loop = player.config.loop; + this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available - Object.defineProperty(player.media, 'loop', { - get: function get() { - return loop; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : player.config.loop.active; + if (!is$1.empty(this.cuePoints)) { + this.cuePoints.forEach(function (cuePoint) { + if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { + var seekElement = _this6.player.elements.progress; - player.embed.setLoop(toggle).then(function () { - loop = toggle; + if (is$1.element(seekElement)) { + var cuePercentage = 100 / _this6.player.duration * cuePoint; + var cue = createElement('span', { + class: _this6.player.config.classNames.cues }); + cue.style.left = "".concat(cuePercentage.toString(), "%"); + seekElement.appendChild(cue); + } } - }); + }); + } // Set volume to match player - // Source - var currentSrc = void 0; - player.embed.getVideoUrl().then(function (value) { - currentSrc = value; - }).catch(function (error) { - _this2.debug.warn(error); - }); - Object.defineProperty(player.media, 'currentSrc', { - get: function get() { - return currentSrc; - } - }); + this.manager.setVolume(this.player.volume); // Add listeners to the required events + // Advertisement error events - // Ended - Object.defineProperty(player.media, 'ended', { - get: function get() { - return player.currentTime === player.duration; - } - }); + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this6.onAdError(error); + }); // Advertisement regular events - // Set aspect ratio based on video size - Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { - var ratio = utils.getAspectRatio(dimensions[0], dimensions[1]); - vimeo.setAspectRatio.call(_this2, ratio); - }); + Object.keys(google.ima.AdEvent.Type).forEach(function (type) { + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { + return _this6.onAdEvent(event); + }); + }); // Resolve our adsManager - // Set autopause - player.embed.setAutopause(player.config.autopause).then(function (state) { - player.config.autopause = state; - }); + this.trigger('loaded'); + } + /** + * This is where all the event handling takes place. Retrieve the ad from the event. Some + * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated + * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type + * @param {Event} event + */ - // Get title - player.embed.getVideoTitle().then(function (title) { - player.config.title = title; - ui.setTitle.call(_this2); - }); + }, { + key: "onAdEvent", + value: function onAdEvent(event) { + var _this7 = this; - // Get current time - player.embed.getCurrentTime().then(function (value) { - currentTime = value; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }); + var container = this.player.elements.container; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) + // don't have ad object associated - // Get duration - player.embed.getDuration().then(function (value) { - player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); - }); + var ad = event.getAd(); + var adData = event.getAdData(); // Proxy event - // Get captions - player.embed.getTextTracks().then(function (tracks) { - player.media.textTracks = tracks; - captions.setup.call(player); - }); + var dispatchEvent = function dispatchEvent(type) { + var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); + triggerEvent.call(_this7.player, _this7.player.media, event); + }; - player.embed.on('cuechange', function (data) { - var cue = null; + switch (event.type) { + case google.ima.AdEvent.Type.LOADED: + // This is the first event sent for an ad - it is possible to determine whether the + // ad is a video ad or an overlay + this.trigger('loaded'); // Bubble event + + dispatchEvent(event.type); // Start countdown + + this.pollCountdown(true); + + if (!ad.isLinear()) { + // Position AdDisplayContainer correctly for overlay + ad.width = container.offsetWidth; + ad.height = container.offsetHeight; + } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); + // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); + + + break; + + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: + // All ads for the current videos are done. We can now request new advertisements + // in case the video is re-played + // Fire event + dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // So here we load a new video when all ads are done. + // Then we load new ads within a new adsManager. When the video + // Is started - after - the ads are loaded, then we get ads. + // You can also easily test cancelling and reloading by running + // player.ads.cancel() and player.ads.play from the console I guess. + // this.player.source = { + // type: 'video', + // title: 'View From A Blue Moon', + // sources: [{ + // src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: + // 'video/mp4', }], poster: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: + // [ { kind: 'captions', label: 'English', srclang: 'en', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], + // }; + // TODO: So there is still this thing where a video should only be allowed to start + // playing when the IMA SDK is ready or has failed - if (data.cues.length) { - cue = utils.stripHTML(data.cues[0].text); - } + this.loadAds(); + break; + + case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: + // This event indicates the ad has started - the video player can adjust the UI, + // for example display a pause button and remaining time. Fired when content should + // be paused. This usually happens right before an ad is about to cover the content + dispatchEvent(event.type); + this.pauseContent(); + break; + + case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: + // This event indicates the ad has finished - the video player can perform + // appropriate UI actions, such as removing the timer for remaining time detection. + // Fired when content should be resumed. This usually happens when an ad finishes + // or collapses + dispatchEvent(event.type); + this.pollCountdown(); + this.resumeContent(); + break; + + case google.ima.AdEvent.Type.STARTED: + case google.ima.AdEvent.Type.MIDPOINT: + case google.ima.AdEvent.Type.COMPLETE: + case google.ima.AdEvent.Type.IMPRESSION: + case google.ima.AdEvent.Type.CLICK: + dispatchEvent(event.type); + break; + + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); + } + + break; + + default: + break; + } + } + /** + * Any ad error handling comes through here + * @param {Event} event + */ - captions.setText.call(player, cue); - }); + }, { + key: "onAdError", + value: function onAdError(event) { + this.cancel(); + this.player.debug.warn('Ads error', event); + } + /** + * Setup hooks for Plyr and window events. This ensures + * the mid- and post-roll launch at the correct time. And + * resize the advertisement when the player resizes + */ - player.embed.on('loaded', function () { - if (utils.is.element(player.embed.element) && player.supported.ui) { - var frame = player.embed.element; + }, { + key: "listeners", + value: function listeners() { + var _this8 = this; - // Fix keyboard focus issues - // https://github.com/sampotts/plyr/issues/317 - frame.setAttribute('tabindex', -1); - } - }); + var container = this.player.elements.container; + var time; // Add listeners to the required events - player.embed.on('play', function () { - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - utils.dispatchEvent.call(player, player.media, 'playing'); + this.player.on('ended', function () { + _this8.loader.contentComplete(); }); - - player.embed.on('pause', function () { - player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'pause'); + this.player.on('timeupdate', function () { + time = _this8.player.currentTime; }); + this.player.on('seeked', function () { + var seekedTime = _this8.player.currentTime; - player.embed.on('timeupdate', function (data) { - player.media.seeking = false; - currentTime = data.seconds; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }); + if (is$1.empty(_this8.cuePoints)) { + return; + } - player.embed.on('progress', function (data) { - player.media.buffered = data.percent; - utils.dispatchEvent.call(player, player.media, 'progress'); + _this8.cuePoints.forEach(function (cuePoint, index) { + if (time < cuePoint && cuePoint < seekedTime) { + _this8.manager.discardAdBreak(); - // Check all loaded - if (parseInt(data.percent, 10) === 1) { - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); + _this8.cuePoints.splice(index, 1); } + }); + }); // Listen to the resizing of the window. And resize ad accordingly + // TODO: eventually implement ResizeObserver - // Get duration as if we do it before load, it gives an incorrect value - // https://github.com/sampotts/plyr/issues/891 - player.embed.getDuration().then(function (value) { - if (value !== player.media.duration) { - player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); - } - }); - }); - - player.embed.on('seeked', function () { - player.media.seeking = false; - utils.dispatchEvent.call(player, player.media, 'seeked'); - utils.dispatchEvent.call(player, player.media, 'play'); - }); - - player.embed.on('ended', function () { - player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'ended'); + window.addEventListener('resize', function () { + if (_this8.manager) { + _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); + } }); + } + /** + * Initialize the adsManager and start playing advertisements + */ - player.embed.on('error', function (detail) { - player.media.error = detail; - utils.dispatchEvent.call(player, player.media, 'error'); - }); + }, { + key: "play", + value: function play() { + var _this9 = this; - // Rebuild UI - setTimeout(function () { - return ui.build.call(player); - }, 0); - } -}; + var container = this.player.elements.container; -// ========================================================================== + if (!this.managerPromise) { + this.resumeContent(); + } // Play the requested advertisement whenever the adsManager is ready -// Standardise YouTube quality unit -function mapQualityUnit(input) { - switch (input) { - case 'hd2160': - return 2160; - case 2160: - return 'hd2160'; + this.managerPromise.then(function () { + // Initialize the container. Must be done via a user action on mobile devices + _this9.elements.displayContainer.initialize(); - case 'hd1440': - return 1440; + try { + if (!_this9.initialized) { + // Initialize the ads manager. Ad rules playlist will start at this time + _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will + // start at this time; the call will be ignored for ad rules - case 1440: - return 'hd1440'; - case 'hd1080': - return 1080; + _this9.manager.start(); + } - case 1080: - return 'hd1080'; + _this9.initialized = true; + } catch (adError) { + // An error may be thrown if there was a problem with the + // VAST response + _this9.onAdError(adError); + } + }).catch(function () {}); + } + /** + * Resume our video + */ - case 'hd720': - return 720; + }, { + key: "resumeContent", + value: function resumeContent() { + // Hide the advertisement container + this.elements.container.style.zIndex = ''; // Ad is stopped - case 720: - return 'hd720'; + this.playing = false; // Play our video - case 'large': - return 480; + if (this.player.currentTime < this.player.duration) { + this.player.play(); + } + } + /** + * Pause our video + */ - case 480: - return 'large'; + }, { + key: "pauseContent", + value: function pauseContent() { + // Show the advertisement container + this.elements.container.style.zIndex = 3; // Ad is playing. - case 'medium': - return 360; + this.playing = true; // Pause our video. - case 360: - return 'medium'; + this.player.pause(); + } + /** + * Destroy the adsManager so we can grab new ads after this. If we don't then we're not + * allowed to call new ads based on google policies, as they interpret this as an accidental + * video requests. https://developers.google.com/interactive- + * media-ads/docs/sdks/android/faq#8 + */ - case 'small': - return 240; + }, { + key: "cancel", + value: function cancel() { + // Pause our video + if (this.initialized) { + this.resumeContent(); + } // Tell our instance that we're done for now - case 240: - return 'small'; - default: - return 'default'; - } -} + this.trigger('error'); // Re-create our adsManager -function mapQualityUnits(levels) { - if (utils.is.empty(levels)) { - return levels; - } + this.loadAds(); + } + /** + * Re-create our adsManager + */ - return utils.dedupe(levels.map(function (level) { - return mapQualityUnit(level); - })); -} + }, { + key: "loadAds", + value: function loadAds() { + var _this10 = this; -var youtube = { - setup: function setup() { - var _this = this; + // Tell our adsManager to go bye bye + this.managerPromise.then(function () { + // Destroy our adsManager + if (_this10.manager) { + _this10.manager.destroy(); + } // Re-set our adsManager promises - // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); - // Set aspect ratio - youtube.setAspectRatio.call(this); + _this10.managerPromise = new Promise(function (resolve) { + _this10.on('loaded', resolve); - // Setup API - if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) { - youtube.ready.call(this); - } else { - // Load the API - utils.loadScript(this.config.urls.youtube.sdk).catch(function (error) { - _this.debug.warn('YouTube API failed to load', error); - }); + _this10.player.debug.log(_this10.manager); + }); // Now request some new advertisements - // Setup callback for the API - // YouTube has it's own system of course... - window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; + _this10.requestAds(); + }).catch(function () {}); + } + /** + * Handles callbacks after an ad event was invoked + * @param {string} event - Event type + */ - // Add to queue - window.onYouTubeReadyCallbacks.push(function () { - youtube.ready.call(_this); - }); + }, { + key: "trigger", + value: function trigger(event) { + var _this11 = this; - // Set callback to process queue - window.onYouTubeIframeAPIReady = function () { - window.onYouTubeReadyCallbacks.forEach(function (callback) { - callback(); - }); - }; + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; } - }, + var handlers = this.events[event]; - // Get the media title - getTitle: function getTitle(videoId) { - var _this2 = this; - - // Try via undocumented API method first - // This method disappears now and then though... - // https://github.com/sampotts/plyr/issues/709 - if (utils.is.function(this.embed.getVideoData)) { - var _embed$getVideoData = this.embed.getVideoData(), - title = _embed$getVideoData.title; - - if (utils.is.empty(title)) { - this.config.title = title; - ui.setTitle.call(this); - return; + if (is$1.array(handlers)) { + handlers.forEach(function (handler) { + if (is$1.function(handler)) { + handler.apply(_this11, args); } + }); } + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + * @return {Ads} + */ - // Or via Google API - var key = this.config.keys.google; - if (utils.is.string(key) && !utils.is.empty(key)) { - var url = utils.format(this.config.urls.youtube.api, videoId, key); - - utils.fetch(url).then(function (result) { - if (utils.is.object(result)) { - _this2.config.title = result.items[0].snippet.title; - ui.setTitle.call(_this2); - } - }).catch(function () {}); + }, { + key: "on", + value: function on$$1(event, callback) { + if (!is$1.array(this.events[event])) { + this.events[event] = []; } - }, + this.events[event].push(callback); + return this; + } + /** + * Setup a safety timer for when the ad network doesn't respond for whatever reason. + * The advertisement has 12 seconds to get its things together. We stop this timer when the + * advertisement is playing, or when a user action is required to start, then we clear the + * timer on ad ready + * @param {number} time + * @param {string} from + */ - // Set aspect ratio - setAspectRatio: function setAspectRatio() { - var ratio = this.config.ratio.split(':'); - this.elements.wrapper.style.paddingBottom = 100 / ratio[0] * ratio[1] + '%'; - }, + }, { + key: "startSafetyTimer", + value: function startSafetyTimer(time, from) { + var _this12 = this; + this.player.debug.log("Safety timer invoked from: ".concat(from)); + this.safetyTimer = setTimeout(function () { + _this12.cancel(); - // API ready - ready: function ready() { - var player = this; + _this12.clearSafetyTimer('startSafetyTimer()'); + }, time); + } + /** + * Clear our safety timer(s) + * @param {string} from + */ - // Ignore already setup (race condition) - var currentId = player.media.getAttribute('id'); - if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) { - return; + }, { + key: "clearSafetyTimer", + value: function clearSafetyTimer(from) { + if (!is$1.nullOrUndefined(this.safetyTimer)) { + this.player.debug.log("Safety timer cleared from: ".concat(from)); + clearTimeout(this.safetyTimer); + this.safetyTimer = null; } + } + }, { + key: "enabled", + get: function get() { + var config = this.config; + return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is$1.empty(config.publisherId) || is$1.url(config.tagUrl)); + } + }, { + key: "tagUrl", + get: function get() { + var config = this.config; + + if (is$1.url(config.tagUrl)) { + return config.tagUrl; + } + + var params = { + AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', + AV_CHANNELID: '5a0458dc28a06145e4519d21', + AV_URL: window.location.hostname, + cb: Date.now(), + AV_WIDTH: 640, + AV_HEIGHT: 480, + AV_CDIM2: this.publisherId + }; + var base = 'https://go.aniview.com/api/adserver6/vast/'; + return "".concat(base, "?").concat(buildUrlParams(params)); + } + }]); - // Get the source URL or ID - var source = player.media.getAttribute('src'); + return Ads; + }(); + + // 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined) + + var $find$1 = _arrayMethods(6); + var KEY$1 = 'findIndex'; + var forced$1 = true; + // Shouldn't skip holes + if (KEY$1 in []) Array(1)[KEY$1](function () { forced$1 = false; }); + _export(_export.P + _export.F * forced$1, 'Array', { + findIndex: function findIndex(callbackfn /* , that = undefined */) { + return $find$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + _addToUnscopables(KEY$1); + + var parseVtt = function parseVtt(vttDataString) { + var processedList = []; + var frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + frames.forEach(function (frame) { + var result = {}; + var lines = frame.split(/\r\n|\n|\r/); + lines.forEach(function (line) { + if (!is$1.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + var matchTimes = line.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = Number(matchTimes[1]) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number("0.".concat(matchTimes[4])); + result.endTime = Number(matchTimes[6]) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number("0.".concat(matchTimes[9])); + } + } else if (!is$1.empty(line.trim()) && is$1.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + var lineSplit = line.trim().split('#xywh='); - // Get from <div> if needed - if (utils.is.empty(source)) { - source = player.media.getAttribute(this.config.attributes.embed.id); - } + var _lineSplit = _slicedToArray(lineSplit, 1); - // Replace the <iframe> with a <div> due to YouTube API issues - var videoId = utils.parseYouTubeId(source); - var id = utils.generateId(player.provider); - var container = utils.createElement('div', { id: id }); - player.media = utils.replaceElement(container, player.media); - - // Set poster image - player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId)); - - // Setup instance - // https://developers.google.com/youtube/iframe_api_reference - player.embed = new window.YT.Player(id, { - videoId: videoId, - playerVars: { - autoplay: player.config.autoplay ? 1 : 0, // Autoplay - controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported - rel: 0, // No related vids - showinfo: 0, // Hide info - iv_load_policy: 3, // Hide annotations - modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) - disablekb: 1, // Disable keyboard as we handle it - playsinline: 1, // Allow iOS inline playback - - // Tracking for stats - // origin: window ? `${window.location.protocol}//${window.location.host}` : null, - widget_referrer: window ? window.location.href : null, - - // Captions are flaky on YouTube - cc_load_policy: player.captions.active ? 1 : 0, - cc_lang_pref: player.config.captions.language - }, - events: { - onError: function onError(event) { - // If we've already fired an error, don't do it again - // YouTube fires onError twice - if (utils.is.object(player.media.error)) { - return; - } - - var detail = { - code: event.data - }; + result.text = _lineSplit[0]; - // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError - switch (event.data) { - case 2: - detail.message = 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.'; - break; - - case 5: - detail.message = 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.'; - break; - - case 100: - detail.message = 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.'; - break; - - case 101: - case 150: - detail.message = 'The owner of the requested video does not allow it to be played in embedded players.'; - break; - - default: - detail.message = 'An unknown error occured'; - break; - } - - player.media.error = detail; - - utils.dispatchEvent.call(player, player.media, 'error'); - }, - onPlaybackQualityChange: function onPlaybackQualityChange() { - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { - quality: player.media.quality - }); - }, - onPlaybackRateChange: function onPlaybackRateChange(event) { - // Get the instance - var instance = event.target; - - // Get current speed - player.media.playbackRate = instance.getPlaybackRate(); - - utils.dispatchEvent.call(player, player.media, 'ratechange'); - }, - onReady: function onReady(event) { - // Get the instance - var instance = event.target; - - // Get the title - youtube.getTitle.call(player, videoId); - - // Create a faux HTML5 API using the YouTube API - player.media.play = function () { - instance.playVideo(); - }; + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + var _lineSplit$1$split = lineSplit[1].split(','); - player.media.pause = function () { - instance.pauseVideo(); - }; + var _lineSplit$1$split2 = _slicedToArray(_lineSplit$1$split, 4); - player.media.stop = function () { - instance.stopVideo(); - }; + result.x = _lineSplit$1$split2[0]; + result.y = _lineSplit$1$split2[1]; + result.w = _lineSplit$1$split2[2]; + result.h = _lineSplit$1$split2[3]; + } + } + }); - player.media.duration = instance.getDuration(); - player.media.paused = true; - - // Seeking - player.media.currentTime = 0; - Object.defineProperty(player.media, 'currentTime', { - get: function get() { - return Number(instance.getCurrentTime()); - }, - set: function set(time) { - // Vimeo will automatically play on seek - var paused = player.media.paused; - - // Set seeking flag - - player.media.seeking = true; - - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); - - // Seek after events sent - instance.seekTo(time); - - // Restore pause state - if (paused) { - player.pause(); - } - } - }); - - // Playback speed - Object.defineProperty(player.media, 'playbackRate', { - get: function get() { - return instance.getPlaybackRate(); - }, - set: function set(input) { - instance.setPlaybackRate(input); - } - }); - - // Quality - Object.defineProperty(player.media, 'quality', { - get: function get() { - return mapQualityUnit(instance.getPlaybackQuality()); - }, - set: function set(input) { - var quality = input; - - // Set via API - instance.setPlaybackQuality(mapQualityUnit(quality)); - - // Trigger request event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality: quality - }); - } - }); - - // Volume - var volume = player.config.volume; - - Object.defineProperty(player.media, 'volume', { - get: function get() { - return volume; - }, - set: function set(input) { - volume = input; - instance.setVolume(volume * 100); - utils.dispatchEvent.call(player, player.media, 'volumechange'); - } - }); - - // Muted - var muted = player.config.muted; - - Object.defineProperty(player.media, 'muted', { - get: function get() { - return muted; - }, - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : muted; - muted = toggle; - instance[toggle ? 'mute' : 'unMute'](); - utils.dispatchEvent.call(player, player.media, 'volumechange'); - } - }); - - // Source - Object.defineProperty(player.media, 'currentSrc', { - get: function get() { - return instance.getVideoUrl(); - } - }); - - // Ended - Object.defineProperty(player.media, 'ended', { - get: function get() { - return player.currentTime === player.duration; - } - }); - - // Get available speeds - player.options.speed = instance.getAvailablePlaybackRates(); - - // Set the tabindex to avoid focus entering iframe - if (player.supported.ui) { - player.media.setAttribute('tabindex', -1); - } - - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - utils.dispatchEvent.call(player, player.media, 'durationchange'); - - // Reset timer - clearInterval(player.timers.buffering); - - // Setup buffering - player.timers.buffering = setInterval(function () { - // Get loaded % from YouTube - player.media.buffered = instance.getVideoLoadedFraction(); - - // Trigger progress only when we actually buffer something - if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { - utils.dispatchEvent.call(player, player.media, 'progress'); - } - - // Set last buffer point - player.media.lastBuffered = player.media.buffered; - - // Bail if we're at 100% - if (player.media.buffered === 1) { - clearInterval(player.timers.buffering); - - // Trigger event - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); - } - }, 200); - - // Rebuild UI - setTimeout(function () { - return ui.build.call(player); - }, 50); - }, - onStateChange: function onStateChange(event) { - // Get the instance - var instance = event.target; - - // Reset timer - clearInterval(player.timers.playing); - - // Handle events - // -1 Unstarted - // 0 Ended - // 1 Playing - // 2 Paused - // 3 Buffering - // 5 Video cued - switch (event.data) { - case -1: - // Update scrubber - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - - // Get loaded % from YouTube - player.media.buffered = instance.getVideoLoadedFraction(); - utils.dispatchEvent.call(player, player.media, 'progress'); - - break; - - case 0: - player.media.paused = true; - - // YouTube doesn't support loop for a single video, so mimick it. - if (player.media.loop) { - // YouTube needs a call to `stopVideo` before playing again - instance.stopVideo(); - instance.playVideo(); - } else { - utils.dispatchEvent.call(player, player.media, 'ended'); - } - - break; - - case 1: - // If we were seeking, fire seeked event - if (player.media.seeking) { - utils.dispatchEvent.call(player, player.media, 'seeked'); - } - player.media.seeking = false; - - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - - utils.dispatchEvent.call(player, player.media, 'playing'); - - // Poll to get playback progress - player.timers.playing = setInterval(function () { - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }, 50); - - // Check duration again due to YouTube bug - // https://github.com/sampotts/plyr/issues/374 - // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - if (player.media.duration !== instance.getDuration()) { - player.media.duration = instance.getDuration(); - utils.dispatchEvent.call(player, player.media, 'durationchange'); - } - - // Get quality - controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels())); - - break; - - case 2: - player.media.paused = true; - - utils.dispatchEvent.call(player, player.media, 'pause'); - - break; - - default: - break; - } - - utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, { - code: event.data - }); - } - } - }); + if (result.text) { + processedList.push(result); + } + }); + return processedList; + }; + /** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + + + var PreviewThumbnails = + /*#__PURE__*/ + function () { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + function PreviewThumbnails(player) { + _classCallCheck(this, PreviewThumbnails); + + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + this.elements = { + thumb: {}, + scrubbing: {} + }; + this.load(); } -}; -// ========================================================================== + _createClass(PreviewThumbnails, [{ + key: "load", + value: function load() { + var _this = this; -var media = { - // Setup media - setup: function setup() { - // If there's no media, bail - if (!this.media) { - this.debug.warn('No media element found!'); - return; + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; } - // Add type class - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); - - // Add provider class - utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); - - // Add video class for embeds - // This will require changes if audio embeds are added - if (this.isEmbed) { - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + if (!this.enabled) { + return; } - // Inject the player wrapper - if (this.isVideo) { - // Create the wrapper div - this.elements.wrapper = utils.createElement('div', { - class: this.config.classNames.video - }); + this.getThumbnails().then(function () { + // Render DOM elements + _this.render(); // Check to see if thumb container size was specified manually in CSS - // Wrap the video in a container - utils.wrap(this.media, this.elements.wrapper); - // Faux poster container - this.elements.poster = utils.createElement('div', { - class: this.config.classNames.poster - }); + _this.determineContainerAutoSizing(); - this.elements.wrapper.appendChild(this.elements.poster); - } + _this.loaded = true; + }); + } // Download VTT files and parse them - if (this.isEmbed) { - switch (this.provider) { - case 'youtube': - youtube.setup.call(this); - break; + }, { + key: "getThumbnails", + value: function getThumbnails() { + var _this2 = this; - case 'vimeo': - vimeo.setup.call(this); - break; + return new Promise(function (resolve) { + var src = _this2.player.config.previewThumbnails.src; - default: - break; - } - } else if (this.isHTML5) { - html5.extend.call(this); - } - } -}; + if (is$1.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } // If string, convert into single-element list -// ========================================================================== -var Ads = function () { - /** - * Ads constructor. - * @param {object} player - * @return {Ads} - */ - function Ads(player) { - var _this = this; + var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails - classCallCheck(this, Ads); + var promises = urls.map(function (u) { + return _this2.getThumbnail(u); + }); + Promise.all(promises).then(function () { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + _this2.thumbnails.sort(function (x, y) { + return x.height - y.height; + }); - this.player = player; - this.publisherId = player.config.ads.publisherId; - this.playing = false; - this.initialized = false; - this.elements = { - container: null, - displayContainer: null - }; - this.manager = null; - this.loader = null; - this.cuePoints = null; - this.events = {}; - this.safetyTimer = null; - this.countdownTimer = null; - - // Setup a promise to resolve when the IMA manager is ready - this.managerPromise = new Promise(function (resolve, reject) { - // The ad is loaded and ready - _this.on('loaded', resolve); - - // Ads failed - _this.on('error', reject); - }); + _this2.player.debug.log('Preview thumbnails', _this2.thumbnails); - this.load(); - } + resolve(); + }); + }); + } // Process individual VTT file - createClass(Ads, [{ - key: 'load', - - - /** - * Load the IMA SDK - */ - value: function load() { - var _this2 = this; - - if (this.enabled) { - // Check if the Google IMA3 SDK is loaded or load it ourselves - if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) { - utils.loadScript(this.player.config.urls.googleIMA.sdk).then(function () { - _this2.ready(); - }).catch(function () { - // Script failed to load or is blocked - _this2.trigger('error', new Error('Google IMA SDK failed to load')); - }); - } else { - this.ready(); - } - } - } + }, { + key: "getThumbnail", + value: function getThumbnail(url) { + var _this3 = this; - /** - * Get the ads instance ready - */ + return new Promise(function (resolve) { + fetch(url).then(function (response) { + var thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '' + }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank - }, { - key: 'ready', - value: function ready() { - var _this3 = this; + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } // Download the first frame, so that we can determine/set the height of this thumbnailsDef - // Start ticking our safety timer. If the whole advertisement - // thing doesn't resolve within our set time; we bail - this.startSafetyTimer(12000, 'ready()'); - // Clear the safety timer - this.managerPromise.then(function () { - _this3.clearSafetyTimer('onAdsManagerLoaded()'); - }); + var tempImage = new Image(); - // Set listeners on the Plyr instance - this.listeners(); + tempImage.onload = function () { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; - // Setup the IMA SDK - this.setupIMA(); - } + _this3.thumbnails.push(thumbnail); - // Build the default tag URL + resolve(); + }; + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } }, { - key: 'setupIMA', - - - /** - * In order for the SDK to display ads for our video, we need to tell it where to put them, - * so here we define our ad container. This div is set up to render on top of the video player. - * Using the code below, we tell the SDK to render ads within that div. We also provide a - * handle to the content video player - the SDK will poll the current time of our player to - * properly place mid-rolls. After we create the ad display container, we initialize it. On - * mobile devices, this initialization is done as the result of a user action. - */ - value: function setupIMA() { - // Create the container for our advertisements - this.elements.container = utils.createElement('div', { - class: this.player.config.classNames.ads - }); - this.player.elements.container.appendChild(this.elements.container); - - // So we can run VPAID2 - google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); + key: "startMove", + value: function startMove(event) { + if (!this.loaded) { + return; + } - // Set language - google.ima.settings.setLocale(this.player.config.ads.language); + if (!is$1.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } // Wait until media has a duration - // We assume the adContainer is the video container of the plyr element - // that will house the ads - this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); - // Request video ads to be pre-loaded - this.requestAds(); + if (!this.player.media.duration) { + return; } - /** - * Request advertisements - */ - - }, { - key: 'requestAds', - value: function requestAds() { - var _this4 = this; + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + var clientRect = this.player.elements.progress.getBoundingClientRect(); + var percentage = 100 / clientRect.width * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); + + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } - var container = this.player.elements.container; + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } + this.mousePosX = event.pageX; // Set time text inside image container - try { - // Create ads loader - this.loader = new google.ima.AdsLoader(this.elements.displayContainer); - - // Listen and respond to ads loaded and error events - this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { - return _this4.onAdsManagerLoaded(event); - }, false); - this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { - return _this4.onAdError(error); - }, false); - - // Request video ads - var request = new google.ima.AdsRequest(); - request.adTagUrl = this.tagUrl; - - // Specify the linear and nonlinear slot sizes. This helps the SDK - // to select the correct creative if multiple are returned - request.linearAdSlotWidth = container.offsetWidth; - request.linearAdSlotHeight = container.offsetHeight; - request.nonLinearAdSlotWidth = container.offsetWidth; - request.nonLinearAdSlotHeight = container.offsetHeight; - - // We only overlay ads as we only support video. - request.forceNonLinearFullSlot = false; - - // Mute based on current state - request.setAdWillPlayMuted(!this.player.muted); - - this.loader.requestAds(request); - } catch (e) { - this.onAdError(e); - } - } + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } // Download and show image - /** - * Update the ad countdown - * @param {boolean} start - */ + this.showImageAtCurrentTime(); + } + }, { + key: "endMove", + value: function endMove() { + this.toggleThumbContainer(false, true); + } }, { - key: 'pollCountdown', - value: function pollCountdown() { - var _this5 = this; + key: "startScrubbing", + value: function startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; // Wait until media has a duration - var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); // Download and show image - if (!start) { - clearInterval(this.countdownTimer); - this.elements.container.removeAttribute('data-badge-text'); - return; - } + this.showImageAtCurrentTime(); + } + } + } + }, { + key: "finishScrubbing", + value: function finishScrubbing() { + var _this4 = this; - var update = function update() { - var time = utils.formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); - var label = i18n.get('advertisement', _this5.player.config) + ' - ' + time; - _this5.elements.container.setAttribute('data-badge-text', label); - }; + this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview - this.countdownTimer = setInterval(update, 100); + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', function () { + // Re-check mousedown - we might have already started scrubbing again + if (!_this4.mouseDown) { + _this4.toggleScrubbingContainer(false); + } + }); } - - /** - * This method is called whenever the ads are ready inside the AdDisplayContainer - * @param {Event} adsManagerLoadedEvent - */ + } + /** + * Setup hooks for Plyr and window events + */ }, { - key: 'onAdsManagerLoaded', - value: function onAdsManagerLoaded(event) { - var _this6 = this; - - // Get the ads manager - var settings = new google.ima.AdsRenderingSettings(); - - // Tell the SDK to save and restore content video state on our behalf - settings.restoreCustomPlaybackStateOnAdBreakComplete = true; - settings.enablePreloading = true; - - // The SDK is polling currentTime on the contentPlayback. And needs a duration - // so it can determine when to start the mid- and post-roll - this.manager = event.getAdsManager(this.player, settings); - - // Get the cue points for any mid-rolls by filtering out the pre- and post-roll - this.cuePoints = this.manager.getCuePoints(); - - // Add advertisement cue's within the time line if available - if (!utils.is.empty(this.cuePoints)) { - this.cuePoints.forEach(function (cuePoint) { - if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { - var seekElement = _this6.player.elements.progress; - - if (utils.is.element(seekElement)) { - var cuePercentage = 100 / _this6.player.duration * cuePoint; - var cue = utils.createElement('span', { - class: _this6.player.config.classNames.cues - }); - - cue.style.left = cuePercentage.toString() + '%'; - seekElement.appendChild(cue); - } - } - }); - } + key: "listeners", + value: function listeners() { + var _this5 = this; - // Get skippable state - // TODO: Skip button - // this.player.debug.warn(this.manager.getAdSkippableState()); + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', function () { + _this5.toggleThumbContainer(false, true); + }); + this.player.on('seeked', function () { + _this5.toggleThumbContainer(false); + }); + this.player.on('timeupdate', function () { + _this5.lastTime = _this5.player.media.currentTime; + }); + } + /** + * Create HTML elements for image containers + */ - // Set volume to match player - this.manager.setVolume(this.player.volume); + }, { + key: "render", + value: function render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer + }); // Wrapper for the image for styling + + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00) - // Add listeners to the required events - // Advertisement error events - this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { - return _this6.onAdError(error); - }); + var timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer + }); + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb - // Advertisement regular events - Object.keys(google.ima.AdEvent.Type).forEach(function (type) { - _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { - return _this6.onAdEvent(event); - }); - }); + this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container - // Resolve our adsManager - this.trigger('loaded'); - } + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer + }); + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + }, { + key: "showImageAtCurrentTime", + value: function showImageAtCurrentTime() { + var _this6 = this; - /** - * This is where all the event handling takes place. Retrieve the ad from the event. Some - * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated - * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type - * @param {Event} event - */ + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null - }, { - key: 'onAdEvent', - value: function onAdEvent(event) { - var _this7 = this; - var container = this.player.elements.container; + var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) { + return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime; + }); + var hasThumb = thumbNum >= 0; + var qualityIndex = 0; + this.toggleThumbContainer(hasThumb); // No matching thumb found - // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) - // don't have ad object associated + if (!hasThumb) { + return; + } // Check to see if we've already downloaded higher quality versions of this image - var ad = event.getAd(); - // Proxy event - var dispatchEvent = function dispatchEvent(type) { - var event = 'ads' + type.replace(/_/g, '').toLowerCase(); - utils.dispatchEvent.call(_this7.player, _this7.player.media, event); - }; + this.thumbnails.forEach(function (thumbnail, index) { + if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); // Only proceed if either thumbnum or thumbfilename has changed - switch (event.type) { - case google.ima.AdEvent.Type.LOADED: - // This is the first event sent for an ad - it is possible to determine whether the - // ad is a video ad or an overlay - this.trigger('loaded'); - - // Bubble event - dispatchEvent(event.type); - - // Start countdown - this.pollCountdown(true); - - if (!ad.isLinear()) { - // Position AdDisplayContainer correctly for overlay - ad.width = container.offsetWidth; - ad.height = container.offsetHeight; - } - - // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); - // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); - break; - - case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: - // All ads for the current videos are done. We can now request new advertisements - // in case the video is re-played - - // Fire event - dispatchEvent(event.type); - - // TODO: Example for what happens when a next video in a playlist would be loaded. - // So here we load a new video when all ads are done. - // Then we load new ads within a new adsManager. When the video - // Is started - after - the ads are loaded, then we get ads. - // You can also easily test cancelling and reloading by running - // player.ads.cancel() and player.ads.play from the console I guess. - // this.player.source = { - // type: 'video', - // title: 'View From A Blue Moon', - // sources: [{ - // src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: - // 'video/mp4', }], poster: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: - // [ { kind: 'captions', label: 'English', srclang: 'en', src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', - // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: - // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], - // }; - - // TODO: So there is still this thing where a video should only be allowed to start - // playing when the IMA SDK is ready or has failed - - this.loadAds(); - break; - - case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: - // This event indicates the ad has started - the video player can adjust the UI, - // for example display a pause button and remaining time. Fired when content should - // be paused. This usually happens right before an ad is about to cover the content - - dispatchEvent(event.type); - - this.pauseContent(); - - break; - - case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: - // This event indicates the ad has finished - the video player can perform - // appropriate UI actions, such as removing the timer for remaining time detection. - // Fired when content should be resumed. This usually happens when an ad finishes - // or collapses - - dispatchEvent(event.type); - - this.pollCountdown(); - - this.resumeContent(); - - break; - - case google.ima.AdEvent.Type.STARTED: - case google.ima.AdEvent.Type.MIDPOINT: - case google.ima.AdEvent.Type.COMPLETE: - case google.ima.AdEvent.Type.IMPRESSION: - case google.ima.AdEvent.Type.CLICK: - dispatchEvent(event.type); - break; - - default: - break; - } + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); } - - /** - * Any ad error handling comes through here - * @param {Event} event - */ + } // Show the image that's currently specified in this.showingThumb }, { - key: 'onAdError', - value: function onAdError(event) { - this.cancel(); - this.player.debug.warn('Ads error', event); + key: "loadImage", + value: function loadImage() { + var _this7 = this; + + var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var thumbNum = this.showingThumb; + var thumbnail = this.thumbnails[qualityIndex]; + var urlPrefix = thumbnail.urlPrefix; + var frame = thumbnail.frames[thumbNum]; + var thumbFilename = thumbnail.frames[thumbNum].text; + var thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + + + var previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + + previewImage.onload = function () { + return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + }; + + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); } + } + }, { + key: "showImage", + value: function showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename) { + var newImage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this.player.debug.log("Showing thumb: ".concat(thumbFilename, ". num: ").concat(thumbNum, ". qual: ").concat(qualityIndex, ". newimg: ").concat(newImage)); + this.setImageSizeAndOffset(previewImage, frame); + + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; + + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading - /** - * Setup hooks for Plyr and window events. This ensures - * the mid- and post-roll launch at the correct time. And - * resize the advertisement when the player resizes - */ + + this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } // Remove all preview images that aren't the designated current image }, { - key: 'listeners', - value: function listeners() { - var _this8 = this; + key: "removeOldImages", + value: function removeOldImages(currentImage) { + var _this8 = this; - var container = this.player.elements.container; + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(function (image) { + if (image.tagName.toLowerCase() !== 'img') { + return; + } - var time = void 0; + var removeDelay = _this8.usingSprites ? 500 : 1000; - // Add listeners to the required events - this.player.on('ended', function () { - _this8.loader.contentComplete(); - }); + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub - this.player.on('seeking', function () { - time = _this8.player.currentTime; - return time; - }); - - this.player.on('seeked', function () { - var seekedTime = _this8.player.currentTime; + var currentImageContainer = _this8.currentImageContainer; + setTimeout(function () { + currentImageContainer.removeChild(image); - if (utils.is.empty(_this8.cuePoints)) { - return; - } + _this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename)); + }, removeDelay); + } + }); + } // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality - _this8.cuePoints.forEach(function (cuePoint, index) { - if (time < cuePoint && cuePoint < seekedTime) { - _this8.manager.discardAdBreak(); - _this8.cuePoints.splice(index, 1); - } - }); - }); + }, { + key: "preloadNearby", + value: function preloadNearby(thumbNum) { + var _this9 = this; - // Listen to the resizing of the window. And resize ad accordingly - // TODO: eventually implement ResizeObserver - window.addEventListener('resize', function () { - if (_this8.manager) { - _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); - } - }); - } + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return new Promise(function (resolve) { + setTimeout(function () { + var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text; - /** - * Initialize the adsManager and start playing advertisements - */ + if (_this9.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + var thumbnailsClone; - }, { - key: 'play', - value: function play() { - var _this9 = this; + if (forward) { + thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } - var container = this.player.elements.container; + var foundOne = false; + thumbnailsClone.forEach(function (frame) { + var newThumbFilename = frame.text; + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!_this9.loadedImages.includes(newThumbFilename)) { + foundOne = true; - if (!this.managerPromise) { - this.resumeContent(); - } + _this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename)); - // Play the requested advertisement whenever the adsManager is ready - this.managerPromise.then(function () { - // Initialize the container. Must be done via a user action on mobile devices - _this9.elements.displayContainer.initialize(); - - try { - if (!_this9.initialized) { - // Initialize the ads manager. Ad rules playlist will start at this time - _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); - - // Call play to start showing the ad. Single video and overlay ads will - // start at this time; the call will be ignored for ad rules - _this9.manager.start(); - } - - _this9.initialized = true; - } catch (adError) { - // An error may be thrown if there was a problem with the - // VAST response - _this9.onAdError(adError); - } - }).catch(function () {}); - } + var urlPrefix = _this9.thumbnails[0].urlPrefix; + var thumbURL = urlPrefix + newThumbFilename; + var previewImage = new Image(); + previewImage.src = thumbURL; - /** - * Resume our video - */ + previewImage.onload = function () { + _this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename)); - }, { - key: 'resumeContent', - value: function resumeContent() { - // Hide the advertisement container - this.elements.container.style.zIndex = ''; + if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded - // Ad is stopped - this.playing = false; + resolve(); + }; + } + } + }); // If there are none to preload then we want to resolve immediately - // Play our video - if (this.player.currentTime < this.player.duration) { - this.player.play(); + if (!foundOne) { + resolve(); + } } - } - - /** - * Pause our video - */ + }, 300); + }); + } // If user has been hovering current image for half a second, look for a higher quality one }, { - key: 'pauseContent', - value: function pauseContent() { - // Show the advertisement container - this.elements.container.style.zIndex = 3; + key: "getHigherQuality", + value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + var _this10 = this; - // Ad is playing. - this.playing = true; + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + var previewImageHeight = previewImage.naturalHeight; - // Pause our video. - this.player.pause(); - } + if (this.usingSprites) { + previewImageHeight = frame.h; + } - /** - * Destroy the adsManager so we can grab new ads after this. If we don't then we're not - * allowed to call new ads based on google policies, as they interpret this as an accidental - * video requests. https://developers.google.com/interactive- - * media-ads/docs/sdks/android/faq#8 - */ + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(function () { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (_this10.showingThumbFilename === thumbFilename) { + _this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename)); + _this10.loadImage(currentQualityIndex + 1); + } + }, 300); + } + } + } }, { - key: 'cancel', - value: function cancel() { - // Pause our video - if (this.initialized) { - this.resumeContent(); - } - - // Tell our instance that we're done for now - this.trigger('error'); + key: "toggleThumbContainer", + value: function toggleThumbContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var clearShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); - // Re-create our adsManager - this.loadAds(); + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; } - - /** - * Re-create our adsManager - */ - + } }, { - key: 'loadAds', - value: function loadAds() { - var _this10 = this; - - // Tell our adsManager to go bye bye - this.managerPromise.then(function () { - // Destroy our adsManager - if (_this10.manager) { - _this10.manager.destroy(); - } - - // Re-set our adsManager promises - _this10.managerPromise = new Promise(function (resolve) { - _this10.on('loaded', resolve); - _this10.player.debug.log(_this10.manager); - }); + key: "toggleScrubbingContainer", + value: function toggleScrubbingContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); - // Now request some new advertisements - _this10.requestAds(); - }).catch(function () {}); + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; } + } + }, { + key: "determineContainerAutoSizing", + value: function determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS - /** - * Handles callbacks after an ad event was invoked - * @param {string} event - Event type - */ + }, { + key: "setThumbContainerSizeAndPos", + value: function setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px"); + this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px"); + } + this.setThumbContainerPos(); + } }, { - key: 'trigger', - value: function trigger(event) { - var _this11 = this; + key: "setThumbContainerPos", + value: function setThumbContainerPos() { + var seekbarRect = this.player.elements.progress.getBoundingClientRect(); + var plyrRect = this.player.elements.container.getBoundingClientRect(); + var container = this.elements.thumb.container; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + var minVal = plyrRect.left - seekbarRect.left + 10; + var maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth - var handlers = this.events[event]; + var previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; - if (utils.is.array(handlers)) { - handlers.forEach(function (handler) { - if (utils.is.function(handler)) { - handler.apply(_this11, args); - } - }); - } + if (previewPos < minVal) { + previewPos = minVal; } - /** - * Add event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - * @return {Ads} - */ - - }, { - key: 'on', - value: function on(event, callback) { - if (!utils.is.array(this.events[event])) { - this.events[event] = []; - } - - this.events[event].push(callback); - - return this; + if (previewPos > maxVal) { + previewPos = maxVal; } - /** - * Setup a safety timer for when the ad network doesn't respond for whatever reason. - * The advertisement has 12 seconds to get its things together. We stop this timer when the - * advertisement is playing, or when a user action is required to start, then we clear the - * timer on ad ready - * @param {number} time - * @param {string} from - */ + container.style.left = "".concat(previewPos, "px"); + } // Can't use 100% width, in case the video is a different aspect ratio to the video container }, { - key: 'startSafetyTimer', - value: function startSafetyTimer(time, from) { - var _this12 = this; + key: "setScrubbingContainerSize", + value: function setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below - this.player.debug.log('Safety timer invoked from: ' + from); + this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px"); + } // Sprites need to be offset to the correct location - this.safetyTimer = setTimeout(function () { - _this12.cancel(); - _this12.clearSafetyTimer('startSafetyTimer()'); - }, time); + }, { + key: "setImageSizeAndOffset", + value: function setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } // Find difference between height and preview container height + + + var multiplier = this.thumbContainerHeight / frame.h; + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); + } + }, { + key: "enabled", + get: function get() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + }, { + key: "currentImageContainer", + get: function get() { + if (this.mouseDown) { + return this.elements.scrubbing.container; } - /** - * Clear our safety timer(s) - * @param {string} from - */ - + return this.elements.thumb.imageContainer; + } }, { - key: 'clearSafetyTimer', - value: function clearSafetyTimer(from) { - if (!utils.is.nullOrUndefined(this.safetyTimer)) { - this.player.debug.log('Safety timer cleared from: ' + from); - - clearTimeout(this.safetyTimer); - this.safetyTimer = null; - } - } + key: "usingSprites", + get: function get() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } }, { - key: 'enabled', - get: function get() { - return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId); + key: "thumbAspectRatio", + get: function get() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; } + + return this.thumbnails[0].width / this.thumbnails[0].height; + } }, { - key: 'tagUrl', - get: function get() { - var params = { - AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', - AV_CHANNELID: '5a0458dc28a06145e4519d21', - AV_URL: location.hostname, - cb: Date.now(), - AV_WIDTH: 640, - AV_HEIGHT: 480, - AV_CDIM2: this.publisherId - }; + key: "thumbContainerHeight", + get: function get() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); + } - var base = 'https://go.aniview.com/api/adserver6/vast/'; + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + }, { + key: "currentImageElement", + get: function get() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } - return base + '?' + utils.buildUrlParams(params); + return this.currentThumbnailImageElement; + }, + set: function set(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; } + } }]); - return Ads; -}(); -// ========================================================================== + return PreviewThumbnails; + }(); -var source = { + var source = { // Add elements to HTML5 media (source, tracks, etc) insertElements: function insertElements(type, attributes) { - var _this = this; + var _this = this; - if (utils.is.string(attributes)) { - utils.insertElement(type, this.media, { - src: attributes - }); - } else if (utils.is.array(attributes)) { - attributes.forEach(function (attribute) { - utils.insertElement(type, _this.media, attribute); - }); - } + if (is$1.string(attributes)) { + insertElement(type, this.media, { + src: attributes + }); + } else if (is$1.array(attributes)) { + attributes.forEach(function (attribute) { + insertElement(type, _this.media, attribute); + }); + } }, - - // Update source // Sources are not checked for support so be careful change: function change(input) { - var _this2 = this; + var _this2 = this; - if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) { - this.debug.warn('Invalid source format'); - return; - } + if (!getDeep(input, 'sources.length')) { + this.debug.warn('Invalid source format'); + return; + } // Cancel current network requests - // Cancel current network requests - html5.cancelRequests.call(this); - // Destroy instance and re-setup - this.destroy.call(this, function () { - // Reset quality options - _this2.options.quality = []; + html5.cancelRequests.call(this); // Destroy instance and re-setup - // Remove elements - utils.removeElement(_this2.media); - _this2.media = null; + this.destroy.call(this, function () { + // Reset quality options + _this2.options.quality = []; // Remove elements - // Reset class name - if (utils.is.element(_this2.elements.container)) { - _this2.elements.container.removeAttribute('class'); - } + removeElement(_this2.media); + _this2.media = null; // Reset class name - // Set the type and provider - _this2.type = input.type; - _this2.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5; + if (is$1.element(_this2.elements.container)) { + _this2.elements.container.removeAttribute('class'); + } // Set the type and provider - // Check for support - _this2.supported = support.check(_this2.type, _this2.provider, _this2.config.playsinline); - // Create new markup - switch (_this2.provider + ':' + _this2.type) { - case 'html5:video': - _this2.media = utils.createElement('video'); - break; + var sources = input.sources, + type = input.type; - case 'html5:audio': - _this2.media = utils.createElement('audio'); - break; + var _sources = _slicedToArray(sources, 1), + _sources$ = _sources[0], + _sources$$provider = _sources$.provider, + provider = _sources$$provider === void 0 ? providers.html5 : _sources$$provider, + src = _sources$.src; - case 'youtube:video': - case 'vimeo:video': - _this2.media = utils.createElement('div', { - src: input.sources[0].src - }); - break; + var tagName = provider === 'html5' ? type : 'div'; + var attributes = provider === 'html5' ? {} : { + src: src + }; + Object.assign(_this2, { + provider: provider, + type: type, + // Check for support + supported: support.check(type, provider, _this2.config.playsinline), + // Create new element + media: createElement(tagName, attributes) + }); // Inject the new element - default: - break; - } + _this2.elements.container.appendChild(_this2.media); // Autoplay the new source? - // Inject the new element - _this2.elements.container.appendChild(_this2.media); - // Autoplay the new source? - if (utils.is.boolean(input.autoplay)) { - _this2.config.autoplay = input.autoplay; - } + if (is$1.boolean(input.autoplay)) { + _this2.config.autoplay = input.autoplay; + } // Set attributes for audio and video - // Set attributes for audio and video - if (_this2.isHTML5) { - if (_this2.config.crossorigin) { - _this2.media.setAttribute('crossorigin', ''); - } - if (_this2.config.autoplay) { - _this2.media.setAttribute('autoplay', ''); - } - if (!utils.is.empty(input.poster)) { - _this2.poster = input.poster; - } - if (_this2.config.loop.active) { - _this2.media.setAttribute('loop', ''); - } - if (_this2.config.muted) { - _this2.media.setAttribute('muted', ''); - } - if (_this2.config.playsinline) { - _this2.media.setAttribute('playsinline', ''); - } - } - - // Restore class hook - ui.addStyleHook.call(_this2); - - // Set new sources for html5 - if (_this2.isHTML5) { - source.insertElements.call(_this2, 'source', input.sources); - } - // Set video title - _this2.config.title = input.title; - - // Set up from scratch - media.setup.call(_this2); + if (_this2.isHTML5) { + if (_this2.config.crossorigin) { + _this2.media.setAttribute('crossorigin', ''); + } - // HTML5 stuff - if (_this2.isHTML5) { - // Setup captions - if ('tracks' in input) { - source.insertElements.call(_this2, 'track', input.tracks); - } + if (_this2.config.autoplay) { + _this2.media.setAttribute('autoplay', ''); + } - // Load HTML5 sources - _this2.media.load(); - } + if (!is$1.empty(input.poster)) { + _this2.poster = input.poster; + } - // If HTML5 or embed but not fully supported, setupInterface and call ready now - if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { - // Setup interface - ui.build.call(_this2); - } + if (_this2.config.loop.active) { + _this2.media.setAttribute('loop', ''); + } - // Update the fullscreen support - _this2.fullscreen.update(); - }, true); - } -}; + if (_this2.config.muted) { + _this2.media.setAttribute('muted', ''); + } -// ========================================================================== + if (_this2.config.playsinline) { + _this2.media.setAttribute('playsinline', ''); + } + } // Restore class hook -var Storage = function () { - function Storage(player) { - classCallCheck(this, Storage); - this.enabled = player.config.storage.enabled; - this.key = player.config.storage.key; - } + ui.addStyleHook.call(_this2); // Set new sources for html5 - // Check for actual support (see if we can use it) + if (_this2.isHTML5) { + source.insertElements.call(_this2, 'source', sources); + } // Set video title - createClass(Storage, [{ - key: 'get', - value: function get(key) { - if (!Storage.supported) { - return null; - } + _this2.config.title = input.title; // Set up from scratch - var store = window.localStorage.getItem(this.key); + media.setup.call(_this2); // HTML5 stuff - if (utils.is.empty(store)) { - return null; - } + if (_this2.isHTML5) { + // Setup captions + if (Object.keys(input).includes('tracks')) { + source.insertElements.call(_this2, 'track', input.tracks); + } + } // If HTML5 or embed but not fully supported, setupInterface and call ready now - var json = JSON.parse(store); - return utils.is.string(key) && key.length ? json[key] : json; - } - }, { - key: 'set', - value: function set(object) { - // Bail if we don't have localStorage support or it's disabled - if (!Storage.supported || !this.enabled) { - return; - } + if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { + // Setup interface + ui.build.call(_this2); + } // Load HTML5 sources - // Can only store objectst - if (!utils.is.object(object)) { - return; - } - // Get current storage - var storage = this.get(); + if (_this2.isHTML5) { + _this2.media.load(); + } // Reload thumbnails - // Default to empty object - if (utils.is.empty(storage)) { - storage = {}; - } - // Update the working copy of the values - utils.extend(storage, object); + if (_this2.previewThumbnails) { + _this2.previewThumbnails.load(); + } // Update the fullscreen support - // Update storage - window.localStorage.setItem(this.key, JSON.stringify(storage)); - } - }], [{ - key: 'supported', - get: function get() { - try { - if (!('localStorage' in window)) { - return false; - } - var test = '___test'; + _this2.fullscreen.update(); + }, true); + } + }; - // Try to use it (it might be disabled, e.g. user is in private mode) - // see: https://github.com/sampotts/plyr/issues/131 - window.localStorage.setItem(test, test); - window.localStorage.removeItem(test); + // TODO: Use a WeakMap for private globals + // const globals = new WeakMap(); + // Plyr instance - return true; - } catch (e) { - return false; - } - } - }]); - return Storage; -}(); + var Plyr = + /*#__PURE__*/ + function () { + function Plyr(target, options) { + var _this = this; -// ========================================================================== + _classCallCheck(this, Plyr); -// Private properties -// TODO: Use a WeakMap for private globals -// const globals = new WeakMap(); + this.timers = {}; // State -// Plyr instance + this.ready = false; + this.loading = false; + this.failed = false; // Touch device -var Plyr = function () { - function Plyr(target, options) { - var _this = this; + this.touch = support.touch; // Set the media element - classCallCheck(this, Plyr); + this.media = target; // String selector passed - this.timers = {}; + if (is$1.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } // jQuery, NodeList or Array passed, use first element - // State - this.ready = false; - this.loading = false; - this.failed = false; - // Touch device - this.touch = support.touch; + if (window.jQuery && this.media instanceof jQuery || is$1.nodeList(this.media) || is$1.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } // Set config - // Set the media element - this.media = target; - // String selector passed - if (utils.is.string(this.media)) { - this.media = document.querySelectorAll(this.media); + this.config = extend({}, defaults, Plyr.defaults, options || {}, function () { + try { + return JSON.parse(_this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; } + }()); // Elements cache - // jQuery, NodeList or Array passed, use first element - if (window.jQuery && this.media instanceof jQuery || utils.is.nodeList(this.media) || utils.is.array(this.media)) { - // eslint-disable-next-line - this.media = this.media[0]; - } + this.elements = { + container: null, + captions: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + popup: null, + menu: null, + panels: {}, + buttons: {} + } + }; // Captions + + this.captions = { + active: null, + currentTrack: -1, + meta: new WeakMap() + }; // Fullscreen + + this.fullscreen = { + active: false + }; // Options - // Set config - this.config = utils.extend({}, defaults$1, options || {}, function () { - try { - return JSON.parse(_this.media.getAttribute('data-plyr-config')); - } catch (e) { - return {}; - } - }()); - - // Elements cache - this.elements = { - container: null, - buttons: {}, - display: {}, - progress: {}, - inputs: {}, - settings: { - menu: null, - panes: {}, - tabs: {} - }, - captions: null - }; + this.options = { + speed: [], + quality: [] + }; // Debugging + // TODO: move to globals - // Captions - this.captions = { - active: null, - currentTrack: null - }; + this.debug = new Console(this.config.debug); // Log config options and support - // Fullscreen - this.fullscreen = { - active: false - }; + this.debug.log('Config', this.config); + this.debug.log('Support', support); // We need an element to setup - // Options - this.options = { - speed: [], - quality: [], - captions: [] - }; + if (is$1.nullOrUndefined(this.media) || !is$1.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); + return; + } // Bail if the element is initialized - // Debugging - // TODO: move to globals - this.debug = new Console(this.config.debug); - // Log config options and support - this.debug.log('Config', this.config); - this.debug.log('Support', support); + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; + } // Bail if not enabled - // We need an element to setup - if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) { - this.debug.error('Setup failed: no suitable element passed'); - return; - } - // Bail if the element is initialized - if (this.media.plyr) { - this.debug.warn('Target already setup'); - return; - } + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; + } // Bail if disabled or no basic support + // You may want to disable certain UAs etc - // Bail if not enabled - if (!this.config.enabled) { - this.debug.error('Setup failed: disabled by config'); - return; - } - // Bail if disabled or no basic support - // You may want to disable certain UAs etc - if (!support.check().api) { - this.debug.error('Setup failed: no support'); - return; - } + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; + } // Cache original element state for .destroy() - // Cache original element state for .destroy() - var clone = this.media.cloneNode(true); - clone.autoplay = false; - this.elements.original = clone; - // Set media type based on tag or data attribute - // Supported: video, audio, vimeo, youtube - var type = this.media.tagName.toLowerCase(); + var clone = this.media.cloneNode(true); + clone.autoplay = false; + this.elements.original = clone; // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube - // Embed properties - var iframe = null; - var url = null; - var params = null; + var type = this.media.tagName.toLowerCase(); // Embed properties - // Different setup based on type - switch (type) { - case 'div': - // Find the frame - iframe = this.media.querySelector('iframe'); - - // <iframe> type - if (utils.is.element(iframe)) { - // Detect provider - url = iframe.getAttribute('src'); - this.provider = utils.getProviderByUrl(url); - - // Rework elements - this.elements.container = this.media; - this.media = iframe; - - // Reset classname - this.elements.container.className = ''; - - // Get attributes from URL and set config - params = utils.getUrlParams(url); - if (!utils.is.empty(params)) { - var truthy = ['1', 'true']; - - if (truthy.includes(params.autoplay)) { - this.config.autoplay = true; - } - if (truthy.includes(params.loop)) { - this.config.loop.active = true; - } - - // TODO: replace fullscreen.iosNative with this playsinline config option - // YouTube requires the playsinline in the URL - if (this.isYouTube) { - this.config.playsinline = truthy.includes(params.playsinline); - } else { - this.config.playsinline = true; - } - } - } else { - // <div> with attributes - this.provider = this.media.getAttribute(this.config.attributes.embed.provider); + var iframe = null; + var url = null; // Different setup based on type - // Remove attribute - this.media.removeAttribute(this.config.attributes.embed.provider); - } + switch (type) { + case 'div': + // Find the frame + iframe = this.media.querySelector('iframe'); // <iframe> type - // Unsupported or missing provider - if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { - this.debug.error('Setup failed: Invalid provider'); - return; - } + if (is$1.element(iframe)) { + // Detect provider + url = parseUrl(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements - // Audio will come later for external providers - this.type = types.video; + this.elements.container = this.media; + this.media = iframe; // Reset classname - break; + this.elements.container.className = ''; // Get attributes from URL and set config - case 'video': - case 'audio': - this.type = type; - this.provider = providers.html5; + if (url.search.length) { + var truthy = ['1', 'true']; - // Get config from attributes - if (this.media.hasAttribute('crossorigin')) { - this.config.crossorigin = true; - } - if (this.media.hasAttribute('autoplay')) { - this.config.autoplay = true; - } - if (this.media.hasAttribute('playsinline')) { - this.config.playsinline = true; - } - if (this.media.hasAttribute('muted')) { - this.config.muted = true; - } - if (this.media.hasAttribute('loop')) { - this.config.loop.active = true; - } + if (truthy.includes(url.searchParams.get('autoplay'))) { + this.config.autoplay = true; + } - break; + if (truthy.includes(url.searchParams.get('loop'))) { + this.config.loop.active = true; + } // TODO: replace fullscreen.iosNative with this playsinline config option + // YouTube requires the playsinline in the URL - default: - this.debug.error('Setup failed: unsupported type'); - return; - } - // Check for support again but with type - this.supported = support.check(this.type, this.provider, this.config.playsinline); + if (this.isYouTube) { + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? + } else { + this.config.playsinline = true; + } + } + } else { + // <div> with attributes + this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute - // If no support for even API, bail - if (!this.supported.api) { - this.debug.error('Setup failed: no support'); - return; - } + this.media.removeAttribute(this.config.attributes.embed.provider); + } // Unsupported or missing provider - // Create listeners - this.listeners = new Listeners(this); - // Setup local storage for user settings - this.storage = new Storage(this); + if (is$1.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } // Audio will come later for external providers - // Store reference - this.media.plyr = this; - // Wrap media - if (!utils.is.element(this.elements.container)) { - this.elements.container = utils.createElement('div'); - utils.wrap(this.media, this.elements.container); - } + this.type = types.video; + break; - // Allow focus to be captured - this.elements.container.setAttribute('tabindex', 0); + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; // Get config from attributes - // Add style hook - ui.addStyleHook.call(this); + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } - // Setup media - media.setup.call(this); + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } - // Listen for events if debugging - if (this.config.debug) { - utils.on(this.elements.container, this.config.events.join(' '), function (event) { - _this.debug.log('event: ' + event.type); - }); - } + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { + this.config.playsinline = true; + } - // Setup interface - // If embed but not fully supported, build interface now to avoid flash of controls - if (this.isHTML5 || this.isEmbed && !this.supported.ui) { - ui.build.call(this); - } + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } - // Container listeners - this.listeners.container(); + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } - // Global listeners - this.listeners.global(); + break; - // Setup fullscreen - this.fullscreen = new Fullscreen(this); + default: + this.debug.error('Setup failed: unsupported type'); + return; + } // Check for support again but with type - // Setup ads if provided - this.ads = new Ads(this); - // Autoplay if required - if (this.config.autoplay) { - this.play(); - } - } + this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail - // --------------------------------------- - // API - // --------------------------------------- + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); + return; + } - /** - * Types and provider helpers - */ + this.eventListeners = []; // Create listeners + this.listeners = new Listeners(this); // Setup local storage for user settings - createClass(Plyr, [{ - key: 'play', + this.storage = new Storage(this); // Store reference + this.media.plyr = this; // Wrap media - /** - * Play the media, or play the advertisement (if they are not blocked) - */ - value: function play() { - if (!utils.is.function(this.media.play)) { - return null; - } + if (!is$1.element(this.elements.container)) { + this.elements.container = createElement('div', { + tabindex: 0 + }); + wrap(this.media, this.elements.container); + } // Add style hook - // Return the promise (for HTML5) - return this.media.play(); - } - /** - * Pause the media - */ + ui.addStyleHook.call(this); // Setup media - }, { - key: 'pause', - value: function pause() { - if (!this.playing || !utils.is.function(this.media.pause)) { - return; - } + media.setup.call(this); // Listen for events if debugging - this.media.pause(); - } + if (this.config.debug) { + on.call(this, this.elements.container, this.config.events.join(' '), function (event) { + _this.debug.log("event: ".concat(event.type)); + }); + } // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls - /** - * Get playing state - */ - }, { - key: 'togglePlay', + if (this.isHTML5 || this.isEmbed && !this.supported.ui) { + ui.build.call(this); + } // Container listeners - /** - * Toggle playback based on current status - * @param {boolean} input - */ - value: function togglePlay(input) { - // Toggle based on current state if nothing passed - var toggle = utils.is.boolean(input) ? input : !this.playing; + this.listeners.container(); // Global listeners - if (toggle) { - this.play(); - } else { - this.pause(); - } - } + this.listeners.global(); // Setup fullscreen - /** - * Stop playback - */ + this.fullscreen = new Fullscreen(this); // Setup ads if provided - }, { - key: 'stop', - value: function stop() { - if (this.isHTML5) { - this.pause(); - this.restart(); - } else if (utils.is.function(this.media.stop)) { - this.media.stop(); - } - } + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required - /** - * Restart playback - */ - }, { - key: 'restart', - value: function restart() { - this.currentTime = 0; - } + if (this.config.autoplay) { + this.play(); + } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek - /** - * Rewind - * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime - */ - }, { - key: 'rewind', - value: function rewind(seekTime) { - this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime); - } + this.lastSeekTime = 0; // Setup preview thumbnails if enabled - /** - * Fast forward - * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime - */ + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } + } // --------------------------------------- + // API + // --------------------------------------- - }, { - key: 'forward', - value: function forward(seekTime) { - this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime); - } + /** + * Types and provider helpers + */ - /** - * Seek to a time - * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) - */ - }, { - key: 'increaseVolume', + _createClass(Plyr, [{ + key: "play", + /** + * Play the media, or play the advertisement (if they are not blocked) + */ + value: function play() { + if (!is$1.function(this.media.play)) { + return null; + } // Return the promise (for HTML5) - /** - * Increase volume - * @param {boolean} step - How much to decrease by (between 0 and 1) - */ - value: function increaseVolume(step) { - var volume = this.media.muted ? 0 : this.volume; - this.volume = volume + (utils.is.number(step) ? step : 1); - } - /** - * Decrease volume - * @param {boolean} step - How much to decrease by (between 0 and 1) - */ + return this.media.play(); + } + /** + * Pause the media + */ }, { - key: 'decreaseVolume', - value: function decreaseVolume(step) { - var volume = this.media.muted ? 0 : this.volume; - this.volume = volume - (utils.is.number(step) ? step : 1); + key: "pause", + value: function pause() { + if (!this.playing || !is$1.function(this.media.pause)) { + return; } - /** - * Set muted state - * @param {boolean} mute - */ + this.media.pause(); + } + /** + * Get playing state + */ }, { - key: 'toggleCaptions', + key: "togglePlay", + /** + * Toggle playback based on current status + * @param {boolean} input + */ + value: function togglePlay(input) { + // Toggle based on current state if nothing passed + var toggle = is$1.boolean(input) ? input : !this.playing; - /** - * Toggle captions - * @param {boolean} input - Whether to enable captions - */ - value: function toggleCaptions(input) { - // If there's no full support - if (!this.supported.ui) { - return; - } - - // If the method is called without parameter, toggle based on current value - var show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active); - - // Nothing to change... - if (this.captions.active === show) { - return; - } - - // Set global - this.captions.active = show; - - // Toggle state - utils.toggleState(this.elements.buttons.captions, this.captions.active); - - // Add class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active); - - // Trigger an event - utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); + if (toggle) { + this.play(); + } else { + this.pause(); } - - /** - * Set the captions language - * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) - */ + } + /** + * Stop playback + */ }, { - key: 'airplay', - - - /** - * Trigger the airplay dialog - * TODO: update player with state, support, enabled - */ - value: function airplay() { - // Show dialog if supported - if (support.airplay) { - this.media.webkitShowPlaybackTargetPicker(); - } + key: "stop", + value: function stop() { + if (this.isHTML5) { + this.pause(); + this.restart(); + } else if (is$1.function(this.media.stop)) { + this.media.stop(); } - - /** - * Toggle the player controls - * @param {boolean} toggle - Whether to show the controls - */ + } + /** + * Restart playback + */ }, { - key: 'toggleControls', - value: function toggleControls(toggle) { - var _this2 = this; - - // We need controls of course... - if (!utils.is.element(this.elements.controls)) { - return; - } + key: "restart", + value: function restart() { + this.currentTime = 0; + } + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ - // Don't hide if no UI support or it's audio - if (!this.supported.ui || this.isAudio) { - return; - } + }, { + key: "rewind", + value: function rewind(seekTime) { + this.currentTime = this.currentTime - (is$1.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ - var delay = 0; - var show = toggle; - var isEnterFullscreen = false; + }, { + key: "forward", + value: function forward(seekTime) { + this.currentTime = this.currentTime + (is$1.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ - // Get toggle state if not set - if (!utils.is.boolean(toggle)) { - if (utils.is.event(toggle)) { - // Is the enter fullscreen event - isEnterFullscreen = toggle.type === 'enterfullscreen'; + }, { + key: "increaseVolume", + + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + value: function increaseVolume(step) { + var volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (is$1.number(step) ? step : 0); + } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ - // Events that show the controls - var showEvents = ['touchstart', 'touchmove', 'mouseenter', 'mousemove', 'focusin']; + }, { + key: "decreaseVolume", + value: function decreaseVolume(step) { + this.increaseVolume(-step); + } + /** + * Set muted state + * @param {boolean} mute + */ - // Events that delay hiding - var delayEvents = ['touchmove', 'touchend', 'mousemove']; + }, { + key: "toggleCaptions", + + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + value: function toggleCaptions(input) { + captions.toggle.call(this, input, false); + } + /** + * Set the caption track by index + * @param {number} - Caption index + */ - // Whether to show controls - show = showEvents.includes(toggle.type); + }, { + key: "airplay", - // Delay hiding on move events - if (delayEvents.includes(toggle.type)) { - delay = 2000; - } + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + value: function airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); + } + } + /** + * Toggle the player controls + * @param {boolean} [toggle] - Whether to show the controls + */ - // Delay a little more for keyboard users - if (!this.touch && toggle.type === 'focusin') { - delay = 3000; - utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); - } - } else { - show = utils.hasClass(this.elements.container, this.config.classNames.hideControls); - } - } + }, { + key: "toggleControls", + value: function toggleControls(toggle) { + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + var isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls - // Clear timer on every call - clearTimeout(this.timers.controls); + var force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state - // If the mouse is not over the controls, set a timeout to hide them - if (show || this.paused || this.loading) { - // Check if controls toggled - var toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false); + var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu - // Trigger event - if (toggled) { - utils.dispatchEvent.call(this, this.media, 'controlsshown'); - } + if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); + } // Trigger event on change - // Always show controls when paused or if touch - if (this.paused || this.loading) { - return; - } - // Delay for hiding on touch - if (this.touch) { - delay = 3000; - } - } + if (hiding !== isHidden) { + var eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); + } - // If toggle is false or if we're playing (regardless of toggle), - // then set the timer to hide the controls - if (!show || this.playing) { - this.timers.controls = setTimeout(function () { - // We need controls of course... - if (!utils.is.element(_this2.elements.controls)) { - return; - } - - // If the mouse is over the controls (and not entering fullscreen), bail - if ((_this2.elements.controls.pressed || _this2.elements.controls.hover) && !isEnterFullscreen) { - return; - } - - // Restore transition behaviour - if (!utils.hasClass(_this2.elements.container, _this2.config.classNames.hideControls)) { - utils.toggleClass(_this2.elements.controls, _this2.config.classNames.noTransition, false); - } - - // Set hideControls class - var toggled = utils.toggleClass(_this2.elements.container, _this2.config.classNames.hideControls, _this2.config.hideControls); - - // Trigger event and close menu - if (toggled) { - utils.dispatchEvent.call(_this2, _this2.media, 'controlshidden'); - - if (_this2.config.controls.includes('settings') && !utils.is.empty(_this2.config.settings)) { - controls.toggleMenu.call(_this2, false); - } - } - }, delay); - } + return !hiding; } - /** - * Add event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - */ + return false; + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ }, { - key: 'on', - value: function on(event, callback) { - utils.on(this.elements.container, event, callback); - } - - /** - * Remove event listeners - * @param {string} event - Event type - * @param {function} callback - Callback for when event occurs - */ + key: "on", + value: function on$$1(event, callback) { + on.call(this, this.elements.container, event, callback); + } + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ }, { - key: 'off', - value: function off(event, callback) { - utils.off(this.elements.container, event, callback); - } + key: "once", + value: function once$$1(event, callback) { + once.call(this, this.elements.container, event, callback); + } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ - /** - * Destroy an instance - * Event listeners are removed when elements are removed - * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory - * @param {function} callback - Callback for when destroy is complete - * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) - */ + }, { + key: "off", + value: function off$$1(event, callback) { + off(this.elements.container, event, callback); + } + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ }, { - key: 'destroy', - value: function destroy(callback) { - var _this3 = this; + key: "destroy", + value: function destroy(callback) { + var _this2 = this; - var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - if (!this.ready) { - return; - } + if (!this.ready) { + return; + } - var done = function done() { - // Reset overflow (incase destroyed while in fullscreen) - document.body.style.overflow = ''; - - // GC for embed - _this3.embed = null; - - // If it's a soft destroy, make minimal changes - if (soft) { - if (Object.keys(_this3.elements).length) { - // Remove elements - utils.removeElement(_this3.elements.buttons.play); - utils.removeElement(_this3.elements.captions); - utils.removeElement(_this3.elements.controls); - utils.removeElement(_this3.elements.wrapper); - - // Clear for GC - _this3.elements.buttons.play = null; - _this3.elements.captions = null; - _this3.elements.controls = null; - _this3.elements.wrapper = null; - } - - // Callback - if (utils.is.function(callback)) { - callback(); - } - } else { - // Unbind listeners - _this3.listeners.clear(); + var done = function done() { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; // GC for embed - // Replace the container with the original element provided - utils.replaceElement(_this3.elements.original, _this3.elements.container); + _this2.embed = null; // If it's a soft destroy, make minimal changes - // Event - utils.dispatchEvent.call(_this3, _this3.elements.original, 'destroyed', true); + if (soft) { + if (Object.keys(_this2.elements).length) { + // Remove elements + removeElement(_this2.elements.buttons.play); + removeElement(_this2.elements.captions); + removeElement(_this2.elements.controls); + removeElement(_this2.elements.wrapper); // Clear for GC - // Callback - if (utils.is.function(callback)) { - callback.call(_this3.elements.original); - } + _this2.elements.buttons.play = null; + _this2.elements.captions = null; + _this2.elements.controls = null; + _this2.elements.wrapper = null; + } // Callback - // Reset state - _this3.ready = false; - // Clear for garbage collection - setTimeout(function () { - _this3.elements = null; - _this3.media = null; - }, 200); - } - }; + if (is$1.function(callback)) { + callback(); + } + } else { + // Unbind listeners + unbindListeners.call(_this2); // Replace the container with the original element provided - // Stop playback - this.stop(); + replaceElement(_this2.elements.original, _this2.elements.container); // Event - // Type specific stuff - switch (this.provider + ':' + this.type) { - case 'html5:video': - case 'html5:audio': - // Clear timeout - clearTimeout(this.timers.loading); + triggerEvent.call(_this2, _this2.elements.original, 'destroyed', true); // Callback - // Restore native video controls - ui.toggleNativeControls.call(this, true); + if (is$1.function(callback)) { + callback.call(_this2.elements.original); + } // Reset state - // Clean up - done(); - break; + _this2.ready = false; // Clear for garbage collection - case 'youtube:video': - // Clear timers - clearInterval(this.timers.buffering); - clearInterval(this.timers.playing); + setTimeout(function () { + _this2.elements = null; + _this2.media = null; + }, 200); + } + }; // Stop playback - // Destroy YouTube API - if (this.embed !== null && utils.is.function(this.embed.destroy)) { - this.embed.destroy(); - } - // Clean up - done(); + this.stop(); // Provider specific stuff - break; + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); // Restore native video controls - case 'vimeo:video': - // Destroy Vimeo API - // then clean up (wait, to prevent postmessage errors) - if (this.embed !== null) { - this.embed.unload().then(done); - } + ui.toggleNativeControls.call(this, true); // Clean up - // Vimeo does not always return - setTimeout(done, 200); + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); // Destroy YouTube API - break; + if (this.embed !== null && is$1.function(this.embed.destroy)) { + this.embed.destroy(); + } // Clean up - default: - break; - } - } - /** - * Check for support for a mime type (HTML5 only) - * @param {string} type - Mime type - */ + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } // Vimeo does not always return - }, { - key: 'supports', - value: function supports(type) { - return support.mime.call(this, type); + + setTimeout(done, 200); } + } + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ - /** - * Check for support - * @param {string} type - Player type (audio/video) - * @param {string} provider - Provider (html5/youtube/vimeo) - * @param {bool} inline - Where player has `playsinline` sttribute - */ + }, { + key: "supports", + value: function supports(type) { + return support.mime.call(this, type); + } + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ }, { - key: 'isHTML5', - get: function get() { - return Boolean(this.provider === providers.html5); - } + key: "isHTML5", + get: function get() { + return Boolean(this.provider === providers.html5); + } }, { - key: 'isEmbed', - get: function get() { - return Boolean(this.isYouTube || this.isVimeo); - } + key: "isEmbed", + get: function get() { + return Boolean(this.isYouTube || this.isVimeo); + } }, { - key: 'isYouTube', - get: function get() { - return Boolean(this.provider === providers.youtube); - } + key: "isYouTube", + get: function get() { + return Boolean(this.provider === providers.youtube); + } }, { - key: 'isVimeo', - get: function get() { - return Boolean(this.provider === providers.vimeo); - } + key: "isVimeo", + get: function get() { + return Boolean(this.provider === providers.vimeo); + } }, { - key: 'isVideo', - get: function get() { - return Boolean(this.type === types.video); - } + key: "isVideo", + get: function get() { + return Boolean(this.type === types.video); + } }, { - key: 'isAudio', - get: function get() { - return Boolean(this.type === types.audio); - } + key: "isAudio", + get: function get() { + return Boolean(this.type === types.audio); + } }, { - key: 'playing', - get: function get() { - return Boolean(this.ready && !this.paused && !this.ended); - } - - /** - * Get paused state - */ + key: "playing", + get: function get() { + return Boolean(this.ready && !this.paused && !this.ended); + } + /** + * Get paused state + */ }, { - key: 'paused', - get: function get() { - return Boolean(this.media.paused); - } - - /** - * Get stopped state - */ + key: "paused", + get: function get() { + return Boolean(this.media.paused); + } + /** + * Get stopped state + */ }, { - key: 'stopped', - get: function get() { - return Boolean(this.paused && this.currentTime === 0); - } - - /** - * Get ended state - */ + key: "stopped", + get: function get() { + return Boolean(this.paused && this.currentTime === 0); + } + /** + * Get ended state + */ }, { - key: 'ended', - get: function get() { - return Boolean(this.media.ended); - } + key: "ended", + get: function get() { + return Boolean(this.media.ended); + } }, { - key: 'currentTime', - set: function set(input) { - var targetTime = 0; - - if (utils.is.number(input)) { - targetTime = input; - } + key: "currentTime", + set: function set(input) { + // Bail if media duration isn't available yet + if (!this.duration) { + return; + } // Validate input - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > this.duration) { - targetTime = this.duration; - } - // Set - this.media.currentTime = targetTime; + var inputIsValid = is$1.number(input) && input > 0; // Set - // Logging - this.debug.log('Seeking to ' + this.currentTime + ' seconds'); - } + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging - /** - * Get current time - */ - , - get: function get() { - return Number(this.media.currentTime); - } - - /** - * Get buffered - */ + this.debug.log("Seeking to ".concat(this.currentTime, " seconds")); + } + /** + * Get current time + */ + , + get: function get() { + return Number(this.media.currentTime); + } + /** + * Get buffered + */ }, { - key: 'buffered', - get: function get() { - var buffered = this.media.buffered; - - // YouTube / Vimeo return a float between 0-1 + key: "buffered", + get: function get() { + var buffered = this.media.buffered; // YouTube / Vimeo return a float between 0-1 - if (utils.is.number(buffered)) { - return buffered; - } + if (is$1.number(buffered)) { + return buffered; + } // HTML5 + // TODO: Handle buffered chunks of the media + // (i.e. seek to another section buffers only that section) - // HTML5 - // TODO: Handle buffered chunks of the media - // (i.e. seek to another section buffers only that section) - if (buffered && buffered.length && this.duration > 0) { - return buffered.end(0) / this.duration; - } - return 0; + if (buffered && buffered.length && this.duration > 0) { + return buffered.end(0) / this.duration; } - /** - * Get seeking status - */ + return 0; + } + /** + * Get seeking status + */ }, { - key: 'seeking', - get: function get() { - return Boolean(this.media.seeking); - } + key: "seeking", + get: function get() { + return Boolean(this.media.seeking); + } + /** + * Get the duration of the current media + */ - /** - * Get the duration of the current media - */ + }, { + key: "duration", + get: function get() { + // Faux duration set via config + var fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded + + var realDuration = (this.media || {}).duration; + var duration = !is$1.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration + + return fauxDuration || duration; + } + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ }, { - key: 'duration', - get: function get() { - // Faux duration set via config - var fauxDuration = parseFloat(this.config.duration); + key: "volume", + set: function set(value) { + var volume = value; + var max = 1; + var min = 0; - // True duration - var realDuration = this.media ? Number(this.media.duration) : 0; + if (is$1.string(volume)) { + volume = Number(volume); + } // Load volume from storage if no value specified - // If custom duration is funky, use regular duration - return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration; - } - /** - * Set the player volume - * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage - */ + if (!is$1.number(volume)) { + volume = this.storage.get('volume'); + } // Use config if all else fails - }, { - key: 'volume', - set: function set(value) { - var volume = value; - var max = 1; - var min = 0; - - if (utils.is.string(volume)) { - volume = Number(volume); - } - // Load volume from storage if no value specified - if (!utils.is.number(volume)) { - volume = this.storage.get('volume'); - } + if (!is$1.number(volume)) { + volume = this.config.volume; + } // Maximum is volumeMax - // Use config if all else fails - if (!utils.is.number(volume)) { - volume = this.config.volume; - } - // Maximum is volumeMax - if (volume > max) { - volume = max; - } - // Minimum is volumeMin - if (volume < min) { - volume = min; - } + if (volume > max) { + volume = max; + } // Minimum is volumeMin - // Update config - this.config.volume = volume; - // Set the player volume - this.media.volume = volume; + if (volume < min) { + volume = min; + } // Update config - // If muted, and we're increasing volume manually, reset muted state - if (!utils.is.empty(value) && this.muted && volume > 0) { - this.muted = false; - } - } - /** - * Get the current player volume - */ - , - get: function get() { - return Number(this.media.volume); + this.config.volume = volume; // Set the player volume + + this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state + + if (!is$1.empty(value) && this.muted && volume > 0) { + this.muted = false; } + } + /** + * Get the current player volume + */ + , + get: function get() { + return Number(this.media.volume); + } }, { - key: 'muted', - set: function set(mute) { - var toggle = mute; + key: "muted", + set: function set(mute) { + var toggle = mute; // Load muted state from storage - // Load muted state from storage - if (!utils.is.boolean(toggle)) { - toggle = this.storage.get('muted'); - } + if (!is$1.boolean(toggle)) { + toggle = this.storage.get('muted'); + } // Use config if all else fails - // Use config if all else fails - if (!utils.is.boolean(toggle)) { - toggle = this.config.muted; - } - // Update config - this.config.muted = toggle; + if (!is$1.boolean(toggle)) { + toggle = this.config.muted; + } // Update config - // Set mute on the player - this.media.muted = toggle; - } - /** - * Get current muted state - */ - , - get: function get() { - return Boolean(this.media.muted); - } + this.config.muted = toggle; // Set mute on the player - /** - * Check if the media has audio - */ + this.media.muted = toggle; + } + /** + * Get current muted state + */ + , + get: function get() { + return Boolean(this.media.muted); + } + /** + * Check if the media has audio + */ }, { - key: 'hasAudio', - get: function get() { - // Assume yes for all non HTML5 (as we can't tell...) - if (!this.isHTML5) { - return true; - } - - if (this.isAudio) { - return true; - } - - // Get audio tracks - return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + key: "hasAudio", + get: function get() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; } - /** - * Set playback speed - * @param {number} speed - the speed of playback (0.5-2.0) - */ + if (this.isAudio) { + return true; + } // Get audio tracks - }, { - key: 'speed', - set: function set(input) { - var speed = null; - if (utils.is.number(input)) { - speed = input; - } + return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } + /** + * Set playback speed + * @param {number} speed - the speed of playback (0.5-2.0) + */ - if (!utils.is.number(speed)) { - speed = this.storage.get('speed'); - } + }, { + key: "speed", + set: function set(input) { + var speed = null; - if (!utils.is.number(speed)) { - speed = this.config.speed.selected; - } + if (is$1.number(input)) { + speed = input; + } - // Set min/max - if (speed < 0.1) { - speed = 0.1; - } - if (speed > 2.0) { - speed = 2.0; - } + if (!is$1.number(speed)) { + speed = this.storage.get('speed'); + } - if (!this.config.speed.options.includes(speed)) { - this.debug.warn('Unsupported speed (' + speed + ')'); - return; - } + if (!is$1.number(speed)) { + speed = this.config.speed.selected; + } // Set min/max - // Update config - this.config.speed.selected = speed; - // Set media speed - this.media.playbackRate = speed; + if (speed < 0.1) { + speed = 0.1; } - /** - * Get current playback speed - */ - , - get: function get() { - return Number(this.media.playbackRate); + if (speed > 2.0) { + speed = 2.0; } - /** - * Set playback quality - * Currently HTML5 & YouTube only - * @param {number} input - Quality level - */ + if (!this.config.speed.options.includes(speed)) { + this.debug.warn("Unsupported speed (".concat(speed, ")")); + return; + } // Update config - }, { - key: 'quality', - set: function set(input) { - var quality = null; - if (!utils.is.empty(input)) { - quality = Number(input); - } + this.config.speed.selected = speed; // Set media speed - if (!utils.is.number(quality) || quality === 0) { - quality = this.storage.get('quality'); - } + this.media.playbackRate = speed; + } + /** + * Get current playback speed + */ + , + get: function get() { + return Number(this.media.playbackRate); + } + /** + * Set playback quality + * Currently HTML5 & YouTube only + * @param {number} input - Quality level + */ - if (!utils.is.number(quality)) { - quality = this.config.quality.selected; - } + }, { + key: "quality", + set: function set(input) { + var config = this.config.quality; + var options = this.options.quality; - if (!utils.is.number(quality)) { - quality = this.config.quality.default; - } + if (!options.length) { + return; + } - if (!this.options.quality.length) { - return; - } + var quality = [!is$1.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is$1.number); + var updateStorage = true; - if (!this.options.quality.includes(quality)) { - var closest = utils.closest(this.options.quality, quality); - this.debug.warn('Unsupported quality option: ' + quality + ', using ' + closest + ' instead'); - quality = closest; - } + if (!options.includes(quality)) { + var value = closest(options, quality); + this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); + quality = value; // Don't update storage if quality is not supported - // Update config - this.config.quality.selected = quality; + updateStorage = false; + } // Update config - // Set quality - this.media.quality = quality; - } - /** - * Get current quality level - */ - , - get: function get() { - return this.media.quality; - } + config.selected = quality; // Set quality - /** - * Toggle loop - * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config - * @param {boolean} input - Whether to loop or not - */ + this.media.quality = quality; // Save to storage + + if (updateStorage) { + this.storage.set({ + quality: quality + }); + } + } + /** + * Get current quality level + */ + , + get: function get() { + return this.media.quality; + } + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ }, { - key: 'loop', - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : this.config.loop.active; - this.config.loop.active = toggle; - this.media.loop = toggle; - - // Set default to be a true toggle - /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; - switch (type) { - case 'start': - if (this.config.loop.end && this.config.loop.end <= this.currentTime) { - this.config.loop.end = null; - } - this.config.loop.start = this.currentTime; - // this.config.loop.indicator.start = this.elements.display.played.value; - break; - case 'end': - if (this.config.loop.start >= this.currentTime) { - return this; - } - this.config.loop.end = this.currentTime; - // this.config.loop.indicator.end = this.elements.display.played.value; - break; - case 'all': - this.config.loop.start = 0; - this.config.loop.end = this.duration - 2; - this.config.loop.indicator.start = 0; - this.config.loop.indicator.end = 100; - break; - case 'toggle': - if (this.config.loop.active) { - this.config.loop.start = 0; - this.config.loop.end = null; - } else { - this.config.loop.start = 0; - this.config.loop.end = this.duration - 2; - } - break; - default: + key: "loop", + set: function set(input) { + var toggle = is$1.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; // Set default to be a true toggle + + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; + } + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; + } + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; + case 'toggle': + if (this.config.loop.active) { this.config.loop.start = 0; this.config.loop.end = null; - break; - } */ - } - - /** - * Get current loop state - */ - , - get: function get() { - return Boolean(this.media.loop); - } - - /** - * Set new media source - * @param {object} input - The new source object (see docs) - */ + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } + /** + * Get current loop state + */ + , + get: function get() { + return Boolean(this.media.loop); + } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ }, { - key: 'source', - set: function set(input) { - source.change.call(this, input); - } - - /** - * Get current source - */ - , - get: function get() { - return this.media.currentSrc; - } - - /** - * Set the poster image for a video - * @param {input} - the URL for the new poster image - */ + key: "source", + set: function set(input) { + source.change.call(this, input); + } + /** + * Get current source + */ + , + get: function get() { + return this.media.currentSrc; + } + /** + * Get a download URL (either source or custom) + */ }, { - key: 'poster', - set: function set(input) { - if (!this.isVideo) { - this.debug.warn('Poster can only be set for video'); - return; - } + key: "download", + get: function get() { + var download = this.config.urls.download; + return is$1.url(download) ? download : this.source; + } + /** + * Set the poster image for a video + * @param {input} - the URL for the new poster image + */ - if (utils.is.string(input)) { - this.media.setAttribute('poster', input); - ui.setPoster.call(this); - } + }, { + key: "poster", + set: function set(input) { + if (!this.isVideo) { + this.debug.warn('Poster can only be set for video'); + return; } - /** - * Get the current poster image - */ - , - get: function get() { - if (!this.isVideo) { - return null; - } - - return this.media.getAttribute('poster'); + ui.setPoster.call(this, input, false).catch(function () {}); + } + /** + * Get the current poster image + */ + , + get: function get() { + if (!this.isVideo) { + return null; } - /** - * Set the autoplay state - * @param {boolean} input - Whether to autoplay or not - */ + return this.media.getAttribute('poster'); + } + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ }, { - key: 'autoplay', - set: function set(input) { - var toggle = utils.is.boolean(input) ? input : this.config.autoplay; - this.config.autoplay = toggle; - } - - /** - * Get the current autoplay state - */ - , - get: function get() { - return Boolean(this.config.autoplay); - } + key: "autoplay", + set: function set(input) { + var toggle = is$1.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } + /** + * Get the current autoplay state + */ + , + get: function get() { + return Boolean(this.config.autoplay); + } }, { - key: 'language', - set: function set(input) { - // Nothing specified - if (!utils.is.string(input)) { - return; - } - - // If empty string is passed, assume disable captions - if (utils.is.empty(input)) { - this.toggleCaptions(false); - return; - } - - // Normalize - var language = input.toLowerCase(); - - // Check for support - if (!this.options.captions.includes(language)) { - this.debug.warn('Unsupported language option: ' + language); - return; - } - - // Ensure captions are enabled - this.toggleCaptions(true); + key: "currentTrack", + set: function set(input) { + captions.set.call(this, input, false); + } + /** + * Get the current caption track index (-1 if disabled) + */ + , + get: function get() { + var _this$captions = this.captions, + toggled = _this$captions.toggled, + currentTrack = _this$captions.currentTrack; + return toggled ? currentTrack : -1; + } + /** + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ - // Enabled only - if (language === 'enabled') { - return; - } + }, { + key: "language", + set: function set(input) { + captions.setLanguage.call(this, input, false); + } + /** + * Get the current track's language + */ + , + get: function get() { + return (captions.getCurrentTrack.call(this) || {}).language; + } + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ - // If nothing to change, bail - if (this.language === language) { - return; - } + }, { + key: "pip", + set: function set(input) { + // Bail if no support + if (!support.pip) { + return; + } // Toggle based on current state if not passed - // Update config - this.captions.language = language; - // Clear caption - captions.setText.call(this, null); + var toggle = is$1.boolean(input) ? input : !this.pip; // Toggle based on current state + // Safari - // Update captions - captions.setLanguage.call(this); + if (is$1.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } // Chrome - // Trigger an event - utils.dispatchEvent.call(this, this.media, 'languagechange'); - } - /** - * Get the current captions language - */ - , - get: function get() { - return this.captions.language; + if (is$1.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } } + } + /** + * Get the current picture-in-picture state + */ + , + get: function get() { + if (!support.pip) { + return null; + } // Safari - /** - * Toggle picture-in-picture playback on WebKit/MacOS - * TODO: update player with state, support, enabled - * TODO: detect outside changes - */ - - }, { - key: 'pip', - set: function set(input) { - var states = { - pip: 'picture-in-picture', - inline: 'inline' - }; - - // Bail if no support - if (!support.pip) { - return; - } - - // Toggle based on current state if not passed - var toggle = utils.is.boolean(input) ? input : this.pip === states.inline; - // Toggle based on current state - this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline); - } + if (!is$1.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } // Chrome - /** - * Get the current picture-in-picture state - */ - , - get: function get() { - if (!support.pip) { - return null; - } - return this.media.webkitPresentationMode; - } + return this.media === document.pictureInPictureElement; + } }], [{ - key: 'supported', - value: function supported(type, provider, inline) { - return support.check(type, provider, inline); - } - - /** - * Load an SVG sprite into the page - * @param {string} url - URL for the SVG sprite - * @param {string} [id] - Unique ID - */ + key: "supported", + value: function supported(type, provider, inline) { + return support.check(type, provider, inline); + } + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ }, { - key: 'loadSprite', - value: function loadSprite(url, id) { - return utils.loadSprite(url, id); - } - - /** - * Setup multiple instances - * @param {*} selector - * @param {object} options - */ + key: "loadSprite", + value: function loadSprite$$1(url, id) { + return loadSprite(url, id); + } + /** + * Setup multiple instances + * @param {*} selector + * @param {object} options + */ }, { - key: 'setup', - value: function setup(selector) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - var targets = null; - - if (utils.is.string(selector)) { - targets = Array.from(document.querySelectorAll(selector)); - } else if (utils.is.nodeList(selector)) { - targets = Array.from(selector); - } else if (utils.is.array(selector)) { - targets = selector.filter(function (i) { - return utils.is.element(i); - }); - } + key: "setup", + value: function setup(selector) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var targets = null; - if (utils.is.empty(targets)) { - return null; - } + if (is$1.string(selector)) { + targets = Array.from(document.querySelectorAll(selector)); + } else if (is$1.nodeList(selector)) { + targets = Array.from(selector); + } else if (is$1.array(selector)) { + targets = selector.filter(is$1.element); + } - return targets.map(function (t) { - return new Plyr(t, options); - }); + if (is$1.empty(targets)) { + return null; } + + return targets.map(function (t) { + return new Plyr(t, options); + }); + } }]); + return Plyr; -}(); + }(); -// ========================================================================== + Plyr.defaults = cloneDeep(defaults); -return Plyr; + // ========================================================================== -}))); + return Plyr; -//# sourceMappingURL=plyr.polyfilled.js.map +}))); diff --git a/dist/plyr.polyfilled.js.map b/dist/plyr.polyfilled.js.map deleted file mode 100644 index a260eb31..00000000 --- a/dist/plyr.polyfilled.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../node_modules/core-js/modules/_global.js","../../node_modules/core-js/modules/_core.js","../../node_modules/core-js/modules/_is-object.js","../../node_modules/core-js/modules/_an-object.js","../../node_modules/core-js/modules/_fails.js","../../node_modules/core-js/modules/_descriptors.js","../../node_modules/core-js/modules/_dom-create.js","../../node_modules/core-js/modules/_ie8-dom-define.js","../../node_modules/core-js/modules/_to-primitive.js","../../node_modules/core-js/modules/_object-dp.js","../../node_modules/core-js/modules/_property-desc.js","../../node_modules/core-js/modules/_hide.js","../../node_modules/core-js/modules/_has.js","../../node_modules/core-js/modules/_uid.js","../../node_modules/core-js/modules/_redefine.js","../../node_modules/core-js/modules/_a-function.js","../../node_modules/core-js/modules/_ctx.js","../../node_modules/core-js/modules/_export.js","../../node_modules/core-js/modules/_typed.js","../../node_modules/core-js/modules/_library.js","../../node_modules/core-js/modules/_redefine-all.js","../../node_modules/core-js/modules/_an-instance.js","../../node_modules/core-js/modules/_to-integer.js","../../node_modules/core-js/modules/_to-length.js","../../node_modules/core-js/modules/_to-index.js","../../node_modules/core-js/modules/_cof.js","../../node_modules/core-js/modules/_iobject.js","../../node_modules/core-js/modules/_defined.js","../../node_modules/core-js/modules/_to-iobject.js","../../node_modules/core-js/modules/_to-absolute-index.js","../../node_modules/core-js/modules/_array-includes.js","../../node_modules/core-js/modules/_shared.js","../../node_modules/core-js/modules/_shared-key.js","../../node_modules/core-js/modules/_object-keys-internal.js","../../node_modules/core-js/modules/_enum-bug-keys.js","../../node_modules/core-js/modules/_object-gopn.js","../../node_modules/core-js/modules/_to-object.js","../../node_modules/core-js/modules/_array-fill.js","../../node_modules/core-js/modules/_wks.js","../../node_modules/core-js/modules/_set-to-string-tag.js","../../node_modules/core-js/modules/_typed-buffer.js","../../node_modules/core-js/modules/_species-constructor.js","../../node_modules/core-js/modules/_set-species.js","../../node_modules/core-js/modules/es6.typed.array-buffer.js","../../node_modules/core-js/modules/_classof.js","../../node_modules/core-js/modules/_iterators.js","../../node_modules/core-js/modules/_is-array-iter.js","../../node_modules/core-js/modules/_object-keys.js","../../node_modules/core-js/modules/_object-dps.js","../../node_modules/core-js/modules/_html.js","../../node_modules/core-js/modules/_object-create.js","../../node_modules/core-js/modules/_object-gpo.js","../../node_modules/core-js/modules/core.get-iterator-method.js","../../node_modules/core-js/modules/_is-array.js","../../node_modules/core-js/modules/_array-species-constructor.js","../../node_modules/core-js/modules/_array-species-create.js","../../node_modules/core-js/modules/_array-methods.js","../../node_modules/core-js/modules/_add-to-unscopables.js","../../node_modules/core-js/modules/_iter-step.js","../../node_modules/core-js/modules/_iter-create.js","../../node_modules/core-js/modules/_iter-define.js","../../node_modules/core-js/modules/es6.array.iterator.js","../../node_modules/core-js/modules/_iter-detect.js","../../node_modules/core-js/modules/_array-copy-within.js","../../node_modules/core-js/modules/_object-pie.js","../../node_modules/core-js/modules/_object-gopd.js","../../node_modules/core-js/modules/_typed-array.js","../../node_modules/core-js/modules/es6.typed.int8-array.js","../../node_modules/core-js/modules/es6.typed.uint8-array.js","../../node_modules/core-js/modules/es6.typed.uint8-clamped-array.js","../../node_modules/core-js/modules/es6.typed.int16-array.js","../../node_modules/core-js/modules/es6.typed.uint16-array.js","../../node_modules/core-js/modules/es6.typed.int32-array.js","../../node_modules/core-js/modules/es6.typed.uint32-array.js","../../node_modules/core-js/modules/es6.typed.float32-array.js","../../node_modules/core-js/modules/es6.typed.float64-array.js","../../node_modules/core-js/modules/_iter-call.js","../../node_modules/core-js/modules/_for-of.js","../../node_modules/core-js/modules/_meta.js","../../node_modules/core-js/modules/_validate-collection.js","../../node_modules/core-js/modules/_collection-strong.js","../../node_modules/core-js/modules/_set-proto.js","../../node_modules/core-js/modules/_inherit-if-required.js","../../node_modules/core-js/modules/_collection.js","../../node_modules/core-js/modules/es6.map.js","../../node_modules/core-js/modules/es6.set.js","../../node_modules/core-js/modules/_object-gops.js","../../node_modules/core-js/modules/_object-assign.js","../../node_modules/core-js/modules/_collection-weak.js","../../node_modules/core-js/modules/es6.weak-map.js","../../node_modules/core-js/modules/es6.weak-set.js","../../node_modules/core-js/modules/es6.reflect.apply.js","../../node_modules/core-js/modules/_invoke.js","../../node_modules/core-js/modules/_bind.js","../../node_modules/core-js/modules/es6.reflect.construct.js","../../node_modules/core-js/modules/es6.reflect.define-property.js","../../node_modules/core-js/modules/es6.reflect.delete-property.js","../../node_modules/core-js/modules/es6.reflect.get.js","../../node_modules/core-js/modules/es6.reflect.get-own-property-descriptor.js","../../node_modules/core-js/modules/es6.reflect.get-prototype-of.js","../../node_modules/core-js/modules/es6.reflect.has.js","../../node_modules/core-js/modules/es6.reflect.is-extensible.js","../../node_modules/core-js/modules/_own-keys.js","../../node_modules/core-js/modules/es6.reflect.own-keys.js","../../node_modules/core-js/modules/es6.reflect.prevent-extensions.js","../../node_modules/core-js/modules/es6.reflect.set.js","../../node_modules/core-js/modules/es6.reflect.set-prototype-of.js","../../node_modules/core-js/modules/_task.js","../../node_modules/core-js/modules/_microtask.js","../../node_modules/core-js/modules/_new-promise-capability.js","../../node_modules/core-js/modules/_perform.js","../../node_modules/core-js/modules/_promise-resolve.js","../../node_modules/core-js/modules/es6.promise.js","../../node_modules/core-js/modules/_wks-ext.js","../../node_modules/core-js/modules/_wks-define.js","../../node_modules/core-js/modules/_enum-keys.js","../../node_modules/core-js/modules/_object-gopn-ext.js","../../node_modules/core-js/modules/es6.symbol.js","../../node_modules/core-js/modules/_object-sap.js","../../node_modules/core-js/modules/es6.object.freeze.js","../../node_modules/core-js/modules/es6.object.seal.js","../../node_modules/core-js/modules/es6.object.prevent-extensions.js","../../node_modules/core-js/modules/es6.object.is-frozen.js","../../node_modules/core-js/modules/es6.object.is-sealed.js","../../node_modules/core-js/modules/es6.object.is-extensible.js","../../node_modules/core-js/modules/es6.object.get-own-property-descriptor.js","../../node_modules/core-js/modules/es6.object.get-prototype-of.js","../../node_modules/core-js/modules/es6.object.keys.js","../../node_modules/core-js/modules/es6.object.get-own-property-names.js","../../node_modules/core-js/modules/es6.object.assign.js","../../node_modules/core-js/modules/_same-value.js","../../node_modules/core-js/modules/es6.object.is.js","../../node_modules/core-js/modules/es6.function.name.js","../../node_modules/core-js/modules/es6.string.raw.js","../../node_modules/core-js/modules/es6.string.from-code-point.js","../../node_modules/core-js/modules/_string-at.js","../../node_modules/core-js/modules/es6.string.code-point-at.js","../../node_modules/core-js/modules/_string-repeat.js","../../node_modules/core-js/modules/es6.string.repeat.js","../../node_modules/core-js/modules/_is-regexp.js","../../node_modules/core-js/modules/_string-context.js","../../node_modules/core-js/modules/_fails-is-regexp.js","../../node_modules/core-js/modules/es6.string.starts-with.js","../../node_modules/core-js/modules/es6.string.ends-with.js","../../node_modules/core-js/modules/es6.string.includes.js","../../node_modules/core-js/modules/_flags.js","../../node_modules/core-js/modules/es6.regexp.flags.js","../../node_modules/core-js/modules/_fix-re-wks.js","../../node_modules/core-js/modules/es6.regexp.match.js","../../node_modules/core-js/modules/es6.regexp.replace.js","../../node_modules/core-js/modules/es6.regexp.split.js","../../node_modules/core-js/modules/es6.regexp.search.js","../../node_modules/core-js/modules/_create-property.js","../../node_modules/core-js/modules/es6.array.from.js","../../node_modules/core-js/modules/es6.array.of.js","../../node_modules/core-js/modules/es6.array.copy-within.js","../../node_modules/core-js/modules/es6.array.find.js","../../node_modules/core-js/modules/es6.array.find-index.js","../../node_modules/core-js/modules/es6.array.fill.js","../../node_modules/core-js/modules/es6.number.is-finite.js","../../node_modules/core-js/modules/_is-integer.js","../../node_modules/core-js/modules/es6.number.is-integer.js","../../node_modules/core-js/modules/es6.number.is-safe-integer.js","../../node_modules/core-js/modules/es6.number.is-nan.js","../../node_modules/core-js/modules/es6.number.epsilon.js","../../node_modules/core-js/modules/es6.number.min-safe-integer.js","../../node_modules/core-js/modules/es6.number.max-safe-integer.js","../../node_modules/core-js/modules/_math-log1p.js","../../node_modules/core-js/modules/es6.math.acosh.js","../../node_modules/core-js/modules/es6.math.asinh.js","../../node_modules/core-js/modules/es6.math.atanh.js","../../node_modules/core-js/modules/_math-sign.js","../../node_modules/core-js/modules/es6.math.cbrt.js","../../node_modules/core-js/modules/es6.math.clz32.js","../../node_modules/core-js/modules/es6.math.cosh.js","../../node_modules/core-js/modules/_math-expm1.js","../../node_modules/core-js/modules/es6.math.expm1.js","../../node_modules/core-js/modules/_math-fround.js","../../node_modules/core-js/modules/es6.math.fround.js","../../node_modules/core-js/modules/es6.math.hypot.js","../../node_modules/core-js/modules/es6.math.imul.js","../../node_modules/core-js/modules/es6.math.log1p.js","../../node_modules/core-js/modules/es6.math.log10.js","../../node_modules/core-js/modules/es6.math.log2.js","../../node_modules/core-js/modules/es6.math.sign.js","../../node_modules/core-js/modules/es6.math.sinh.js","../../node_modules/core-js/modules/es6.math.tanh.js","../../node_modules/core-js/modules/es6.math.trunc.js","../../node_modules/core-js/modules/es7.array.includes.js","../../node_modules/core-js/modules/_object-to-array.js","../../node_modules/core-js/modules/es7.object.values.js","../../node_modules/core-js/modules/es7.object.entries.js","../../node_modules/core-js/modules/es7.object.get-own-property-descriptors.js","../../node_modules/core-js/modules/_string-pad.js","../../node_modules/core-js/modules/_user-agent.js","../../node_modules/core-js/modules/es7.string.pad-start.js","../../node_modules/core-js/modules/es7.string.pad-end.js","../../node_modules/core-js/modules/web.timers.js","../../node_modules/core-js/modules/web.immediate.js","../../node_modules/core-js/modules/web.dom.iterable.js","../../node_modules/regenerator-runtime/runtime.js","../../node_modules/custom-event-polyfill/custom-event-polyfill.js","../../node_modules/loadjs/dist/loadjs.umd.js","types.js","utils.js","support.js","html5.js","i18n.js","ui.js","controls.js","captions.js","console.js","defaults.js","fullscreen.js","listeners.js","plugins/vimeo.js","plugins/youtube.js","media.js","plugins/ads.js","source.js","storage.js","plyr.js","plyr.polyfilled.js"],"names":["isObject","require$$0","document","require$$1","require$$2","anObject","toPrimitive","IE8_DOM_DEFINE","dP","createDesc","has","hide","global","aFunction","core","ctx","redefine","uid","toInteger","toLength","cof","IObject","defined","min","toIObject","toAbsoluteIndex","$keys","toObject","DESCRIPTORS","toIndex","$typed","anInstance","arrayFill","redefineAll","fails","LIBRARY","setToStringTag","SPECIES","buffer","VIEW","$export","speciesConstructor","TAG","Iterators","enumBugKeys","getKeys","IE_PROTO","PROTOTYPE","dPs","ITERATOR","classof","isArray","asc","ArrayProto","create","descriptor","$iterCreate","getPrototypeOf","step","addToUnscopables","pIE","require$$3","require$$4","require$$5","require$$6","require$$7","require$$8","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21","require$$22","require$$23","require$$24","require$$25","require$$26","require$$27","require$$28","require$$29","require$$30","require$$31","require$$32","require$$33","require$$34","require$$35","require$$36","require$$37","require$$38","getIterFn","isArrayIter","call","forOf","validate","$iterDefine","setSpecies","meta","$iterDetect","inheritIfRequired","strong","gOPS","createArrayMethod","id","$has","weak","assign","invoke","bind","gOPD","getProto","Reflect","gOPN","setProto","cel","html","process","Promise","newPromiseCapability","TypeError","isNode","newPromiseCapabilityModule","perform","promiseResolve","wksExt","toString","$GOPD","$DP","gOPNExt","wks","shared","ObjectProto","USE_NATIVE","$fails","_create","enumKeys","wksDefine","$getOwnPropertyDescriptor","$getPrototypeOf","isRegExp","MATCH","context","$defineProperty","createProperty","$find","KEY","forced","floor","isInteger","log1p","sign","$expm1","abs","exp","expm1","isEnum","ownKeys","repeat","navigator","userAgent","$pad","wrap","$task","i","NAME","$iterators","this","CustomEvent","define","providers","types","utils","input","instanceof","window","Plyr","getConstructor","Object","Number","isNaN","String","Boolean","Function","nullOrUndefined","Array","WeakMap","NodeList","Element","Text","Event","TextTrackCue","VTTCue","TextTrack","string","kind","test","array","nodeList","length","object","keys","constructor","documentMode","documentElement","style","platform","url","responseType","resolve","reject","request","XMLHttpRequest","addEventListener","JSON","parse","responseText","e","response","Error","statusText","open","send","is","prefix","hasId","isCached","exists","querySelectorAll","injectSprite","data","innerHTML","body","insertBefore","childNodes","container","createElement","toggleHidden","setAttribute","support","storage","cached","localStorage","getItem","content","fetch","then","empty","result","setItem","stringify","catch","Math","random","elements","wrapper","targets","from","reverse","forEach","element","index","child","cloneNode","parent","parentNode","sibling","nextSibling","appendChild","type","attributes","text","setAttributes","textContent","target","removeElement","removeChild","lastChild","newChild","oldChild","replaceChild","entries","key","value","sel","existingAttributes","existing","split","selector","s","trim","className","replace","stripped","parts","start","charAt","class","hidden","boolean","hasAttribute","removeAttribute","toggle","contains","classList","prototype","match","includes","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","querySelector","focused","activeElement","focusable","getElements","first","last","trap","event","keyCode","getFocusElement","shiftKey","focus","preventDefault","on","off","callback","passive","capture","function","Node","toggleListener","events","options","passiveListeners","bubbles","detail","plyr","dispatchEvent","toggleState","pressed","getAttribute","state","args","current","max","toFixed","parseInt","time","displayHours","inverted","number","formatTime","format","slice","hours","getHours","mins","getMinutes","secs","getSeconds","find","RegExp","toUpperCase","substr","toLowerCase","replaceAll","toTitleCase","toPascalCase","sources","source","shift","extend","filter","item","indexOf","reduce","prev","curr","youtube","vimeo","regex","$2","parser","href","search","startsWith","parseUrl","hashes","params","hash","val","decodeURIComponent","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","getRatio","w","h","ratio","transitionEndEvent","undefined","offsetHeight","provider","playsinline","api","ui","browser","getBrowser","canPlayInline","isIPhone","video","rangeInput","audio","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","isHTML5","canPlayType","isVideo","isAudio","supported","defineProperty","range","matchMedia","html5","getSources","sizes","dedupe","player","mime","currentTime","playing","src","load","play","config","blankVideo","debug","log","i18n","seekTime","title","toggleClass","selectors","classNames","uiSupported","listeners","warn","toggleNativeControls","controls","inject","setup","volume","muted","speed","loop","quality","updateVolume","timeUpdate","checkPlaying","pip","airplay","isIos","isTouch","touch","ready","setTitle","setPoster","label","get","buttons","isEmbed","iframe","getElement","poster","posters","backgroundImage","p","paused","stopped","toggleControls","loading","timers","setTimeout","failed","networkState","error","inputs","setRange","mute","updateRangeFill","progress","display","getElementsByTagName","nodeValue","getPercentage","duration","seek","setProgress","buffered","forceHours","invert","invertTime","updateTimeDisplay","seeking","updateProgress","hasDuration","displayDuration","updateSeekTooltip","isWebkit","setProperty","URL","iconUrl","location","cors","host","isIE","svg4everybody","pause","restart","rewind","fastForward","settings","captions","fullscreen","seekTooltip","tooltip","namespace","getIconUrl","iconPath","iconPrefix","icon","createElementNS","use","path","setAttributeNS","attr","badge","menu","buttonType","button","toCamelCase","labelPressed","iconPressed","control","createIcon","createLabel","getAttributesFromSelector","push","suffix","list","checked","radio","faux","insertAdjacentHTML","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","parseFloat","setting","tabs","panes","toggleTab","checkMenu","emptyElement","getBadge","createBadge","sort","a","b","sorting","getLabel","createMenuItem","updateSetting","pane","active","some","lang","language","default","getTracks","tracks","track","unshift","isVimeo","values","tab","form","show","isMenuItem","isButton","stopPropagation","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","isTab","transitions","reducedMotion","size","getTabSize","restore","propertyName","createButton","createRange","createProgress","createTime","inner","home","back","setQualityMenu","getQualityOptions","setSpeedMenu","loadSprite","props","update","findElements","repaint","labels","stored","isYouTube","textTracks","setCaptionsMenu","insertAfter","enabled","hostname","protocol","createObjectURL","blob","setLanguage","setCue","mode","currentTrack","getCurrentTrack","activeCues","embed","enableTextTrack","cue","setText","getCueAsHTML","caption","noop","Console","console","defaults","userLanguage","onChange","trapFocus","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","x","y","overflow","fallback","Fullscreen","property","native","iosNative","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","cancelFullScreen","exitFullscreen","action","enter","exit","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","prefixes","pre","Listeners","lastKey","handleKey","toggleMenu","firstTouch","code","which","altKey","ctrlKey","metaKey","seekByKey","editable","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","keyboard","tabFocus","hideControls","durationUpdate","hasAudio","resetOnEnd","checkLoading","ads","initialized","managerPromise","clickToPlay","ended","disableContextMenu","set","concat","inputEvent","proxy","defaultHandler","customHandlerKey","customHandler","hasCustomHandler","returned","showHomeTab","showTab","toggleInvert","hover","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","setAspectRatio","Vimeo","loadScript","urls","sdk","padding","paddingBottom","offset","transform","autoplay","buildUrlParams","parseVimeoId","embedContainer","replaceElement","thumbnail_large","pathname","Player","autopause","disableTextTrack","stop","setCurrentTime","selected","setPlaybackRate","setVolume","setLoop","currentSrc","getVideoUrl","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","setAutopause","getVideoTitle","getCurrentTime","getDuration","getTextTracks","cues","stripHTML","frame","seconds","build","mapQualityUnit","mapQualityUnits","levels","level","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","videoId","getVideoData","google","items","snippet","currentId","parseYouTubeId","generateId","message","instance","playbackRate","getPlaybackRate","getTitle","playVideo","pauseVideo","stopVideo","seekTo","getPlaybackQuality","setPlaybackQuality","getAvailablePlaybackRates","buffering","setInterval","getVideoLoadedFraction","lastBuffered","getAvailableQualityLevels","Ads","publisherId","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","googleIMA","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","displayContainer","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","tagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","cancel","contentComplete","seekedTime","discardAdBreak","splice","resize","ViewMode","NORMAL","initialize","init","adError","zIndex","destroy","handlers","handler","apply","Date","now","base","insertElement","attribute","cancelRequests","check","crossorigin","addStyleHook","insertElements","Storage","store","json","removeItem","jQuery","original","tagName","getProviderByUrl","getUrlParams","truthy","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","showEvents","delayEvents","noTransition","toggled","soft","done","clear","unload","targetTime","end","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","closest","change","states","inline","webkitPresentationMode","t"],"mappings":"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","file":"plyr.polyfilled.js","sourcesContent":["// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var core = module.exports = { version: '2.5.3' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar TO_STRING = 'toString';\nvar $toString = Function[TO_STRING];\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar uid = require('./_uid');\nvar TYPED = uid('typed_array');\nvar VIEW = uid('view');\nvar ABV = !!(global.ArrayBuffer && global.DataView);\nvar CONSTR = ABV;\nvar i = 0;\nvar l = 9;\nvar Typed;\n\nvar TypedArrayConstructors = (\n 'Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array'\n).split(',');\n\nwhile (i < l) {\n if (Typed = global[TypedArrayConstructors[i++]]) {\n hide(Typed.prototype, TYPED, true);\n hide(Typed.prototype, VIEW, true);\n } else CONSTR = false;\n}\n\nmodule.exports = {\n ABV: ABV,\n CONSTR: CONSTR,\n TYPED: TYPED,\n VIEW: VIEW\n};\n","module.exports = false;\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","// https://tc39.github.io/ecma262/#sec-toindex\nvar toInteger = require('./_to-integer');\nvar toLength = require('./_to-length');\nmodule.exports = function (it) {\n if (it === undefined) return 0;\n var number = toInteger(it);\n var length = toLength(number);\n if (number !== length) throw RangeError('Wrong length!');\n return length;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","var global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\nmodule.exports = function (key) {\n return store[key] || (store[key] = {});\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)\nvar $keys = require('./_object-keys-internal');\nvar hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype');\n\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {\n return $keys(O, hiddenKeys);\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)\n'use strict';\nvar toObject = require('./_to-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\nmodule.exports = function fill(value /* , start = 0, end = @length */) {\n var O = toObject(this);\n var length = toLength(O.length);\n var aLen = arguments.length;\n var index = toAbsoluteIndex(aLen > 1 ? arguments[1] : undefined, length);\n var end = aLen > 2 ? arguments[2] : undefined;\n var endPos = end === undefined ? length : toAbsoluteIndex(end, length);\n while (endPos > index) O[index++] = value;\n return O;\n};\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","'use strict';\nvar global = require('./_global');\nvar DESCRIPTORS = require('./_descriptors');\nvar LIBRARY = require('./_library');\nvar $typed = require('./_typed');\nvar hide = require('./_hide');\nvar redefineAll = require('./_redefine-all');\nvar fails = require('./_fails');\nvar anInstance = require('./_an-instance');\nvar toInteger = require('./_to-integer');\nvar toLength = require('./_to-length');\nvar toIndex = require('./_to-index');\nvar gOPN = require('./_object-gopn').f;\nvar dP = require('./_object-dp').f;\nvar arrayFill = require('./_array-fill');\nvar setToStringTag = require('./_set-to-string-tag');\nvar ARRAY_BUFFER = 'ArrayBuffer';\nvar DATA_VIEW = 'DataView';\nvar PROTOTYPE = 'prototype';\nvar WRONG_LENGTH = 'Wrong length!';\nvar WRONG_INDEX = 'Wrong index!';\nvar $ArrayBuffer = global[ARRAY_BUFFER];\nvar $DataView = global[DATA_VIEW];\nvar Math = global.Math;\nvar RangeError = global.RangeError;\n// eslint-disable-next-line no-shadow-restricted-names\nvar Infinity = global.Infinity;\nvar BaseBuffer = $ArrayBuffer;\nvar abs = Math.abs;\nvar pow = Math.pow;\nvar floor = Math.floor;\nvar log = Math.log;\nvar LN2 = Math.LN2;\nvar BUFFER = 'buffer';\nvar BYTE_LENGTH = 'byteLength';\nvar BYTE_OFFSET = 'byteOffset';\nvar $BUFFER = DESCRIPTORS ? '_b' : BUFFER;\nvar $LENGTH = DESCRIPTORS ? '_l' : BYTE_LENGTH;\nvar $OFFSET = DESCRIPTORS ? '_o' : BYTE_OFFSET;\n\n// IEEE754 conversions based on https://github.com/feross/ieee754\nfunction packIEEE754(value, mLen, nBytes) {\n var buffer = new Array(nBytes);\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var rt = mLen === 23 ? pow(2, -24) - pow(2, -77) : 0;\n var i = 0;\n var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;\n var e, m, c;\n value = abs(value);\n // eslint-disable-next-line no-self-compare\n if (value != value || value === Infinity) {\n // eslint-disable-next-line no-self-compare\n m = value != value ? 1 : 0;\n e = eMax;\n } else {\n e = floor(log(value) / LN2);\n if (value * (c = pow(2, -e)) < 1) {\n e--;\n c *= 2;\n }\n if (e + eBias >= 1) {\n value += rt / c;\n } else {\n value += rt * pow(2, 1 - eBias);\n }\n if (value * c >= 2) {\n e++;\n c /= 2;\n }\n if (e + eBias >= eMax) {\n m = 0;\n e = eMax;\n } else if (e + eBias >= 1) {\n m = (value * c - 1) * pow(2, mLen);\n e = e + eBias;\n } else {\n m = value * pow(2, eBias - 1) * pow(2, mLen);\n e = 0;\n }\n }\n for (; mLen >= 8; buffer[i++] = m & 255, m /= 256, mLen -= 8);\n e = e << mLen | m;\n eLen += mLen;\n for (; eLen > 0; buffer[i++] = e & 255, e /= 256, eLen -= 8);\n buffer[--i] |= s * 128;\n return buffer;\n}\nfunction unpackIEEE754(buffer, mLen, nBytes) {\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var nBits = eLen - 7;\n var i = nBytes - 1;\n var s = buffer[i--];\n var e = s & 127;\n var m;\n s >>= 7;\n for (; nBits > 0; e = e * 256 + buffer[i], i--, nBits -= 8);\n m = e & (1 << -nBits) - 1;\n e >>= -nBits;\n nBits += mLen;\n for (; nBits > 0; m = m * 256 + buffer[i], i--, nBits -= 8);\n if (e === 0) {\n e = 1 - eBias;\n } else if (e === eMax) {\n return m ? NaN : s ? -Infinity : Infinity;\n } else {\n m = m + pow(2, mLen);\n e = e - eBias;\n } return (s ? -1 : 1) * m * pow(2, e - mLen);\n}\n\nfunction unpackI32(bytes) {\n return bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];\n}\nfunction packI8(it) {\n return [it & 0xff];\n}\nfunction packI16(it) {\n return [it & 0xff, it >> 8 & 0xff];\n}\nfunction packI32(it) {\n return [it & 0xff, it >> 8 & 0xff, it >> 16 & 0xff, it >> 24 & 0xff];\n}\nfunction packF64(it) {\n return packIEEE754(it, 52, 8);\n}\nfunction packF32(it) {\n return packIEEE754(it, 23, 4);\n}\n\nfunction addGetter(C, key, internal) {\n dP(C[PROTOTYPE], key, { get: function () { return this[internal]; } });\n}\n\nfunction get(view, bytes, index, isLittleEndian) {\n var numIndex = +index;\n var intIndex = toIndex(numIndex);\n if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX);\n var store = view[$BUFFER]._b;\n var start = intIndex + view[$OFFSET];\n var pack = store.slice(start, start + bytes);\n return isLittleEndian ? pack : pack.reverse();\n}\nfunction set(view, bytes, index, conversion, value, isLittleEndian) {\n var numIndex = +index;\n var intIndex = toIndex(numIndex);\n if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX);\n var store = view[$BUFFER]._b;\n var start = intIndex + view[$OFFSET];\n var pack = conversion(+value);\n for (var i = 0; i < bytes; i++) store[start + i] = pack[isLittleEndian ? i : bytes - i - 1];\n}\n\nif (!$typed.ABV) {\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, $ArrayBuffer, ARRAY_BUFFER);\n var byteLength = toIndex(length);\n this._b = arrayFill.call(new Array(byteLength), 0);\n this[$LENGTH] = byteLength;\n };\n\n $DataView = function DataView(buffer, byteOffset, byteLength) {\n anInstance(this, $DataView, DATA_VIEW);\n anInstance(buffer, $ArrayBuffer, DATA_VIEW);\n var bufferLength = buffer[$LENGTH];\n var offset = toInteger(byteOffset);\n if (offset < 0 || offset > bufferLength) throw RangeError('Wrong offset!');\n byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);\n if (offset + byteLength > bufferLength) throw RangeError(WRONG_LENGTH);\n this[$BUFFER] = buffer;\n this[$OFFSET] = offset;\n this[$LENGTH] = byteLength;\n };\n\n if (DESCRIPTORS) {\n addGetter($ArrayBuffer, BYTE_LENGTH, '_l');\n addGetter($DataView, BUFFER, '_b');\n addGetter($DataView, BYTE_LENGTH, '_l');\n addGetter($DataView, BYTE_OFFSET, '_o');\n }\n\n redefineAll($DataView[PROTOTYPE], {\n getInt8: function getInt8(byteOffset) {\n return get(this, 1, byteOffset)[0] << 24 >> 24;\n },\n getUint8: function getUint8(byteOffset) {\n return get(this, 1, byteOffset)[0];\n },\n getInt16: function getInt16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments[1]);\n return (bytes[1] << 8 | bytes[0]) << 16 >> 16;\n },\n getUint16: function getUint16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments[1]);\n return bytes[1] << 8 | bytes[0];\n },\n getInt32: function getInt32(byteOffset /* , littleEndian */) {\n return unpackI32(get(this, 4, byteOffset, arguments[1]));\n },\n getUint32: function getUint32(byteOffset /* , littleEndian */) {\n return unpackI32(get(this, 4, byteOffset, arguments[1])) >>> 0;\n },\n getFloat32: function getFloat32(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 4, byteOffset, arguments[1]), 23, 4);\n },\n getFloat64: function getFloat64(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 8, byteOffset, arguments[1]), 52, 8);\n },\n setInt8: function setInt8(byteOffset, value) {\n set(this, 1, byteOffset, packI8, value);\n },\n setUint8: function setUint8(byteOffset, value) {\n set(this, 1, byteOffset, packI8, value);\n },\n setInt16: function setInt16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packI16, value, arguments[2]);\n },\n setUint16: function setUint16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packI16, value, arguments[2]);\n },\n setInt32: function setInt32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packI32, value, arguments[2]);\n },\n setUint32: function setUint32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packI32, value, arguments[2]);\n },\n setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packF32, value, arguments[2]);\n },\n setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {\n set(this, 8, byteOffset, packF64, value, arguments[2]);\n }\n });\n} else {\n if (!fails(function () {\n $ArrayBuffer(1);\n }) || !fails(function () {\n new $ArrayBuffer(-1); // eslint-disable-line no-new\n }) || fails(function () {\n new $ArrayBuffer(); // eslint-disable-line no-new\n new $ArrayBuffer(1.5); // eslint-disable-line no-new\n new $ArrayBuffer(NaN); // eslint-disable-line no-new\n return $ArrayBuffer.name != ARRAY_BUFFER;\n })) {\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, $ArrayBuffer);\n return new BaseBuffer(toIndex(length));\n };\n var ArrayBufferProto = $ArrayBuffer[PROTOTYPE] = BaseBuffer[PROTOTYPE];\n for (var keys = gOPN(BaseBuffer), j = 0, key; keys.length > j;) {\n if (!((key = keys[j++]) in $ArrayBuffer)) hide($ArrayBuffer, key, BaseBuffer[key]);\n }\n if (!LIBRARY) ArrayBufferProto.constructor = $ArrayBuffer;\n }\n // iOS Safari 7.x bug\n var view = new $DataView(new $ArrayBuffer(2));\n var $setInt8 = $DataView[PROTOTYPE].setInt8;\n view.setInt8(0, 2147483648);\n view.setInt8(1, 2147483649);\n if (view.getInt8(0) || !view.getInt8(1)) redefineAll($DataView[PROTOTYPE], {\n setInt8: function setInt8(byteOffset, value) {\n $setInt8.call(this, byteOffset, value << 24 >> 24);\n },\n setUint8: function setUint8(byteOffset, value) {\n $setInt8.call(this, byteOffset, value << 24 >> 24);\n }\n }, true);\n}\nsetToStringTag($ArrayBuffer, ARRAY_BUFFER);\nsetToStringTag($DataView, DATA_VIEW);\nhide($DataView[PROTOTYPE], $typed.VIEW, true);\nexports[ARRAY_BUFFER] = $ArrayBuffer;\nexports[DATA_VIEW] = $DataView;\n","// 7.3.20 SpeciesConstructor(O, defaultConstructor)\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar SPECIES = require('./_wks')('species');\nmodule.exports = function (O, D) {\n var C = anObject(O).constructor;\n var S;\n return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);\n};\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","'use strict';\nvar $export = require('./_export');\nvar $typed = require('./_typed');\nvar buffer = require('./_typed-buffer');\nvar anObject = require('./_an-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\nvar isObject = require('./_is-object');\nvar ArrayBuffer = require('./_global').ArrayBuffer;\nvar speciesConstructor = require('./_species-constructor');\nvar $ArrayBuffer = buffer.ArrayBuffer;\nvar $DataView = buffer.DataView;\nvar $isView = $typed.ABV && ArrayBuffer.isView;\nvar $slice = $ArrayBuffer.prototype.slice;\nvar VIEW = $typed.VIEW;\nvar ARRAY_BUFFER = 'ArrayBuffer';\n\n$export($export.G + $export.W + $export.F * (ArrayBuffer !== $ArrayBuffer), { ArrayBuffer: $ArrayBuffer });\n\n$export($export.S + $export.F * !$typed.CONSTR, ARRAY_BUFFER, {\n // 24.1.3.1 ArrayBuffer.isView(arg)\n isView: function isView(it) {\n return $isView && $isView(it) || isObject(it) && VIEW in it;\n }\n});\n\n$export($export.P + $export.U + $export.F * require('./_fails')(function () {\n return !new $ArrayBuffer(2).slice(1, undefined).byteLength;\n}), ARRAY_BUFFER, {\n // 24.1.4.3 ArrayBuffer.prototype.slice(start, end)\n slice: function slice(start, end) {\n if ($slice !== undefined && end === undefined) return $slice.call(anObject(this), start); // FF fix\n var len = anObject(this).byteLength;\n var first = toAbsoluteIndex(start, len);\n var final = toAbsoluteIndex(end === undefined ? len : end, len);\n var result = new (speciesConstructor(this, $ArrayBuffer))(toLength(final - first));\n var viewS = new $DataView(this);\n var viewT = new $DataView(result);\n var index = 0;\n while (first < final) {\n viewT.setUint8(index++, viewS.getUint8(first++));\n } return result;\n }\n});\n\nrequire('./_set-species')(ARRAY_BUFFER);\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","module.exports = {};\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","// 22.1.3.31 Array.prototype[@@unscopables]\nvar UNSCOPABLES = require('./_wks')('unscopables');\nvar ArrayProto = Array.prototype;\nif (ArrayProto[UNSCOPABLES] == undefined) require('./_hide')(ArrayProto, UNSCOPABLES, {});\nmodule.exports = function (key) {\n ArrayProto[UNSCOPABLES][key] = true;\n};\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = (!BUGGY && $native) || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","'use strict';\nvar addToUnscopables = require('./_add-to-unscopables');\nvar step = require('./_iter-step');\nvar Iterators = require('./_iterators');\nvar toIObject = require('./_to-iobject');\n\n// 22.1.3.4 Array.prototype.entries()\n// 22.1.3.13 Array.prototype.keys()\n// 22.1.3.29 Array.prototype.values()\n// 22.1.3.30 Array.prototype[@@iterator]()\nmodule.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) {\n this._t = toIObject(iterated); // target\n this._i = 0; // next index\n this._k = kind; // kind\n// 22.1.5.2.1 %ArrayIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var kind = this._k;\n var index = this._i++;\n if (!O || index >= O.length) {\n this._t = undefined;\n return step(1);\n }\n if (kind == 'keys') return step(0, index);\n if (kind == 'values') return step(0, O[index]);\n return step(0, [index, O[index]]);\n}, 'values');\n\n// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)\nIterators.Arguments = Iterators.Array;\n\naddToUnscopables('keys');\naddToUnscopables('values');\naddToUnscopables('entries');\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)\n'use strict';\nvar toObject = require('./_to-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\n\nmodule.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {\n var O = toObject(this);\n var len = toLength(O.length);\n var to = toAbsoluteIndex(target, len);\n var from = toAbsoluteIndex(start, len);\n var end = arguments.length > 2 ? arguments[2] : undefined;\n var count = Math.min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);\n var inc = 1;\n if (from < to && to < from + count) {\n inc = -1;\n from += count - 1;\n to += count - 1;\n }\n while (count-- > 0) {\n if (from in O) O[to] = O[from];\n else delete O[to];\n to += inc;\n from += inc;\n } return O;\n};\n","exports.f = {}.propertyIsEnumerable;\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","'use strict';\nif (require('./_descriptors')) {\n var LIBRARY = require('./_library');\n var global = require('./_global');\n var fails = require('./_fails');\n var $export = require('./_export');\n var $typed = require('./_typed');\n var $buffer = require('./_typed-buffer');\n var ctx = require('./_ctx');\n var anInstance = require('./_an-instance');\n var propertyDesc = require('./_property-desc');\n var hide = require('./_hide');\n var redefineAll = require('./_redefine-all');\n var toInteger = require('./_to-integer');\n var toLength = require('./_to-length');\n var toIndex = require('./_to-index');\n var toAbsoluteIndex = require('./_to-absolute-index');\n var toPrimitive = require('./_to-primitive');\n var has = require('./_has');\n var classof = require('./_classof');\n var isObject = require('./_is-object');\n var toObject = require('./_to-object');\n var isArrayIter = require('./_is-array-iter');\n var create = require('./_object-create');\n var getPrototypeOf = require('./_object-gpo');\n var gOPN = require('./_object-gopn').f;\n var getIterFn = require('./core.get-iterator-method');\n var uid = require('./_uid');\n var wks = require('./_wks');\n var createArrayMethod = require('./_array-methods');\n var createArrayIncludes = require('./_array-includes');\n var speciesConstructor = require('./_species-constructor');\n var ArrayIterators = require('./es6.array.iterator');\n var Iterators = require('./_iterators');\n var $iterDetect = require('./_iter-detect');\n var setSpecies = require('./_set-species');\n var arrayFill = require('./_array-fill');\n var arrayCopyWithin = require('./_array-copy-within');\n var $DP = require('./_object-dp');\n var $GOPD = require('./_object-gopd');\n var dP = $DP.f;\n var gOPD = $GOPD.f;\n var RangeError = global.RangeError;\n var TypeError = global.TypeError;\n var Uint8Array = global.Uint8Array;\n var ARRAY_BUFFER = 'ArrayBuffer';\n var SHARED_BUFFER = 'Shared' + ARRAY_BUFFER;\n var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';\n var PROTOTYPE = 'prototype';\n var ArrayProto = Array[PROTOTYPE];\n var $ArrayBuffer = $buffer.ArrayBuffer;\n var $DataView = $buffer.DataView;\n var arrayForEach = createArrayMethod(0);\n var arrayFilter = createArrayMethod(2);\n var arraySome = createArrayMethod(3);\n var arrayEvery = createArrayMethod(4);\n var arrayFind = createArrayMethod(5);\n var arrayFindIndex = createArrayMethod(6);\n var arrayIncludes = createArrayIncludes(true);\n var arrayIndexOf = createArrayIncludes(false);\n var arrayValues = ArrayIterators.values;\n var arrayKeys = ArrayIterators.keys;\n var arrayEntries = ArrayIterators.entries;\n var arrayLastIndexOf = ArrayProto.lastIndexOf;\n var arrayReduce = ArrayProto.reduce;\n var arrayReduceRight = ArrayProto.reduceRight;\n var arrayJoin = ArrayProto.join;\n var arraySort = ArrayProto.sort;\n var arraySlice = ArrayProto.slice;\n var arrayToString = ArrayProto.toString;\n var arrayToLocaleString = ArrayProto.toLocaleString;\n var ITERATOR = wks('iterator');\n var TAG = wks('toStringTag');\n var TYPED_CONSTRUCTOR = uid('typed_constructor');\n var DEF_CONSTRUCTOR = uid('def_constructor');\n var ALL_CONSTRUCTORS = $typed.CONSTR;\n var TYPED_ARRAY = $typed.TYPED;\n var VIEW = $typed.VIEW;\n var WRONG_LENGTH = 'Wrong length!';\n\n var $map = createArrayMethod(1, function (O, length) {\n return allocate(speciesConstructor(O, O[DEF_CONSTRUCTOR]), length);\n });\n\n var LITTLE_ENDIAN = fails(function () {\n // eslint-disable-next-line no-undef\n return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\n });\n\n var FORCED_SET = !!Uint8Array && !!Uint8Array[PROTOTYPE].set && fails(function () {\n new Uint8Array(1).set({});\n });\n\n var toOffset = function (it, BYTES) {\n var offset = toInteger(it);\n if (offset < 0 || offset % BYTES) throw RangeError('Wrong offset!');\n return offset;\n };\n\n var validate = function (it) {\n if (isObject(it) && TYPED_ARRAY in it) return it;\n throw TypeError(it + ' is not a typed array!');\n };\n\n var allocate = function (C, length) {\n if (!(isObject(C) && TYPED_CONSTRUCTOR in C)) {\n throw TypeError('It is not a typed array constructor!');\n } return new C(length);\n };\n\n var speciesFromList = function (O, list) {\n return fromList(speciesConstructor(O, O[DEF_CONSTRUCTOR]), list);\n };\n\n var fromList = function (C, list) {\n var index = 0;\n var length = list.length;\n var result = allocate(C, length);\n while (length > index) result[index] = list[index++];\n return result;\n };\n\n var addGetter = function (it, key, internal) {\n dP(it, key, { get: function () { return this._d[internal]; } });\n };\n\n var $from = function from(source /* , mapfn, thisArg */) {\n var O = toObject(source);\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var iterFn = getIterFn(O);\n var i, length, values, result, step, iterator;\n if (iterFn != undefined && !isArrayIter(iterFn)) {\n for (iterator = iterFn.call(O), values = [], i = 0; !(step = iterator.next()).done; i++) {\n values.push(step.value);\n } O = values;\n }\n if (mapping && aLen > 2) mapfn = ctx(mapfn, arguments[2], 2);\n for (i = 0, length = toLength(O.length), result = allocate(this, length); length > i; i++) {\n result[i] = mapping ? mapfn(O[i], i) : O[i];\n }\n return result;\n };\n\n var $of = function of(/* ...items */) {\n var index = 0;\n var length = arguments.length;\n var result = allocate(this, length);\n while (length > index) result[index] = arguments[index++];\n return result;\n };\n\n // iOS Safari 6.x fails here\n var TO_LOCALE_BUG = !!Uint8Array && fails(function () { arrayToLocaleString.call(new Uint8Array(1)); });\n\n var $toLocaleString = function toLocaleString() {\n return arrayToLocaleString.apply(TO_LOCALE_BUG ? arraySlice.call(validate(this)) : validate(this), arguments);\n };\n\n var proto = {\n copyWithin: function copyWithin(target, start /* , end */) {\n return arrayCopyWithin.call(validate(this), target, start, arguments.length > 2 ? arguments[2] : undefined);\n },\n every: function every(callbackfn /* , thisArg */) {\n return arrayEvery(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n fill: function fill(value /* , start, end */) { // eslint-disable-line no-unused-vars\n return arrayFill.apply(validate(this), arguments);\n },\n filter: function filter(callbackfn /* , thisArg */) {\n return speciesFromList(this, arrayFilter(validate(this), callbackfn,\n arguments.length > 1 ? arguments[1] : undefined));\n },\n find: function find(predicate /* , thisArg */) {\n return arrayFind(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined);\n },\n findIndex: function findIndex(predicate /* , thisArg */) {\n return arrayFindIndex(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined);\n },\n forEach: function forEach(callbackfn /* , thisArg */) {\n arrayForEach(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n indexOf: function indexOf(searchElement /* , fromIndex */) {\n return arrayIndexOf(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);\n },\n includes: function includes(searchElement /* , fromIndex */) {\n return arrayIncludes(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);\n },\n join: function join(separator) { // eslint-disable-line no-unused-vars\n return arrayJoin.apply(validate(this), arguments);\n },\n lastIndexOf: function lastIndexOf(searchElement /* , fromIndex */) { // eslint-disable-line no-unused-vars\n return arrayLastIndexOf.apply(validate(this), arguments);\n },\n map: function map(mapfn /* , thisArg */) {\n return $map(validate(this), mapfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n reduce: function reduce(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars\n return arrayReduce.apply(validate(this), arguments);\n },\n reduceRight: function reduceRight(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars\n return arrayReduceRight.apply(validate(this), arguments);\n },\n reverse: function reverse() {\n var that = this;\n var length = validate(that).length;\n var middle = Math.floor(length / 2);\n var index = 0;\n var value;\n while (index < middle) {\n value = that[index];\n that[index++] = that[--length];\n that[length] = value;\n } return that;\n },\n some: function some(callbackfn /* , thisArg */) {\n return arraySome(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n sort: function sort(comparefn) {\n return arraySort.call(validate(this), comparefn);\n },\n subarray: function subarray(begin, end) {\n var O = validate(this);\n var length = O.length;\n var $begin = toAbsoluteIndex(begin, length);\n return new (speciesConstructor(O, O[DEF_CONSTRUCTOR]))(\n O.buffer,\n O.byteOffset + $begin * O.BYTES_PER_ELEMENT,\n toLength((end === undefined ? length : toAbsoluteIndex(end, length)) - $begin)\n );\n }\n };\n\n var $slice = function slice(start, end) {\n return speciesFromList(this, arraySlice.call(validate(this), start, end));\n };\n\n var $set = function set(arrayLike /* , offset */) {\n validate(this);\n var offset = toOffset(arguments[1], 1);\n var length = this.length;\n var src = toObject(arrayLike);\n var len = toLength(src.length);\n var index = 0;\n if (len + offset > length) throw RangeError(WRONG_LENGTH);\n while (index < len) this[offset + index] = src[index++];\n };\n\n var $iterators = {\n entries: function entries() {\n return arrayEntries.call(validate(this));\n },\n keys: function keys() {\n return arrayKeys.call(validate(this));\n },\n values: function values() {\n return arrayValues.call(validate(this));\n }\n };\n\n var isTAIndex = function (target, key) {\n return isObject(target)\n && target[TYPED_ARRAY]\n && typeof key != 'symbol'\n && key in target\n && String(+key) == String(key);\n };\n var $getDesc = function getOwnPropertyDescriptor(target, key) {\n return isTAIndex(target, key = toPrimitive(key, true))\n ? propertyDesc(2, target[key])\n : gOPD(target, key);\n };\n var $setDesc = function defineProperty(target, key, desc) {\n if (isTAIndex(target, key = toPrimitive(key, true))\n && isObject(desc)\n && has(desc, 'value')\n && !has(desc, 'get')\n && !has(desc, 'set')\n // TODO: add validation descriptor w/o calling accessors\n && !desc.configurable\n && (!has(desc, 'writable') || desc.writable)\n && (!has(desc, 'enumerable') || desc.enumerable)\n ) {\n target[key] = desc.value;\n return target;\n } return dP(target, key, desc);\n };\n\n if (!ALL_CONSTRUCTORS) {\n $GOPD.f = $getDesc;\n $DP.f = $setDesc;\n }\n\n $export($export.S + $export.F * !ALL_CONSTRUCTORS, 'Object', {\n getOwnPropertyDescriptor: $getDesc,\n defineProperty: $setDesc\n });\n\n if (fails(function () { arrayToString.call({}); })) {\n arrayToString = arrayToLocaleString = function toString() {\n return arrayJoin.call(this);\n };\n }\n\n var $TypedArrayPrototype$ = redefineAll({}, proto);\n redefineAll($TypedArrayPrototype$, $iterators);\n hide($TypedArrayPrototype$, ITERATOR, $iterators.values);\n redefineAll($TypedArrayPrototype$, {\n slice: $slice,\n set: $set,\n constructor: function () { /* noop */ },\n toString: arrayToString,\n toLocaleString: $toLocaleString\n });\n addGetter($TypedArrayPrototype$, 'buffer', 'b');\n addGetter($TypedArrayPrototype$, 'byteOffset', 'o');\n addGetter($TypedArrayPrototype$, 'byteLength', 'l');\n addGetter($TypedArrayPrototype$, 'length', 'e');\n dP($TypedArrayPrototype$, TAG, {\n get: function () { return this[TYPED_ARRAY]; }\n });\n\n // eslint-disable-next-line max-statements\n module.exports = function (KEY, BYTES, wrapper, CLAMPED) {\n CLAMPED = !!CLAMPED;\n var NAME = KEY + (CLAMPED ? 'Clamped' : '') + 'Array';\n var GETTER = 'get' + KEY;\n var SETTER = 'set' + KEY;\n var TypedArray = global[NAME];\n var Base = TypedArray || {};\n var TAC = TypedArray && getPrototypeOf(TypedArray);\n var FORCED = !TypedArray || !$typed.ABV;\n var O = {};\n var TypedArrayPrototype = TypedArray && TypedArray[PROTOTYPE];\n var getter = function (that, index) {\n var data = that._d;\n return data.v[GETTER](index * BYTES + data.o, LITTLE_ENDIAN);\n };\n var setter = function (that, index, value) {\n var data = that._d;\n if (CLAMPED) value = (value = Math.round(value)) < 0 ? 0 : value > 0xff ? 0xff : value & 0xff;\n data.v[SETTER](index * BYTES + data.o, value, LITTLE_ENDIAN);\n };\n var addElement = function (that, index) {\n dP(that, index, {\n get: function () {\n return getter(this, index);\n },\n set: function (value) {\n return setter(this, index, value);\n },\n enumerable: true\n });\n };\n if (FORCED) {\n TypedArray = wrapper(function (that, data, $offset, $length) {\n anInstance(that, TypedArray, NAME, '_d');\n var index = 0;\n var offset = 0;\n var buffer, byteLength, length, klass;\n if (!isObject(data)) {\n length = toIndex(data);\n byteLength = length * BYTES;\n buffer = new $ArrayBuffer(byteLength);\n } else if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) {\n buffer = data;\n offset = toOffset($offset, BYTES);\n var $len = data.byteLength;\n if ($length === undefined) {\n if ($len % BYTES) throw RangeError(WRONG_LENGTH);\n byteLength = $len - offset;\n if (byteLength < 0) throw RangeError(WRONG_LENGTH);\n } else {\n byteLength = toLength($length) * BYTES;\n if (byteLength + offset > $len) throw RangeError(WRONG_LENGTH);\n }\n length = byteLength / BYTES;\n } else if (TYPED_ARRAY in data) {\n return fromList(TypedArray, data);\n } else {\n return $from.call(TypedArray, data);\n }\n hide(that, '_d', {\n b: buffer,\n o: offset,\n l: byteLength,\n e: length,\n v: new $DataView(buffer)\n });\n while (index < length) addElement(that, index++);\n });\n TypedArrayPrototype = TypedArray[PROTOTYPE] = create($TypedArrayPrototype$);\n hide(TypedArrayPrototype, 'constructor', TypedArray);\n } else if (!fails(function () {\n TypedArray(1);\n }) || !fails(function () {\n new TypedArray(-1); // eslint-disable-line no-new\n }) || !$iterDetect(function (iter) {\n new TypedArray(); // eslint-disable-line no-new\n new TypedArray(null); // eslint-disable-line no-new\n new TypedArray(1.5); // eslint-disable-line no-new\n new TypedArray(iter); // eslint-disable-line no-new\n }, true)) {\n TypedArray = wrapper(function (that, data, $offset, $length) {\n anInstance(that, TypedArray, NAME);\n var klass;\n // `ws` module bug, temporarily remove validation length for Uint8Array\n // https://github.com/websockets/ws/pull/645\n if (!isObject(data)) return new Base(toIndex(data));\n if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) {\n return $length !== undefined\n ? new Base(data, toOffset($offset, BYTES), $length)\n : $offset !== undefined\n ? new Base(data, toOffset($offset, BYTES))\n : new Base(data);\n }\n if (TYPED_ARRAY in data) return fromList(TypedArray, data);\n return $from.call(TypedArray, data);\n });\n arrayForEach(TAC !== Function.prototype ? gOPN(Base).concat(gOPN(TAC)) : gOPN(Base), function (key) {\n if (!(key in TypedArray)) hide(TypedArray, key, Base[key]);\n });\n TypedArray[PROTOTYPE] = TypedArrayPrototype;\n if (!LIBRARY) TypedArrayPrototype.constructor = TypedArray;\n }\n var $nativeIterator = TypedArrayPrototype[ITERATOR];\n var CORRECT_ITER_NAME = !!$nativeIterator\n && ($nativeIterator.name == 'values' || $nativeIterator.name == undefined);\n var $iterator = $iterators.values;\n hide(TypedArray, TYPED_CONSTRUCTOR, true);\n hide(TypedArrayPrototype, TYPED_ARRAY, NAME);\n hide(TypedArrayPrototype, VIEW, true);\n hide(TypedArrayPrototype, DEF_CONSTRUCTOR, TypedArray);\n\n if (CLAMPED ? new TypedArray(1)[TAG] != NAME : !(TAG in TypedArrayPrototype)) {\n dP(TypedArrayPrototype, TAG, {\n get: function () { return NAME; }\n });\n }\n\n O[NAME] = TypedArray;\n\n $export($export.G + $export.W + $export.F * (TypedArray != Base), O);\n\n $export($export.S, NAME, {\n BYTES_PER_ELEMENT: BYTES\n });\n\n $export($export.S + $export.F * fails(function () { Base.of.call(TypedArray, 1); }), NAME, {\n from: $from,\n of: $of\n });\n\n if (!(BYTES_PER_ELEMENT in TypedArrayPrototype)) hide(TypedArrayPrototype, BYTES_PER_ELEMENT, BYTES);\n\n $export($export.P, NAME, proto);\n\n setSpecies(NAME);\n\n $export($export.P + $export.F * FORCED_SET, NAME, { set: $set });\n\n $export($export.P + $export.F * !CORRECT_ITER_NAME, NAME, $iterators);\n\n if (!LIBRARY && TypedArrayPrototype.toString != arrayToString) TypedArrayPrototype.toString = arrayToString;\n\n $export($export.P + $export.F * fails(function () {\n new TypedArray(1).slice();\n }), NAME, { slice: $slice });\n\n $export($export.P + $export.F * (fails(function () {\n return [1, 2].toLocaleString() != new TypedArray([1, 2]).toLocaleString();\n }) || !fails(function () {\n TypedArrayPrototype.toLocaleString.call([1, 2]);\n })), NAME, { toLocaleString: $toLocaleString });\n\n Iterators[NAME] = CORRECT_ITER_NAME ? $nativeIterator : $iterator;\n if (!LIBRARY && !CORRECT_ITER_NAME) hide(TypedArrayPrototype, ITERATOR, $iterator);\n };\n} else module.exports = function () { /* empty */ };\n","require('./_typed-array')('Int8', 1, function (init) {\n return function Int8Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint8', 1, function (init) {\n return function Uint8Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint8', 1, function (init) {\n return function Uint8ClampedArray(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n}, true);\n","require('./_typed-array')('Int16', 2, function (init) {\n return function Int16Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint16', 2, function (init) {\n return function Uint16Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Int32', 4, function (init) {\n return function Int32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint32', 4, function (init) {\n return function Uint32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Float32', 4, function (init) {\n return function Float32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Float64', 8, function (init) {\n return function Float64Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","'use strict';\nvar dP = require('./_object-dp').f;\nvar create = require('./_object-create');\nvar redefineAll = require('./_redefine-all');\nvar ctx = require('./_ctx');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar $iterDefine = require('./_iter-define');\nvar step = require('./_iter-step');\nvar setSpecies = require('./_set-species');\nvar DESCRIPTORS = require('./_descriptors');\nvar fastKey = require('./_meta').fastKey;\nvar validate = require('./_validate-collection');\nvar SIZE = DESCRIPTORS ? '_s' : 'size';\n\nvar getEntry = function (that, key) {\n // fast case\n var index = fastKey(key);\n var entry;\n if (index !== 'F') return that._i[index];\n // frozen object case\n for (entry = that._f; entry; entry = entry.n) {\n if (entry.k == key) return entry;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = create(null); // index\n that._f = undefined; // first entry\n that._l = undefined; // last entry\n that[SIZE] = 0; // size\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.1.3.1 Map.prototype.clear()\n // 23.2.3.2 Set.prototype.clear()\n clear: function clear() {\n for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {\n entry.r = true;\n if (entry.p) entry.p = entry.p.n = undefined;\n delete data[entry.i];\n }\n that._f = that._l = undefined;\n that[SIZE] = 0;\n },\n // 23.1.3.3 Map.prototype.delete(key)\n // 23.2.3.4 Set.prototype.delete(value)\n 'delete': function (key) {\n var that = validate(this, NAME);\n var entry = getEntry(that, key);\n if (entry) {\n var next = entry.n;\n var prev = entry.p;\n delete that._i[entry.i];\n entry.r = true;\n if (prev) prev.n = next;\n if (next) next.p = prev;\n if (that._f == entry) that._f = next;\n if (that._l == entry) that._l = prev;\n that[SIZE]--;\n } return !!entry;\n },\n // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)\n // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)\n forEach: function forEach(callbackfn /* , that = undefined */) {\n validate(this, NAME);\n var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);\n var entry;\n while (entry = entry ? entry.n : this._f) {\n f(entry.v, entry.k, this);\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n }\n },\n // 23.1.3.7 Map.prototype.has(key)\n // 23.2.3.7 Set.prototype.has(value)\n has: function has(key) {\n return !!getEntry(validate(this, NAME), key);\n }\n });\n if (DESCRIPTORS) dP(C.prototype, 'size', {\n get: function () {\n return validate(this, NAME)[SIZE];\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var entry = getEntry(that, key);\n var prev, index;\n // change existing entry\n if (entry) {\n entry.v = value;\n // create new entry\n } else {\n that._l = entry = {\n i: index = fastKey(key, true), // <- index\n k: key, // <- key\n v: value, // <- value\n p: prev = that._l, // <- previous entry\n n: undefined, // <- next entry\n r: false // <- removed\n };\n if (!that._f) that._f = entry;\n if (prev) prev.n = entry;\n that[SIZE]++;\n // add to index\n if (index !== 'F') that._i[index] = entry;\n } return that;\n },\n getEntry: getEntry,\n setStrong: function (C, NAME, IS_MAP) {\n // add .keys, .values, .entries, [@@iterator]\n // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11\n $iterDefine(C, NAME, function (iterated, kind) {\n this._t = validate(iterated, NAME); // target\n this._k = kind; // kind\n this._l = undefined; // previous\n }, function () {\n var that = this;\n var kind = that._k;\n var entry = that._l;\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n // get next entry\n if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {\n // or finish the iteration\n that._t = undefined;\n return step(1);\n }\n // return step by kind\n if (kind == 'keys') return step(0, entry.k);\n if (kind == 'values') return step(0, entry.v);\n return step(0, [entry.k, entry.v]);\n }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);\n\n // add [@@species], 23.1.2.2, 23.2.2.2\n setSpecies(NAME);\n }\n};\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar MAP = 'Map';\n\n// 23.1 Map Objects\nmodule.exports = require('./_collection')(MAP, function (get) {\n return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.1.3.6 Map.prototype.get(key)\n get: function get(key) {\n var entry = strong.getEntry(validate(this, MAP), key);\n return entry && entry.v;\n },\n // 23.1.3.9 Map.prototype.set(key, value)\n set: function set(key, value) {\n return strong.def(validate(this, MAP), key === 0 ? 0 : key, value);\n }\n}, strong, true);\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar SET = 'Set';\n\n// 23.2 Set Objects\nmodule.exports = require('./_collection')(SET, function (get) {\n return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.2.3.1 Set.prototype.add(value)\n add: function add(value) {\n return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);\n }\n}, strong);\n","exports.f = Object.getOwnPropertySymbols;\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];\n } return T;\n} : $assign;\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar validate = require('./_validate-collection');\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar tmp = {};\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","'use strict';\nvar weak = require('./_collection-weak');\nvar validate = require('./_validate-collection');\nvar WEAK_SET = 'WeakSet';\n\n// 23.4 WeakSet Objects\nrequire('./_collection')(WEAK_SET, function (get) {\n return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.4.3.1 WeakSet.prototype.add(value)\n add: function add(value) {\n return weak.def(validate(this, WEAK_SET), value, true);\n }\n}, weak, false, true);\n","// 26.1.1 Reflect.apply(target, thisArgument, argumentsList)\nvar $export = require('./_export');\nvar aFunction = require('./_a-function');\nvar anObject = require('./_an-object');\nvar rApply = (require('./_global').Reflect || {}).apply;\nvar fApply = Function.apply;\n// MS Edge argumentsList argument is optional\n$export($export.S + $export.F * !require('./_fails')(function () {\n rApply(function () { /* empty */ });\n}), 'Reflect', {\n apply: function apply(target, thisArgument, argumentsList) {\n var T = aFunction(target);\n var L = anObject(argumentsList);\n return rApply ? rApply(T, thisArgument, L) : fApply.call(T, thisArgument, L);\n }\n});\n","// fast apply, http://jsperf.lnkit.com/fast-apply/5\nmodule.exports = function (fn, args, that) {\n var un = that === undefined;\n switch (args.length) {\n case 0: return un ? fn()\n : fn.call(that);\n case 1: return un ? fn(args[0])\n : fn.call(that, args[0]);\n case 2: return un ? fn(args[0], args[1])\n : fn.call(that, args[0], args[1]);\n case 3: return un ? fn(args[0], args[1], args[2])\n : fn.call(that, args[0], args[1], args[2]);\n case 4: return un ? fn(args[0], args[1], args[2], args[3])\n : fn.call(that, args[0], args[1], args[2], args[3]);\n } return fn.apply(that, args);\n};\n","'use strict';\nvar aFunction = require('./_a-function');\nvar isObject = require('./_is-object');\nvar invoke = require('./_invoke');\nvar arraySlice = [].slice;\nvar factories = {};\n\nvar construct = function (F, len, args) {\n if (!(len in factories)) {\n for (var n = [], i = 0; i < len; i++) n[i] = 'a[' + i + ']';\n // eslint-disable-next-line no-new-func\n factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')');\n } return factories[len](F, args);\n};\n\nmodule.exports = Function.bind || function bind(that /* , ...args */) {\n var fn = aFunction(this);\n var partArgs = arraySlice.call(arguments, 1);\n var bound = function (/* args... */) {\n var args = partArgs.concat(arraySlice.call(arguments));\n return this instanceof bound ? construct(fn, args.length, args) : invoke(fn, args, that);\n };\n if (isObject(fn.prototype)) bound.prototype = fn.prototype;\n return bound;\n};\n","// 26.1.2 Reflect.construct(target, argumentsList [, newTarget])\nvar $export = require('./_export');\nvar create = require('./_object-create');\nvar aFunction = require('./_a-function');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar bind = require('./_bind');\nvar rConstruct = (require('./_global').Reflect || {}).construct;\n\n// MS Edge supports only 2 arguments and argumentsList argument is optional\n// FF Nightly sets third argument as `new.target`, but does not create `this` from it\nvar NEW_TARGET_BUG = fails(function () {\n function F() { /* empty */ }\n return !(rConstruct(function () { /* empty */ }, [], F) instanceof F);\n});\nvar ARGS_BUG = !fails(function () {\n rConstruct(function () { /* empty */ });\n});\n\n$export($export.S + $export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', {\n construct: function construct(Target, args /* , newTarget */) {\n aFunction(Target);\n anObject(args);\n var newTarget = arguments.length < 3 ? Target : aFunction(arguments[2]);\n if (ARGS_BUG && !NEW_TARGET_BUG) return rConstruct(Target, args, newTarget);\n if (Target == newTarget) {\n // w/o altered newTarget, optimization for 0-4 arguments\n switch (args.length) {\n case 0: return new Target();\n case 1: return new Target(args[0]);\n case 2: return new Target(args[0], args[1]);\n case 3: return new Target(args[0], args[1], args[2]);\n case 4: return new Target(args[0], args[1], args[2], args[3]);\n }\n // w/o altered newTarget, lot of arguments case\n var $args = [null];\n $args.push.apply($args, args);\n return new (bind.apply(Target, $args))();\n }\n // with altered newTarget, not support built-in constructors\n var proto = newTarget.prototype;\n var instance = create(isObject(proto) ? proto : Object.prototype);\n var result = Function.apply.call(Target, instance, args);\n return isObject(result) ? result : instance;\n }\n});\n","// 26.1.3 Reflect.defineProperty(target, propertyKey, attributes)\nvar dP = require('./_object-dp');\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar toPrimitive = require('./_to-primitive');\n\n// MS Edge has broken Reflect.defineProperty - throwing instead of returning false\n$export($export.S + $export.F * require('./_fails')(function () {\n // eslint-disable-next-line no-undef\n Reflect.defineProperty(dP.f({}, 1, { value: 1 }), 1, { value: 2 });\n}), 'Reflect', {\n defineProperty: function defineProperty(target, propertyKey, attributes) {\n anObject(target);\n propertyKey = toPrimitive(propertyKey, true);\n anObject(attributes);\n try {\n dP.f(target, propertyKey, attributes);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","// 26.1.4 Reflect.deleteProperty(target, propertyKey)\nvar $export = require('./_export');\nvar gOPD = require('./_object-gopd').f;\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n deleteProperty: function deleteProperty(target, propertyKey) {\n var desc = gOPD(anObject(target), propertyKey);\n return desc && !desc.configurable ? false : delete target[propertyKey];\n }\n});\n","// 26.1.6 Reflect.get(target, propertyKey [, receiver])\nvar gOPD = require('./_object-gopd');\nvar getPrototypeOf = require('./_object-gpo');\nvar has = require('./_has');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\n\nfunction get(target, propertyKey /* , receiver */) {\n var receiver = arguments.length < 3 ? target : arguments[2];\n var desc, proto;\n if (anObject(target) === receiver) return target[propertyKey];\n if (desc = gOPD.f(target, propertyKey)) return has(desc, 'value')\n ? desc.value\n : desc.get !== undefined\n ? desc.get.call(receiver)\n : undefined;\n if (isObject(proto = getPrototypeOf(target))) return get(proto, propertyKey, receiver);\n}\n\n$export($export.S, 'Reflect', { get: get });\n","// 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey)\nvar gOPD = require('./_object-gopd');\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey) {\n return gOPD.f(anObject(target), propertyKey);\n }\n});\n","// 26.1.8 Reflect.getPrototypeOf(target)\nvar $export = require('./_export');\nvar getProto = require('./_object-gpo');\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getPrototypeOf: function getPrototypeOf(target) {\n return getProto(anObject(target));\n }\n});\n","// 26.1.9 Reflect.has(target, propertyKey)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', {\n has: function has(target, propertyKey) {\n return propertyKey in target;\n }\n});\n","// 26.1.10 Reflect.isExtensible(target)\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar $isExtensible = Object.isExtensible;\n\n$export($export.S, 'Reflect', {\n isExtensible: function isExtensible(target) {\n anObject(target);\n return $isExtensible ? $isExtensible(target) : true;\n }\n});\n","// all object keys, includes non-enumerable and symbols\nvar gOPN = require('./_object-gopn');\nvar gOPS = require('./_object-gops');\nvar anObject = require('./_an-object');\nvar Reflect = require('./_global').Reflect;\nmodule.exports = Reflect && Reflect.ownKeys || function ownKeys(it) {\n var keys = gOPN.f(anObject(it));\n var getSymbols = gOPS.f;\n return getSymbols ? keys.concat(getSymbols(it)) : keys;\n};\n","// 26.1.11 Reflect.ownKeys(target)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', { ownKeys: require('./_own-keys') });\n","// 26.1.12 Reflect.preventExtensions(target)\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar $preventExtensions = Object.preventExtensions;\n\n$export($export.S, 'Reflect', {\n preventExtensions: function preventExtensions(target) {\n anObject(target);\n try {\n if ($preventExtensions) $preventExtensions(target);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","// 26.1.13 Reflect.set(target, propertyKey, V [, receiver])\nvar dP = require('./_object-dp');\nvar gOPD = require('./_object-gopd');\nvar getPrototypeOf = require('./_object-gpo');\nvar has = require('./_has');\nvar $export = require('./_export');\nvar createDesc = require('./_property-desc');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\n\nfunction set(target, propertyKey, V /* , receiver */) {\n var receiver = arguments.length < 4 ? target : arguments[3];\n var ownDesc = gOPD.f(anObject(target), propertyKey);\n var existingDescriptor, proto;\n if (!ownDesc) {\n if (isObject(proto = getPrototypeOf(target))) {\n return set(proto, propertyKey, V, receiver);\n }\n ownDesc = createDesc(0);\n }\n if (has(ownDesc, 'value')) {\n if (ownDesc.writable === false || !isObject(receiver)) return false;\n existingDescriptor = gOPD.f(receiver, propertyKey) || createDesc(0);\n existingDescriptor.value = V;\n dP.f(receiver, propertyKey, existingDescriptor);\n return true;\n }\n return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true);\n}\n\n$export($export.S, 'Reflect', { set: set });\n","// 26.1.14 Reflect.setPrototypeOf(target, proto)\nvar $export = require('./_export');\nvar setProto = require('./_set-proto');\n\nif (setProto) $export($export.S, 'Reflect', {\n setPrototypeOf: function setPrototypeOf(target, proto) {\n setProto.check(target, proto);\n try {\n setProto.set(target, proto);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","var ctx = require('./_ctx');\nvar invoke = require('./_invoke');\nvar html = require('./_html');\nvar cel = require('./_dom-create');\nvar global = require('./_global');\nvar process = global.process;\nvar setTask = global.setImmediate;\nvar clearTask = global.clearImmediate;\nvar MessageChannel = global.MessageChannel;\nvar Dispatch = global.Dispatch;\nvar counter = 0;\nvar queue = {};\nvar ONREADYSTATECHANGE = 'onreadystatechange';\nvar defer, channel, port;\nvar run = function () {\n var id = +this;\n // eslint-disable-next-line no-prototype-builtins\n if (queue.hasOwnProperty(id)) {\n var fn = queue[id];\n delete queue[id];\n fn();\n }\n};\nvar listener = function (event) {\n run.call(event.data);\n};\n// Node.js 0.9+ & IE10+ has setImmediate, otherwise:\nif (!setTask || !clearTask) {\n setTask = function setImmediate(fn) {\n var args = [];\n var i = 1;\n while (arguments.length > i) args.push(arguments[i++]);\n queue[++counter] = function () {\n // eslint-disable-next-line no-new-func\n invoke(typeof fn == 'function' ? fn : Function(fn), args);\n };\n defer(counter);\n return counter;\n };\n clearTask = function clearImmediate(id) {\n delete queue[id];\n };\n // Node.js 0.8-\n if (require('./_cof')(process) == 'process') {\n defer = function (id) {\n process.nextTick(ctx(run, id, 1));\n };\n // Sphere (JS game engine) Dispatch API\n } else if (Dispatch && Dispatch.now) {\n defer = function (id) {\n Dispatch.now(ctx(run, id, 1));\n };\n // Browsers with MessageChannel, includes WebWorkers\n } else if (MessageChannel) {\n channel = new MessageChannel();\n port = channel.port2;\n channel.port1.onmessage = listener;\n defer = ctx(port.postMessage, port, 1);\n // Browsers with postMessage, skip WebWorkers\n // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'\n } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {\n defer = function (id) {\n global.postMessage(id + '', '*');\n };\n global.addEventListener('message', listener, false);\n // IE8-\n } else if (ONREADYSTATECHANGE in cel('script')) {\n defer = function (id) {\n html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {\n html.removeChild(this);\n run.call(id);\n };\n };\n // Rest old browsers\n } else {\n defer = function (id) {\n setTimeout(ctx(run, id, 1), 0);\n };\n }\n}\nmodule.exports = {\n set: setTask,\n clear: clearTask\n};\n","var global = require('./_global');\nvar macrotask = require('./_task').set;\nvar Observer = global.MutationObserver || global.WebKitMutationObserver;\nvar process = global.process;\nvar Promise = global.Promise;\nvar isNode = require('./_cof')(process) == 'process';\n\nmodule.exports = function () {\n var head, last, notify;\n\n var flush = function () {\n var parent, fn;\n if (isNode && (parent = process.domain)) parent.exit();\n while (head) {\n fn = head.fn;\n head = head.next;\n try {\n fn();\n } catch (e) {\n if (head) notify();\n else last = undefined;\n throw e;\n }\n } last = undefined;\n if (parent) parent.enter();\n };\n\n // Node.js\n if (isNode) {\n notify = function () {\n process.nextTick(flush);\n };\n // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339\n } else if (Observer && !(global.navigator && global.navigator.standalone)) {\n var toggle = true;\n var node = document.createTextNode('');\n new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new\n notify = function () {\n node.data = toggle = !toggle;\n };\n // environments with maybe non-completely correct, but existent Promise\n } else if (Promise && Promise.resolve) {\n var promise = Promise.resolve();\n notify = function () {\n promise.then(flush);\n };\n // for other environments - macrotask based on:\n // - setImmediate\n // - MessageChannel\n // - window.postMessag\n // - onreadystatechange\n // - setTimeout\n } else {\n notify = function () {\n // strange IE + webpack dev server bug - use .call(global)\n macrotask.call(global, flush);\n };\n }\n\n return function (fn) {\n var task = { fn: fn, next: undefined };\n if (last) last.next = task;\n if (!head) {\n head = task;\n notify();\n } last = task;\n };\n};\n","'use strict';\n// 25.4.1.5 NewPromiseCapability(C)\nvar aFunction = require('./_a-function');\n\nfunction PromiseCapability(C) {\n var resolve, reject;\n this.promise = new C(function ($$resolve, $$reject) {\n if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');\n resolve = $$resolve;\n reject = $$reject;\n });\n this.resolve = aFunction(resolve);\n this.reject = aFunction(reject);\n}\n\nmodule.exports.f = function (C) {\n return new PromiseCapability(C);\n};\n","module.exports = function (exec) {\n try {\n return { e: false, v: exec() };\n } catch (e) {\n return { e: true, v: e };\n }\n};\n","var anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar newPromiseCapability = require('./_new-promise-capability');\n\nmodule.exports = function (C, x) {\n anObject(C);\n if (isObject(x) && x.constructor === C) return x;\n var promiseCapability = newPromiseCapability.f(C);\n var resolve = promiseCapability.resolve;\n resolve(x);\n return promiseCapability.promise;\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar global = require('./_global');\nvar ctx = require('./_ctx');\nvar classof = require('./_classof');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar aFunction = require('./_a-function');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar speciesConstructor = require('./_species-constructor');\nvar task = require('./_task').set;\nvar microtask = require('./_microtask')();\nvar newPromiseCapabilityModule = require('./_new-promise-capability');\nvar perform = require('./_perform');\nvar promiseResolve = require('./_promise-resolve');\nvar PROMISE = 'Promise';\nvar TypeError = global.TypeError;\nvar process = global.process;\nvar $Promise = global[PROMISE];\nvar isNode = classof(process) == 'process';\nvar empty = function () { /* empty */ };\nvar Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;\nvar newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;\n\nvar USE_NATIVE = !!function () {\n try {\n // correct subclassing with @@species support\n var promise = $Promise.resolve(1);\n var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) {\n exec(empty, empty);\n };\n // unhandled rejections tracking support, NodeJS Promise without it fails @@species test\n return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;\n } catch (e) { /* empty */ }\n}();\n\n// helpers\nvar isThenable = function (it) {\n var then;\n return isObject(it) && typeof (then = it.then) == 'function' ? then : false;\n};\nvar notify = function (promise, isReject) {\n if (promise._n) return;\n promise._n = true;\n var chain = promise._c;\n microtask(function () {\n var value = promise._v;\n var ok = promise._s == 1;\n var i = 0;\n var run = function (reaction) {\n var handler = ok ? reaction.ok : reaction.fail;\n var resolve = reaction.resolve;\n var reject = reaction.reject;\n var domain = reaction.domain;\n var result, then;\n try {\n if (handler) {\n if (!ok) {\n if (promise._h == 2) onHandleUnhandled(promise);\n promise._h = 1;\n }\n if (handler === true) result = value;\n else {\n if (domain) domain.enter();\n result = handler(value);\n if (domain) domain.exit();\n }\n if (result === reaction.promise) {\n reject(TypeError('Promise-chain cycle'));\n } else if (then = isThenable(result)) {\n then.call(result, resolve, reject);\n } else resolve(result);\n } else reject(value);\n } catch (e) {\n reject(e);\n }\n };\n while (chain.length > i) run(chain[i++]); // variable length - can't use forEach\n promise._c = [];\n promise._n = false;\n if (isReject && !promise._h) onUnhandled(promise);\n });\n};\nvar onUnhandled = function (promise) {\n task.call(global, function () {\n var value = promise._v;\n var unhandled = isUnhandled(promise);\n var result, handler, console;\n if (unhandled) {\n result = perform(function () {\n if (isNode) {\n process.emit('unhandledRejection', value, promise);\n } else if (handler = global.onunhandledrejection) {\n handler({ promise: promise, reason: value });\n } else if ((console = global.console) && console.error) {\n console.error('Unhandled promise rejection', value);\n }\n });\n // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should\n promise._h = isNode || isUnhandled(promise) ? 2 : 1;\n } promise._a = undefined;\n if (unhandled && result.e) throw result.v;\n });\n};\nvar isUnhandled = function (promise) {\n return promise._h !== 1 && (promise._a || promise._c).length === 0;\n};\nvar onHandleUnhandled = function (promise) {\n task.call(global, function () {\n var handler;\n if (isNode) {\n process.emit('rejectionHandled', promise);\n } else if (handler = global.onrejectionhandled) {\n handler({ promise: promise, reason: promise._v });\n }\n });\n};\nvar $reject = function (value) {\n var promise = this;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n promise._v = value;\n promise._s = 2;\n if (!promise._a) promise._a = promise._c.slice();\n notify(promise, true);\n};\nvar $resolve = function (value) {\n var promise = this;\n var then;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n try {\n if (promise === value) throw TypeError(\"Promise can't be resolved itself\");\n if (then = isThenable(value)) {\n microtask(function () {\n var wrapper = { _w: promise, _d: false }; // wrap\n try {\n then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));\n } catch (e) {\n $reject.call(wrapper, e);\n }\n });\n } else {\n promise._v = value;\n promise._s = 1;\n notify(promise, false);\n }\n } catch (e) {\n $reject.call({ _w: promise, _d: false }, e); // wrap\n }\n};\n\n// constructor polyfill\nif (!USE_NATIVE) {\n // 25.4.3.1 Promise(executor)\n $Promise = function Promise(executor) {\n anInstance(this, $Promise, PROMISE, '_h');\n aFunction(executor);\n Internal.call(this);\n try {\n executor(ctx($resolve, this, 1), ctx($reject, this, 1));\n } catch (err) {\n $reject.call(this, err);\n }\n };\n // eslint-disable-next-line no-unused-vars\n Internal = function Promise(executor) {\n this._c = []; // <- awaiting reactions\n this._a = undefined; // <- checked in isUnhandled reactions\n this._s = 0; // <- state\n this._d = false; // <- done\n this._v = undefined; // <- value\n this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled\n this._n = false; // <- notify\n };\n Internal.prototype = require('./_redefine-all')($Promise.prototype, {\n // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)\n then: function then(onFulfilled, onRejected) {\n var reaction = newPromiseCapability(speciesConstructor(this, $Promise));\n reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;\n reaction.fail = typeof onRejected == 'function' && onRejected;\n reaction.domain = isNode ? process.domain : undefined;\n this._c.push(reaction);\n if (this._a) this._a.push(reaction);\n if (this._s) notify(this, false);\n return reaction.promise;\n },\n // 25.4.5.1 Promise.prototype.catch(onRejected)\n 'catch': function (onRejected) {\n return this.then(undefined, onRejected);\n }\n });\n OwnPromiseCapability = function () {\n var promise = new Internal();\n this.promise = promise;\n this.resolve = ctx($resolve, promise, 1);\n this.reject = ctx($reject, promise, 1);\n };\n newPromiseCapabilityModule.f = newPromiseCapability = function (C) {\n return C === $Promise || C === Wrapper\n ? new OwnPromiseCapability(C)\n : newGenericPromiseCapability(C);\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });\nrequire('./_set-to-string-tag')($Promise, PROMISE);\nrequire('./_set-species')(PROMISE);\nWrapper = require('./_core')[PROMISE];\n\n// statics\n$export($export.S + $export.F * !USE_NATIVE, PROMISE, {\n // 25.4.4.5 Promise.reject(r)\n reject: function reject(r) {\n var capability = newPromiseCapability(this);\n var $$reject = capability.reject;\n $$reject(r);\n return capability.promise;\n }\n});\n$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {\n // 25.4.4.6 Promise.resolve(x)\n resolve: function resolve(x) {\n return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);\n }\n});\n$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) {\n $Promise.all(iter)['catch'](empty);\n})), PROMISE, {\n // 25.4.4.1 Promise.all(iterable)\n all: function all(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var resolve = capability.resolve;\n var reject = capability.reject;\n var result = perform(function () {\n var values = [];\n var index = 0;\n var remaining = 1;\n forOf(iterable, false, function (promise) {\n var $index = index++;\n var alreadyCalled = false;\n values.push(undefined);\n remaining++;\n C.resolve(promise).then(function (value) {\n if (alreadyCalled) return;\n alreadyCalled = true;\n values[$index] = value;\n --remaining || resolve(values);\n }, reject);\n });\n --remaining || resolve(values);\n });\n if (result.e) reject(result.v);\n return capability.promise;\n },\n // 25.4.4.4 Promise.race(iterable)\n race: function race(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var reject = capability.reject;\n var result = perform(function () {\n forOf(iterable, false, function (promise) {\n C.resolve(promise).then(capability.resolve, reject);\n });\n });\n if (result.e) reject(result.v);\n return capability.promise;\n }\n});\n","exports.f = require('./_wks');\n","var global = require('./_global');\nvar core = require('./_core');\nvar LIBRARY = require('./_library');\nvar wksExt = require('./_wks-ext');\nvar defineProperty = require('./_object-dp').f;\nmodule.exports = function (name) {\n var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});\n if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) });\n};\n","// all enumerable object keys, includes symbols\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nmodule.exports = function (it) {\n var result = getKeys(it);\n var getSymbols = gOPS.f;\n if (getSymbols) {\n var symbols = getSymbols(it);\n var isEnum = pIE.f;\n var i = 0;\n var key;\n while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key);\n } return result;\n};\n","// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window\nvar toIObject = require('./_to-iobject');\nvar gOPN = require('./_object-gopn').f;\nvar toString = {}.toString;\n\nvar windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames\n ? Object.getOwnPropertyNames(window) : [];\n\nvar getWindowNames = function (it) {\n try {\n return gOPN(it);\n } catch (e) {\n return windowNames.slice();\n }\n};\n\nmodule.exports.f = function getOwnPropertyNames(it) {\n return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));\n};\n","'use strict';\n// ECMAScript 6 symbols shim\nvar global = require('./_global');\nvar has = require('./_has');\nvar DESCRIPTORS = require('./_descriptors');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar META = require('./_meta').KEY;\nvar $fails = require('./_fails');\nvar shared = require('./_shared');\nvar setToStringTag = require('./_set-to-string-tag');\nvar uid = require('./_uid');\nvar wks = require('./_wks');\nvar wksExt = require('./_wks-ext');\nvar wksDefine = require('./_wks-define');\nvar enumKeys = require('./_enum-keys');\nvar isArray = require('./_is-array');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar createDesc = require('./_property-desc');\nvar _create = require('./_object-create');\nvar gOPNExt = require('./_object-gopn-ext');\nvar $GOPD = require('./_object-gopd');\nvar $DP = require('./_object-dp');\nvar $keys = require('./_object-keys');\nvar gOPD = $GOPD.f;\nvar dP = $DP.f;\nvar gOPN = gOPNExt.f;\nvar $Symbol = global.Symbol;\nvar $JSON = global.JSON;\nvar _stringify = $JSON && $JSON.stringify;\nvar PROTOTYPE = 'prototype';\nvar HIDDEN = wks('_hidden');\nvar TO_PRIMITIVE = wks('toPrimitive');\nvar isEnum = {}.propertyIsEnumerable;\nvar SymbolRegistry = shared('symbol-registry');\nvar AllSymbols = shared('symbols');\nvar OPSymbols = shared('op-symbols');\nvar ObjectProto = Object[PROTOTYPE];\nvar USE_NATIVE = typeof $Symbol == 'function';\nvar QObject = global.QObject;\n// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173\nvar setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;\n\n// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687\nvar setSymbolDesc = DESCRIPTORS && $fails(function () {\n return _create(dP({}, 'a', {\n get: function () { return dP(this, 'a', { value: 7 }).a; }\n })).a != 7;\n}) ? function (it, key, D) {\n var protoDesc = gOPD(ObjectProto, key);\n if (protoDesc) delete ObjectProto[key];\n dP(it, key, D);\n if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);\n} : dP;\n\nvar wrap = function (tag) {\n var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);\n sym._k = tag;\n return sym;\n};\n\nvar isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) {\n return typeof it == 'symbol';\n} : function (it) {\n return it instanceof $Symbol;\n};\n\nvar $defineProperty = function defineProperty(it, key, D) {\n if (it === ObjectProto) $defineProperty(OPSymbols, key, D);\n anObject(it);\n key = toPrimitive(key, true);\n anObject(D);\n if (has(AllSymbols, key)) {\n if (!D.enumerable) {\n if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));\n it[HIDDEN][key] = true;\n } else {\n if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;\n D = _create(D, { enumerable: createDesc(0, false) });\n } return setSymbolDesc(it, key, D);\n } return dP(it, key, D);\n};\nvar $defineProperties = function defineProperties(it, P) {\n anObject(it);\n var keys = enumKeys(P = toIObject(P));\n var i = 0;\n var l = keys.length;\n var key;\n while (l > i) $defineProperty(it, key = keys[i++], P[key]);\n return it;\n};\nvar $create = function create(it, P) {\n return P === undefined ? _create(it) : $defineProperties(_create(it), P);\n};\nvar $propertyIsEnumerable = function propertyIsEnumerable(key) {\n var E = isEnum.call(this, key = toPrimitive(key, true));\n if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;\n return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;\n};\nvar $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {\n it = toIObject(it);\n key = toPrimitive(key, true);\n if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;\n var D = gOPD(it, key);\n if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;\n return D;\n};\nvar $getOwnPropertyNames = function getOwnPropertyNames(it) {\n var names = gOPN(toIObject(it));\n var result = [];\n var i = 0;\n var key;\n while (names.length > i) {\n if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);\n } return result;\n};\nvar $getOwnPropertySymbols = function getOwnPropertySymbols(it) {\n var IS_OP = it === ObjectProto;\n var names = gOPN(IS_OP ? OPSymbols : toIObject(it));\n var result = [];\n var i = 0;\n var key;\n while (names.length > i) {\n if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);\n } return result;\n};\n\n// 19.4.1.1 Symbol([description])\nif (!USE_NATIVE) {\n $Symbol = function Symbol() {\n if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');\n var tag = uid(arguments.length > 0 ? arguments[0] : undefined);\n var $set = function (value) {\n if (this === ObjectProto) $set.call(OPSymbols, value);\n if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;\n setSymbolDesc(this, tag, createDesc(1, value));\n };\n if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, { configurable: true, set: $set });\n return wrap(tag);\n };\n redefine($Symbol[PROTOTYPE], 'toString', function toString() {\n return this._k;\n });\n\n $GOPD.f = $getOwnPropertyDescriptor;\n $DP.f = $defineProperty;\n require('./_object-gopn').f = gOPNExt.f = $getOwnPropertyNames;\n require('./_object-pie').f = $propertyIsEnumerable;\n require('./_object-gops').f = $getOwnPropertySymbols;\n\n if (DESCRIPTORS && !require('./_library')) {\n redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);\n }\n\n wksExt.f = function (name) {\n return wrap(wks(name));\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol });\n\nfor (var es6Symbols = (\n // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14\n 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'\n).split(','), j = 0; es6Symbols.length > j;)wks(es6Symbols[j++]);\n\nfor (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) wksDefine(wellKnownSymbols[k++]);\n\n$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {\n // 19.4.2.1 Symbol.for(key)\n 'for': function (key) {\n return has(SymbolRegistry, key += '')\n ? SymbolRegistry[key]\n : SymbolRegistry[key] = $Symbol(key);\n },\n // 19.4.2.5 Symbol.keyFor(sym)\n keyFor: function keyFor(sym) {\n if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');\n for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key;\n },\n useSetter: function () { setter = true; },\n useSimple: function () { setter = false; }\n});\n\n$export($export.S + $export.F * !USE_NATIVE, 'Object', {\n // 19.1.2.2 Object.create(O [, Properties])\n create: $create,\n // 19.1.2.4 Object.defineProperty(O, P, Attributes)\n defineProperty: $defineProperty,\n // 19.1.2.3 Object.defineProperties(O, Properties)\n defineProperties: $defineProperties,\n // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)\n getOwnPropertyDescriptor: $getOwnPropertyDescriptor,\n // 19.1.2.7 Object.getOwnPropertyNames(O)\n getOwnPropertyNames: $getOwnPropertyNames,\n // 19.1.2.8 Object.getOwnPropertySymbols(O)\n getOwnPropertySymbols: $getOwnPropertySymbols\n});\n\n// 24.3.2 JSON.stringify(value [, replacer [, space]])\n$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {\n var S = $Symbol();\n // MS Edge converts symbol values to JSON as {}\n // WebKit converts symbol values to JSON as null\n // V8 throws on boxed symbols\n return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';\n})), 'JSON', {\n stringify: function stringify(it) {\n var args = [it];\n var i = 1;\n var replacer, $replacer;\n while (arguments.length > i) args.push(arguments[i++]);\n $replacer = replacer = args[1];\n if (!isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined\n if (!isArray(replacer)) replacer = function (key, value) {\n if (typeof $replacer == 'function') value = $replacer.call(this, key, value);\n if (!isSymbol(value)) return value;\n };\n args[1] = replacer;\n return _stringify.apply($JSON, args);\n }\n});\n\n// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)\n$Symbol[PROTOTYPE][TO_PRIMITIVE] || require('./_hide')($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);\n// 19.4.3.5 Symbol.prototype[@@toStringTag]\nsetToStringTag($Symbol, 'Symbol');\n// 20.2.1.9 Math[@@toStringTag]\nsetToStringTag(Math, 'Math', true);\n// 24.3.3 JSON[@@toStringTag]\nsetToStringTag(global.JSON, 'JSON', true);\n","// most Object methods by ES6 should accept primitives\nvar $export = require('./_export');\nvar core = require('./_core');\nvar fails = require('./_fails');\nmodule.exports = function (KEY, exec) {\n var fn = (core.Object || {})[KEY] || Object[KEY];\n var exp = {};\n exp[KEY] = exec(fn);\n $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp);\n};\n","// 19.1.2.5 Object.freeze(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('freeze', function ($freeze) {\n return function freeze(it) {\n return $freeze && isObject(it) ? $freeze(meta(it)) : it;\n };\n});\n","// 19.1.2.17 Object.seal(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('seal', function ($seal) {\n return function seal(it) {\n return $seal && isObject(it) ? $seal(meta(it)) : it;\n };\n});\n","// 19.1.2.15 Object.preventExtensions(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('preventExtensions', function ($preventExtensions) {\n return function preventExtensions(it) {\n return $preventExtensions && isObject(it) ? $preventExtensions(meta(it)) : it;\n };\n});\n","// 19.1.2.12 Object.isFrozen(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isFrozen', function ($isFrozen) {\n return function isFrozen(it) {\n return isObject(it) ? $isFrozen ? $isFrozen(it) : false : true;\n };\n});\n","// 19.1.2.13 Object.isSealed(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isSealed', function ($isSealed) {\n return function isSealed(it) {\n return isObject(it) ? $isSealed ? $isSealed(it) : false : true;\n };\n});\n","// 19.1.2.11 Object.isExtensible(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isExtensible', function ($isExtensible) {\n return function isExtensible(it) {\n return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false;\n };\n});\n","// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)\nvar toIObject = require('./_to-iobject');\nvar $getOwnPropertyDescriptor = require('./_object-gopd').f;\n\nrequire('./_object-sap')('getOwnPropertyDescriptor', function () {\n return function getOwnPropertyDescriptor(it, key) {\n return $getOwnPropertyDescriptor(toIObject(it), key);\n };\n});\n","// 19.1.2.9 Object.getPrototypeOf(O)\nvar toObject = require('./_to-object');\nvar $getPrototypeOf = require('./_object-gpo');\n\nrequire('./_object-sap')('getPrototypeOf', function () {\n return function getPrototypeOf(it) {\n return $getPrototypeOf(toObject(it));\n };\n});\n","// 19.1.2.14 Object.keys(O)\nvar toObject = require('./_to-object');\nvar $keys = require('./_object-keys');\n\nrequire('./_object-sap')('keys', function () {\n return function keys(it) {\n return $keys(toObject(it));\n };\n});\n","// 19.1.2.7 Object.getOwnPropertyNames(O)\nrequire('./_object-sap')('getOwnPropertyNames', function () {\n return require('./_object-gopn-ext').f;\n});\n","// 19.1.3.1 Object.assign(target, source)\nvar $export = require('./_export');\n\n$export($export.S + $export.F, 'Object', { assign: require('./_object-assign') });\n","// 7.2.9 SameValue(x, y)\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare\n return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;\n};\n","// 19.1.3.10 Object.is(value1, value2)\nvar $export = require('./_export');\n$export($export.S, 'Object', { is: require('./_same-value') });\n","var dP = require('./_object-dp').f;\nvar FProto = Function.prototype;\nvar nameRE = /^\\s*function ([^ (]*)/;\nvar NAME = 'name';\n\n// 19.2.4.2 name\nNAME in FProto || require('./_descriptors') && dP(FProto, NAME, {\n configurable: true,\n get: function () {\n try {\n return ('' + this).match(nameRE)[1];\n } catch (e) {\n return '';\n }\n }\n});\n","var $export = require('./_export');\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\n\n$export($export.S, 'String', {\n // 21.1.2.4 String.raw(callSite, ...substitutions)\n raw: function raw(callSite) {\n var tpl = toIObject(callSite.raw);\n var len = toLength(tpl.length);\n var aLen = arguments.length;\n var res = [];\n var i = 0;\n while (len > i) {\n res.push(String(tpl[i++]));\n if (i < aLen) res.push(String(arguments[i]));\n } return res.join('');\n }\n});\n","var $export = require('./_export');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar fromCharCode = String.fromCharCode;\nvar $fromCodePoint = String.fromCodePoint;\n\n// length should be 1, old FF problem\n$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {\n // 21.1.2.2 String.fromCodePoint(...codePoints)\n fromCodePoint: function fromCodePoint(x) { // eslint-disable-line no-unused-vars\n var res = [];\n var aLen = arguments.length;\n var i = 0;\n var code;\n while (aLen > i) {\n code = +arguments[i++];\n if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');\n res.push(code < 0x10000\n ? fromCharCode(code)\n : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00)\n );\n } return res.join('');\n }\n});\n","var toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n// true -> String#at\n// false -> String#codePointAt\nmodule.exports = function (TO_STRING) {\n return function (that, pos) {\n var s = String(defined(that));\n var i = toInteger(pos);\n var l = s.length;\n var a, b;\n if (i < 0 || i >= l) return TO_STRING ? '' : undefined;\n a = s.charCodeAt(i);\n return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff\n ? TO_STRING ? s.charAt(i) : a\n : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;\n };\n};\n","'use strict';\nvar $export = require('./_export');\nvar $at = require('./_string-at')(false);\n$export($export.P, 'String', {\n // 21.1.3.3 String.prototype.codePointAt(pos)\n codePointAt: function codePointAt(pos) {\n return $at(this, pos);\n }\n});\n","'use strict';\nvar toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n\nmodule.exports = function repeat(count) {\n var str = String(defined(this));\n var res = '';\n var n = toInteger(count);\n if (n < 0 || n == Infinity) throw RangeError(\"Count can't be negative\");\n for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) res += str;\n return res;\n};\n","var $export = require('./_export');\n\n$export($export.P, 'String', {\n // 21.1.3.13 String.prototype.repeat(count)\n repeat: require('./_string-repeat')\n});\n","// 7.2.8 IsRegExp(argument)\nvar isObject = require('./_is-object');\nvar cof = require('./_cof');\nvar MATCH = require('./_wks')('match');\nmodule.exports = function (it) {\n var isRegExp;\n return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');\n};\n","// helper for String#{startsWith, endsWith, includes}\nvar isRegExp = require('./_is-regexp');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, searchString, NAME) {\n if (isRegExp(searchString)) throw TypeError('String#' + NAME + \" doesn't accept regex!\");\n return String(defined(that));\n};\n","var MATCH = require('./_wks')('match');\nmodule.exports = function (KEY) {\n var re = /./;\n try {\n '/./'[KEY](re);\n } catch (e) {\n try {\n re[MATCH] = false;\n return !'/./'[KEY](re);\n } catch (f) { /* empty */ }\n } return true;\n};\n","// 21.1.3.18 String.prototype.startsWith(searchString [, position ])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar STARTS_WITH = 'startsWith';\nvar $startsWith = ''[STARTS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(STARTS_WITH), 'String', {\n startsWith: function startsWith(searchString /* , position = 0 */) {\n var that = context(this, searchString, STARTS_WITH);\n var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));\n var search = String(searchString);\n return $startsWith\n ? $startsWith.call(that, search, index)\n : that.slice(index, index + search.length) === search;\n }\n});\n","// 21.1.3.6 String.prototype.endsWith(searchString [, endPosition])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar ENDS_WITH = 'endsWith';\nvar $endsWith = ''[ENDS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(ENDS_WITH), 'String', {\n endsWith: function endsWith(searchString /* , endPosition = @length */) {\n var that = context(this, searchString, ENDS_WITH);\n var endPosition = arguments.length > 1 ? arguments[1] : undefined;\n var len = toLength(that.length);\n var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len);\n var search = String(searchString);\n return $endsWith\n ? $endsWith.call(that, search, end)\n : that.slice(end - search.length, end) === search;\n }\n});\n","// 21.1.3.7 String.prototype.includes(searchString, position = 0)\n'use strict';\nvar $export = require('./_export');\nvar context = require('./_string-context');\nvar INCLUDES = 'includes';\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(INCLUDES), 'String', {\n includes: function includes(searchString /* , position = 0 */) {\n return !!~context(this, searchString, INCLUDES)\n .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","'use strict';\n// 21.2.5.3 get RegExp.prototype.flags\nvar anObject = require('./_an-object');\nmodule.exports = function () {\n var that = anObject(this);\n var result = '';\n if (that.global) result += 'g';\n if (that.ignoreCase) result += 'i';\n if (that.multiline) result += 'm';\n if (that.unicode) result += 'u';\n if (that.sticky) result += 'y';\n return result;\n};\n","// 21.2.5.3 get RegExp.prototype.flags()\nif (require('./_descriptors') && /./g.flags != 'g') require('./_object-dp').f(RegExp.prototype, 'flags', {\n configurable: true,\n get: require('./_flags')\n});\n","'use strict';\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar fails = require('./_fails');\nvar defined = require('./_defined');\nvar wks = require('./_wks');\n\nmodule.exports = function (KEY, length, exec) {\n var SYMBOL = wks(KEY);\n var fns = exec(defined, SYMBOL, ''[KEY]);\n var strfn = fns[0];\n var rxfn = fns[1];\n if (fails(function () {\n var O = {};\n O[SYMBOL] = function () { return 7; };\n return ''[KEY](O) != 7;\n })) {\n redefine(String.prototype, KEY, strfn);\n hide(RegExp.prototype, SYMBOL, length == 2\n // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)\n // 21.2.5.11 RegExp.prototype[@@split](string, limit)\n ? function (string, arg) { return rxfn.call(string, this, arg); }\n // 21.2.5.6 RegExp.prototype[@@match](string)\n // 21.2.5.9 RegExp.prototype[@@search](string)\n : function (string) { return rxfn.call(string, this); }\n );\n }\n};\n","// @@match logic\nrequire('./_fix-re-wks')('match', 1, function (defined, MATCH, $match) {\n // 21.1.3.11 String.prototype.match(regexp)\n return [function match(regexp) {\n 'use strict';\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[MATCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));\n }, $match];\n});\n","// @@replace logic\nrequire('./_fix-re-wks')('replace', 2, function (defined, REPLACE, $replace) {\n // 21.1.3.14 String.prototype.replace(searchValue, replaceValue)\n return [function replace(searchValue, replaceValue) {\n 'use strict';\n var O = defined(this);\n var fn = searchValue == undefined ? undefined : searchValue[REPLACE];\n return fn !== undefined\n ? fn.call(searchValue, O, replaceValue)\n : $replace.call(String(O), searchValue, replaceValue);\n }, $replace];\n});\n","// @@split logic\nrequire('./_fix-re-wks')('split', 2, function (defined, SPLIT, $split) {\n 'use strict';\n var isRegExp = require('./_is-regexp');\n var _split = $split;\n var $push = [].push;\n var $SPLIT = 'split';\n var LENGTH = 'length';\n var LAST_INDEX = 'lastIndex';\n if (\n 'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||\n 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||\n 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||\n '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||\n '.'[$SPLIT](/()()/)[LENGTH] > 1 ||\n ''[$SPLIT](/.?/)[LENGTH]\n ) {\n var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group\n // based on es5-shim implementation, need to rework it\n $split = function (separator, limit) {\n var string = String(this);\n if (separator === undefined && limit === 0) return [];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) return _split.call(string, separator, limit);\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n var splitLimit = limit === undefined ? 4294967295 : limit >>> 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var separator2, match, lastIndex, lastLength, i;\n // Doesn't need flags gy, but they don't hurt\n if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\\\s)', flags);\n while (match = separatorCopy.exec(string)) {\n // `separatorCopy.lastIndex` is not reliable cross-browser\n lastIndex = match.index + match[0][LENGTH];\n if (lastIndex > lastLastIndex) {\n output.push(string.slice(lastLastIndex, match.index));\n // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG\n // eslint-disable-next-line no-loop-func\n if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () {\n for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined;\n });\n if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));\n lastLength = match[0][LENGTH];\n lastLastIndex = lastIndex;\n if (output[LENGTH] >= splitLimit) break;\n }\n if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop\n }\n if (lastLastIndex === string[LENGTH]) {\n if (lastLength || !separatorCopy.test('')) output.push('');\n } else output.push(string.slice(lastLastIndex));\n return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;\n };\n // Chakra, V8\n } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {\n $split = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit);\n };\n }\n // 21.1.3.17 String.prototype.split(separator, limit)\n return [function split(separator, limit) {\n var O = defined(this);\n var fn = separator == undefined ? undefined : separator[SPLIT];\n return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit);\n }, $split];\n});\n","// @@search logic\nrequire('./_fix-re-wks')('search', 1, function (defined, SEARCH, $search) {\n // 21.1.3.15 String.prototype.search(regexp)\n return [function search(regexp) {\n 'use strict';\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[SEARCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));\n }, $search];\n});\n","'use strict';\nvar $defineProperty = require('./_object-dp');\nvar createDesc = require('./_property-desc');\n\nmodule.exports = function (object, index, value) {\n if (index in object) $defineProperty.f(object, index, createDesc(0, value));\n else object[index] = value;\n};\n","'use strict';\nvar ctx = require('./_ctx');\nvar $export = require('./_export');\nvar toObject = require('./_to-object');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar toLength = require('./_to-length');\nvar createProperty = require('./_create-property');\nvar getIterFn = require('./core.get-iterator-method');\n\n$export($export.S + $export.F * !require('./_iter-detect')(function (iter) { Array.from(iter); }), 'Array', {\n // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)\n from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {\n var O = toObject(arrayLike);\n var C = typeof this == 'function' ? this : Array;\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var index = 0;\n var iterFn = getIterFn(O);\n var length, result, step, iterator;\n if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);\n // if object isn't iterable or it's array with default iterator - use simple case\n if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {\n for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {\n createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);\n }\n } else {\n length = toLength(O.length);\n for (result = new C(length); length > index; index++) {\n createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);\n }\n }\n result.length = index;\n return result;\n }\n});\n","'use strict';\nvar $export = require('./_export');\nvar createProperty = require('./_create-property');\n\n// WebKit Array.of isn't generic\n$export($export.S + $export.F * require('./_fails')(function () {\n function F() { /* empty */ }\n return !(Array.of.call(F) instanceof F);\n}), 'Array', {\n // 22.1.2.3 Array.of( ...items)\n of: function of(/* ...args */) {\n var index = 0;\n var aLen = arguments.length;\n var result = new (typeof this == 'function' ? this : Array)(aLen);\n while (aLen > index) createProperty(result, index, arguments[index++]);\n result.length = aLen;\n return result;\n }\n});\n","// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)\nvar $export = require('./_export');\n\n$export($export.P, 'Array', { copyWithin: require('./_array-copy-within') });\n\nrequire('./_add-to-unscopables')('copyWithin');\n","'use strict';\n// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(5);\nvar KEY = 'find';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n find: function find(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","'use strict';\n// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(6);\nvar KEY = 'findIndex';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n findIndex: function findIndex(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)\nvar $export = require('./_export');\n\n$export($export.P, 'Array', { fill: require('./_array-fill') });\n\nrequire('./_add-to-unscopables')('fill');\n","// 20.1.2.2 Number.isFinite(number)\nvar $export = require('./_export');\nvar _isFinite = require('./_global').isFinite;\n\n$export($export.S, 'Number', {\n isFinite: function isFinite(it) {\n return typeof it == 'number' && _isFinite(it);\n }\n});\n","// 20.1.2.3 Number.isInteger(number)\nvar isObject = require('./_is-object');\nvar floor = Math.floor;\nmodule.exports = function isInteger(it) {\n return !isObject(it) && isFinite(it) && floor(it) === it;\n};\n","// 20.1.2.3 Number.isInteger(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { isInteger: require('./_is-integer') });\n","// 20.1.2.5 Number.isSafeInteger(number)\nvar $export = require('./_export');\nvar isInteger = require('./_is-integer');\nvar abs = Math.abs;\n\n$export($export.S, 'Number', {\n isSafeInteger: function isSafeInteger(number) {\n return isInteger(number) && abs(number) <= 0x1fffffffffffff;\n }\n});\n","// 20.1.2.4 Number.isNaN(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', {\n isNaN: function isNaN(number) {\n // eslint-disable-next-line no-self-compare\n return number != number;\n }\n});\n","// 20.1.2.1 Number.EPSILON\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { EPSILON: Math.pow(2, -52) });\n","// 20.1.2.10 Number.MIN_SAFE_INTEGER\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff });\n","// 20.1.2.6 Number.MAX_SAFE_INTEGER\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff });\n","// 20.2.2.20 Math.log1p(x)\nmodule.exports = Math.log1p || function log1p(x) {\n return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x);\n};\n","// 20.2.2.3 Math.acosh(x)\nvar $export = require('./_export');\nvar log1p = require('./_math-log1p');\nvar sqrt = Math.sqrt;\nvar $acosh = Math.acosh;\n\n$export($export.S + $export.F * !($acosh\n // V8 bug: https://code.google.com/p/v8/issues/detail?id=3509\n && Math.floor($acosh(Number.MAX_VALUE)) == 710\n // Tor Browser bug: Math.acosh(Infinity) -> NaN\n && $acosh(Infinity) == Infinity\n), 'Math', {\n acosh: function acosh(x) {\n return (x = +x) < 1 ? NaN : x > 94906265.62425156\n ? Math.log(x) + Math.LN2\n : log1p(x - 1 + sqrt(x - 1) * sqrt(x + 1));\n }\n});\n","// 20.2.2.5 Math.asinh(x)\nvar $export = require('./_export');\nvar $asinh = Math.asinh;\n\nfunction asinh(x) {\n return !isFinite(x = +x) || x == 0 ? x : x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1));\n}\n\n// Tor Browser bug: Math.asinh(0) -> -0\n$export($export.S + $export.F * !($asinh && 1 / $asinh(0) > 0), 'Math', { asinh: asinh });\n","// 20.2.2.7 Math.atanh(x)\nvar $export = require('./_export');\nvar $atanh = Math.atanh;\n\n// Tor Browser bug: Math.atanh(-0) -> 0\n$export($export.S + $export.F * !($atanh && 1 / $atanh(-0) < 0), 'Math', {\n atanh: function atanh(x) {\n return (x = +x) == 0 ? x : Math.log((1 + x) / (1 - x)) / 2;\n }\n});\n","// 20.2.2.28 Math.sign(x)\nmodule.exports = Math.sign || function sign(x) {\n // eslint-disable-next-line no-self-compare\n return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;\n};\n","// 20.2.2.9 Math.cbrt(x)\nvar $export = require('./_export');\nvar sign = require('./_math-sign');\n\n$export($export.S, 'Math', {\n cbrt: function cbrt(x) {\n return sign(x = +x) * Math.pow(Math.abs(x), 1 / 3);\n }\n});\n","// 20.2.2.11 Math.clz32(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n clz32: function clz32(x) {\n return (x >>>= 0) ? 31 - Math.floor(Math.log(x + 0.5) * Math.LOG2E) : 32;\n }\n});\n","// 20.2.2.12 Math.cosh(x)\nvar $export = require('./_export');\nvar exp = Math.exp;\n\n$export($export.S, 'Math', {\n cosh: function cosh(x) {\n return (exp(x = +x) + exp(-x)) / 2;\n }\n});\n","// 20.2.2.14 Math.expm1(x)\nvar $expm1 = Math.expm1;\nmodule.exports = (!$expm1\n // Old FF bug\n || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168\n // Tor Browser bug\n || $expm1(-2e-17) != -2e-17\n) ? function expm1(x) {\n return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1;\n} : $expm1;\n","// 20.2.2.14 Math.expm1(x)\nvar $export = require('./_export');\nvar $expm1 = require('./_math-expm1');\n\n$export($export.S + $export.F * ($expm1 != Math.expm1), 'Math', { expm1: $expm1 });\n","// 20.2.2.16 Math.fround(x)\nvar sign = require('./_math-sign');\nvar pow = Math.pow;\nvar EPSILON = pow(2, -52);\nvar EPSILON32 = pow(2, -23);\nvar MAX32 = pow(2, 127) * (2 - EPSILON32);\nvar MIN32 = pow(2, -126);\n\nvar roundTiesToEven = function (n) {\n return n + 1 / EPSILON - 1 / EPSILON;\n};\n\nmodule.exports = Math.fround || function fround(x) {\n var $abs = Math.abs(x);\n var $sign = sign(x);\n var a, result;\n if ($abs < MIN32) return $sign * roundTiesToEven($abs / MIN32 / EPSILON32) * MIN32 * EPSILON32;\n a = (1 + EPSILON32 / EPSILON) * $abs;\n result = a - (a - $abs);\n // eslint-disable-next-line no-self-compare\n if (result > MAX32 || result != result) return $sign * Infinity;\n return $sign * result;\n};\n","// 20.2.2.16 Math.fround(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { fround: require('./_math-fround') });\n","// 20.2.2.17 Math.hypot([value1[, value2[, … ]]])\nvar $export = require('./_export');\nvar abs = Math.abs;\n\n$export($export.S, 'Math', {\n hypot: function hypot(value1, value2) { // eslint-disable-line no-unused-vars\n var sum = 0;\n var i = 0;\n var aLen = arguments.length;\n var larg = 0;\n var arg, div;\n while (i < aLen) {\n arg = abs(arguments[i++]);\n if (larg < arg) {\n div = larg / arg;\n sum = sum * div * div + 1;\n larg = arg;\n } else if (arg > 0) {\n div = arg / larg;\n sum += div * div;\n } else sum += arg;\n }\n return larg === Infinity ? Infinity : larg * Math.sqrt(sum);\n }\n});\n","// 20.2.2.18 Math.imul(x, y)\nvar $export = require('./_export');\nvar $imul = Math.imul;\n\n// some WebKit versions fails with big numbers, some has wrong arity\n$export($export.S + $export.F * require('./_fails')(function () {\n return $imul(0xffffffff, 5) != -5 || $imul.length != 2;\n}), 'Math', {\n imul: function imul(x, y) {\n var UINT16 = 0xffff;\n var xn = +x;\n var yn = +y;\n var xl = UINT16 & xn;\n var yl = UINT16 & yn;\n return 0 | xl * yl + ((UINT16 & xn >>> 16) * yl + xl * (UINT16 & yn >>> 16) << 16 >>> 0);\n }\n});\n","// 20.2.2.20 Math.log1p(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { log1p: require('./_math-log1p') });\n","// 20.2.2.21 Math.log10(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n log10: function log10(x) {\n return Math.log(x) * Math.LOG10E;\n }\n});\n","// 20.2.2.22 Math.log2(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n log2: function log2(x) {\n return Math.log(x) / Math.LN2;\n }\n});\n","// 20.2.2.28 Math.sign(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { sign: require('./_math-sign') });\n","// 20.2.2.30 Math.sinh(x)\nvar $export = require('./_export');\nvar expm1 = require('./_math-expm1');\nvar exp = Math.exp;\n\n// V8 near Chromium 38 has a problem with very small numbers\n$export($export.S + $export.F * require('./_fails')(function () {\n return !Math.sinh(-2e-17) != -2e-17;\n}), 'Math', {\n sinh: function sinh(x) {\n return Math.abs(x = +x) < 1\n ? (expm1(x) - expm1(-x)) / 2\n : (exp(x - 1) - exp(-x - 1)) * (Math.E / 2);\n }\n});\n","// 20.2.2.33 Math.tanh(x)\nvar $export = require('./_export');\nvar expm1 = require('./_math-expm1');\nvar exp = Math.exp;\n\n$export($export.S, 'Math', {\n tanh: function tanh(x) {\n var a = expm1(x = +x);\n var b = expm1(-x);\n return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (exp(x) + exp(-x));\n }\n});\n","// 20.2.2.34 Math.trunc(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n trunc: function trunc(it) {\n return (it > 0 ? Math.floor : Math.ceil)(it);\n }\n});\n","'use strict';\n// https://github.com/tc39/Array.prototype.includes\nvar $export = require('./_export');\nvar $includes = require('./_array-includes')(true);\n\n$export($export.P, 'Array', {\n includes: function includes(el /* , fromIndex = 0 */) {\n return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n\nrequire('./_add-to-unscopables')('includes');\n","var getKeys = require('./_object-keys');\nvar toIObject = require('./_to-iobject');\nvar isEnum = require('./_object-pie').f;\nmodule.exports = function (isEntries) {\n return function (it) {\n var O = toIObject(it);\n var keys = getKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) if (isEnum.call(O, key = keys[i++])) {\n result.push(isEntries ? [key, O[key]] : O[key]);\n } return result;\n };\n};\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $values = require('./_object-to-array')(false);\n\n$export($export.S, 'Object', {\n values: function values(it) {\n return $values(it);\n }\n});\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $entries = require('./_object-to-array')(true);\n\n$export($export.S, 'Object', {\n entries: function entries(it) {\n return $entries(it);\n }\n});\n","// https://github.com/tc39/proposal-object-getownpropertydescriptors\nvar $export = require('./_export');\nvar ownKeys = require('./_own-keys');\nvar toIObject = require('./_to-iobject');\nvar gOPD = require('./_object-gopd');\nvar createProperty = require('./_create-property');\n\n$export($export.S, 'Object', {\n getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {\n var O = toIObject(object);\n var getDesc = gOPD.f;\n var keys = ownKeys(O);\n var result = {};\n var i = 0;\n var key, desc;\n while (keys.length > i) {\n desc = getDesc(O, key = keys[i++]);\n if (desc !== undefined) createProperty(result, key, desc);\n }\n return result;\n }\n});\n","// https://github.com/tc39/proposal-string-pad-start-end\nvar toLength = require('./_to-length');\nvar repeat = require('./_string-repeat');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, maxLength, fillString, left) {\n var S = String(defined(that));\n var stringLength = S.length;\n var fillStr = fillString === undefined ? ' ' : String(fillString);\n var intMaxLength = toLength(maxLength);\n if (intMaxLength <= stringLength || fillStr == '') return S;\n var fillLen = intMaxLength - stringLength;\n var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));\n if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);\n return left ? stringFiller + S : S + stringFiller;\n};\n","var global = require('./_global');\nvar navigator = global.navigator;\n\nmodule.exports = navigator && navigator.userAgent || '';\n","'use strict';\n// https://github.com/tc39/proposal-string-pad-start-end\nvar $export = require('./_export');\nvar $pad = require('./_string-pad');\nvar userAgent = require('./_user-agent');\n\n// https://github.com/zloirock/core-js/issues/280\n$export($export.P + $export.F * /Version\\/10\\.\\d+(\\.\\d+)? Safari\\//.test(userAgent), 'String', {\n padStart: function padStart(maxLength /* , fillString = ' ' */) {\n return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true);\n }\n});\n","'use strict';\n// https://github.com/tc39/proposal-string-pad-start-end\nvar $export = require('./_export');\nvar $pad = require('./_string-pad');\nvar userAgent = require('./_user-agent');\n\n// https://github.com/zloirock/core-js/issues/280\n$export($export.P + $export.F * /Version\\/10\\.\\d+(\\.\\d+)? Safari\\//.test(userAgent), 'String', {\n padEnd: function padEnd(maxLength /* , fillString = ' ' */) {\n return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false);\n }\n});\n","// ie9- setTimeout & setInterval additional parameters fix\nvar global = require('./_global');\nvar $export = require('./_export');\nvar userAgent = require('./_user-agent');\nvar slice = [].slice;\nvar MSIE = /MSIE .\\./.test(userAgent); // <- dirty ie9- check\nvar wrap = function (set) {\n return function (fn, time /* , ...args */) {\n var boundArgs = arguments.length > 2;\n var args = boundArgs ? slice.call(arguments, 2) : false;\n return set(boundArgs ? function () {\n // eslint-disable-next-line no-new-func\n (typeof fn == 'function' ? fn : Function(fn)).apply(this, args);\n } : fn, time);\n };\n};\n$export($export.G + $export.B + $export.F * MSIE, {\n setTimeout: wrap(global.setTimeout),\n setInterval: wrap(global.setInterval)\n});\n","var $export = require('./_export');\nvar $task = require('./_task');\n$export($export.G + $export.B, {\n setImmediate: $task.set,\n clearImmediate: $task.clear\n});\n","var $iterators = require('./es6.array.iterator');\nvar getKeys = require('./_object-keys');\nvar redefine = require('./_redefine');\nvar global = require('./_global');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar wks = require('./_wks');\nvar ITERATOR = wks('iterator');\nvar TO_STRING_TAG = wks('toStringTag');\nvar ArrayValues = Iterators.Array;\n\nvar DOMIterables = {\n CSSRuleList: true, // TODO: Not spec compliant, should be false.\n CSSStyleDeclaration: false,\n CSSValueList: false,\n ClientRectList: false,\n DOMRectList: false,\n DOMStringList: false,\n DOMTokenList: true,\n DataTransferItemList: false,\n FileList: false,\n HTMLAllCollection: false,\n HTMLCollection: false,\n HTMLFormElement: false,\n HTMLSelectElement: false,\n MediaList: true, // TODO: Not spec compliant, should be false.\n MimeTypeArray: false,\n NamedNodeMap: false,\n NodeList: true,\n PaintRequestList: false,\n Plugin: false,\n PluginArray: false,\n SVGLengthList: false,\n SVGNumberList: false,\n SVGPathSegList: false,\n SVGPointList: false,\n SVGStringList: false,\n SVGTransformList: false,\n SourceBufferList: false,\n StyleSheetList: true, // TODO: Not spec compliant, should be false.\n TextTrackCueList: false,\n TextTrackList: false,\n TouchList: false\n};\n\nfor (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {\n var NAME = collections[i];\n var explicit = DOMIterables[NAME];\n var Collection = global[NAME];\n var proto = Collection && Collection.prototype;\n var key;\n if (proto) {\n if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);\n if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);\n Iterators[NAME] = ArrayValues;\n if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true);\n }\n}\n","/**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * https://raw.github.com/facebook/regenerator/master/LICENSE file. An\n * additional grant of patent rights can be found in the PATENTS file in\n * the same directory.\n */\n\n!(function(global) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n var inModule = typeof module === \"object\";\n var runtime = global.regeneratorRuntime;\n if (runtime) {\n if (inModule) {\n // If regeneratorRuntime is defined globally and we're in a module,\n // make the exports object identical to regeneratorRuntime.\n module.exports = runtime;\n }\n // Don't bother evaluating the rest of this file if the runtime was\n // already defined globally.\n return;\n }\n\n // Define the runtime globally (as expected by generated code) as either\n // module.exports (if we're in a module) or a new, empty object.\n runtime = global.regeneratorRuntime = inModule ? module.exports : {};\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n runtime.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunctionPrototype[toStringTagSymbol] =\n GeneratorFunction.displayName = \"GeneratorFunction\";\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n prototype[method] = function(arg) {\n return this._invoke(method, arg);\n };\n });\n }\n\n runtime.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n runtime.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n if (!(toStringTagSymbol in genFun)) {\n genFun[toStringTagSymbol] = \"GeneratorFunction\";\n }\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n runtime.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return Promise.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return Promise.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration. If the Promise is rejected, however, the\n // result for this iteration will be rejected with the same\n // reason. Note that rejections of yielded Promises are not\n // thrown back into the generator function, as is the case\n // when an awaited Promise is rejected. This difference in\n // behavior between yield and await is important, because it\n // allows the consumer to decide what to do with the yielded\n // rejection (swallow it and continue, manually .throw it back\n // into the generator, abandon iteration, whatever). With\n // await, by contrast, there is no opportunity to examine the\n // rejection reason outside the generator function, so the\n // only option is to throw it from the await expression, and\n // let the generator function handle the exception.\n result.value = unwrapped;\n resolve(result);\n }, reject);\n }\n }\n\n if (typeof global.process === \"object\" && global.process.domain) {\n invoke = global.process.domain.bind(invoke);\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new Promise(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n runtime.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n runtime.async = function(innerFn, outerFn, self, tryLocsList) {\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList)\n );\n\n return runtime.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n if (delegate.iterator.return) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n Gp[toStringTagSymbol] = \"Generator\";\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n runtime.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n runtime.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n})(\n // Among the various tricks for obtaining a reference to the global\n // object, this seems to be the most reliable technique that does not\n // use indirect eval (which violates Content Security Policy).\n typeof global === \"object\" ? global :\n typeof window === \"object\" ? window :\n typeof self === \"object\" ? self : this\n);\n","// Polyfill for creating CustomEvents on IE9/10/11\n\n// code pulled from:\n// https://github.com/d4tocchini/customevent-polyfill\n// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill\n\ntry {\n var ce = new window.CustomEvent('test');\n ce.preventDefault();\n if (ce.defaultPrevented !== true) {\n // IE has problems with .preventDefault() on custom events\n // http://stackoverflow.com/questions/23349191\n throw new Error('Could not prevent default');\n }\n} catch(e) {\n var CustomEvent = function(event, params) {\n var evt, origPrevent;\n params = params || {\n bubbles: false,\n cancelable: false,\n detail: undefined\n };\n\n evt = document.createEvent(\"CustomEvent\");\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n origPrevent = evt.preventDefault;\n evt.preventDefault = function () {\n origPrevent.call(this);\n try {\n Object.defineProperty(this, 'defaultPrevented', {\n get: function () {\n return true;\n }\n });\n } catch(e) {\n this.defaultPrevented = true;\n }\n };\n return evt;\n };\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent; // expose definition to window\n}\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText`\n result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\nexport default { providers, types };\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport loadjs from 'loadjs';\nimport support from './support';\nimport { providers } from './types';\n\nconst utils = {\n // Check variable types\n is: {\n plyr(input) {\n return this.instanceof(input, window.Plyr);\n },\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.nullOrUndefined(input) && Array.isArray(input);\n },\n weakMap(input) {\n return this.instanceof(input, window.WeakMap);\n },\n nodeList(input) {\n return this.instanceof(input, window.NodeList);\n },\n element(input) {\n return this.instanceof(input, window.Element);\n },\n textNode(input) {\n return this.getConstructor(input) === Text;\n },\n event(input) {\n return this.instanceof(input, window.Event);\n },\n cue(input) {\n return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);\n },\n track(input) {\n return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));\n },\n url(input) {\n return !this.nullOrUndefined(input) && /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-/]))?/.test(input);\n },\n nullOrUndefined(input) {\n return input === null || typeof input === 'undefined';\n },\n empty(input) {\n return (\n this.nullOrUndefined(input) ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||\n (this.object(input) && !Object.keys(input).length)\n );\n },\n instanceof(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n getConstructor(input) {\n return !this.nullOrUndefined(input) ? input.constructor : null;\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Fetch wrapper\n // Using XHR to avoid issues with older browsers\n fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.statusText);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n },\n\n // Load an external script\n loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (!utils.is.string(url)) {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = utils.is.string(id);\n let isCached = false;\n\n const exists = () => document.querySelectorAll(`#${id}`).length;\n\n function injectSprite(data) {\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n // Create container\n const container = document.createElement('div');\n utils.toggleHidden(container, true);\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n injectSprite.call(container, data.content);\n return;\n }\n }\n\n // Get the sprite\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.empty(result)) {\n return;\n }\n\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n injectSprite.call(container, result);\n })\n .catch(() => {});\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new <element>\n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove element(s)\n removeElement(element) {\n if (utils.is.nodeList(element) || utils.is.array(element)) {\n Array.from(element).forEach(utils.removeElement);\n return;\n }\n\n if (!utils.is.element(element) || !utils.is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Replace element\n replaceElement(newChild, oldChild) {\n if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n if (!utils.is.element(element) || utils.is.empty(attributes)) {\n return;\n }\n\n Object.entries(attributes).forEach(([\n key,\n value,\n ]) => {\n element.setAttribute(key, value);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle hidden\n toggleHidden(element, hidden) {\n if (!utils.is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!utils.is.boolean(hide)) {\n hide = !element.hasAttribute('hidden');\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.element(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.element(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus(element = null, toggle = false) {\n if (!utils.is.element(element)) {\n return;\n }\n\n const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n if (toggle) {\n utils.on(this.elements.container, 'keydown', trap, false);\n } else {\n utils.off(this.elements.container, 'keydown', trap, false);\n }\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no elemetns, event, or callback\n if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements) || utils.is.array(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!utils.is.element(element) || utils.is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: utils.is.plyr(this) ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // If multiple elements passed\n if (utils.is.array(element) || utils.is.nodeList(element)) {\n Array.from(element).forEach(target => utils.toggleState(target, input));\n return;\n }\n\n // Bail if no target\n if (!utils.is.element(element)) {\n return;\n }\n\n // Get state\n const pressed = element.getAttribute('aria-pressed') === 'true';\n const state = utils.is.boolean(input) ? input : !pressed;\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Format string\n format(input, ...args) {\n if (utils.is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : '');\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return (current / max * 100).toFixed(2);\n },\n\n // Time helpers\n getHours(value) {\n return parseInt((value / 60 / 60) % 60, 10);\n },\n getMinutes(value) {\n return parseInt((value / 60) % 60, 10);\n },\n getSeconds(value) {\n return parseInt(value % 60, 10);\n },\n\n // Format time to UI friendly string\n formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!utils.is.number(time)) {\n return this.formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = this.getHours(time);\n const mins = this.getMinutes(time);\n const secs = this.getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n },\n\n // Replace all occurances of a string in a string\n replaceAll(input = '', find = '', replace = '') {\n return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n },\n\n // Convert to title case\n toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n },\n\n // Convert string to pascalCase\n toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = utils.replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = utils.replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = utils.toTitleCase(string);\n\n // Convert to pascal case\n return utils.replaceAll(string, ' ', '');\n },\n\n // Convert string to pascalCase\n toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = utils.toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n },\n\n // Deep extend destination object with N more objects\n extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!utils.is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (utils.is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n utils.extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return utils.extend(target, ...sources);\n },\n\n // Remove duplicates in an array\n dedupe(array) {\n if (!utils.is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n },\n\n // Get the closest value in an array\n closest(array, value) {\n if (!utils.is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n },\n\n // Get the provider for a given URL\n getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert a URL to a location object\n parseUrl(url) {\n const parser = document.createElement('a');\n parser.href = url;\n return parser;\n },\n\n // Get URL query parameters\n getUrlParams(input) {\n let search = input;\n\n // Parse URL if needed\n if (input.startsWith('http://') || input.startsWith('https://')) {\n ({ search } = this.parseUrl(input));\n }\n\n if (this.is.empty(search)) {\n return null;\n }\n\n const hashes = search.slice(search.indexOf('?') + 1).split('&');\n\n return hashes.reduce((params, hash) => {\n const [\n key,\n val,\n ] = hash.split('=');\n\n return Object.assign(params, { [key]: decodeURIComponent(val) });\n }, {});\n },\n\n // Convert object to URL parameters\n buildUrlParams(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n get transitionEndEvent() {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return utils.is.string(type) ? events[type] : false;\n },\n\n // Force repaint of element\n repaint(element) {\n setTimeout(() => {\n utils.toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n utils.toggleHidden(element, false);\n }, 0);\n },\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n\n switch (`${provider}:${type}`) {\n case 'html5:video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n case 'html5:audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!this.isHTML5 || !utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Check directly if codecs specified\n if (type.includes('codecs=')) {\n return media.canPlayType(type).replace(/no/, '');\n }\n\n // Type specific checks\n if (this.isVideo) {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.isAudio) {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return null;\n }\n\n return this.media.querySelectorAll('source');\n },\n\n // Get quality levels\n getQualityOptions() {\n if (!this.isHTML5) {\n return null;\n }\n\n // Get sources\n const sources = html5.getSources.call(this);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n // Get <source> with size attribute\n const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size')));\n\n // If none, bail\n if (utils.is.empty(sizes)) {\n return null;\n }\n\n // Reduce to unique list\n return utils.dedupe(sizes.map(source => Number(source.getAttribute('size'))));\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source);\n\n if (utils.is.empty(matches)) {\n return null;\n }\n\n return Number(matches[0].getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return;\n }\n\n // Get matches for requested size\n const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input);\n\n // No matches for requested size\n if (utils.is.empty(matches)) {\n return;\n }\n\n // Get supported sources\n const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type')));\n\n // No supported sources\n if (utils.is.empty(supported)) {\n return;\n }\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality: input,\n });\n\n // Get current state\n const { currentTime, playing } = player;\n\n // Set new source\n player.media.src = supported[0].getAttribute('src');\n\n // Load new source\n player.media.load();\n\n // Resume playing\n if (playing) {\n player.play();\n }\n\n // Restore time\n player.currentTime = currentTime;\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n utils.removeElement(html5.getSources());\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport utils from './utils';\n\nconst i18n = {\n get(key = '', config = {}) {\n if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {\n return '';\n }\n\n let string = config.i18n[key];\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([\n key,\n value,\n ]) => {\n string = utils.replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n ui.updateVolume.call(this);\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n utils.dispatchEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Set the poster image\n ui.setPoster.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Set the poster image\n setPoster() {\n if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) {\n return;\n }\n\n // Set the inline style\n const posters = this.poster.split(',');\n this.elements.poster.style.backgroundImage = posters.map(p => `url('${p}')`).join(',');\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set ARIA state\n utils.toggleState(this.elements.buttons.play, this.playing);\n\n // Only update controls on non timeupdate events\n if (utils.is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n this.toggleControls(!this.playing);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = [\n 'stalled',\n 'waiting',\n ].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Check if media failed to load\n checkFailed() {\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState\n this.failed = this.media.networkState === 3;\n\n if (this.failed) {\n utils.toggleClass(this.elements.container, this.config.classNames.loading, false);\n utils.toggleClass(this.elements.container, this.config.classNames.error, true);\n }\n\n // Clear timer\n clearTimeout(this.timers.failed);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.element(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (utils.is.element(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!utils.is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set <progress> value\n setProgress(target, input) {\n const value = utils.is.number(input) ? input : 0;\n const progress = utils.is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !utils.is.event(event)) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!utils.is.element(target) || !utils.is.number(time)) {\n return;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = utils.getHours(this.duration) > 0;\n\n // eslint-disable-next-line no-param-reassign\n target.textContent = utils.formatTime(time, forceHours, inverted);\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded\n durationUpdate() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's a spot to display duration\n const hasDuration = utils.is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport i18n from './i18n';\nimport support from './support';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria value for https://github.com/sampotts/plyr/issues/905\n range.setAttribute('aria-valuenow', range.value);\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n },\n\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (utils.is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type, attr) {\n let text = i18n.get(type, this.config);\n const attributes = Object.assign({}, attr);\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n if ('class' in attributes) {\n attributes.class += ` ${this.config.classNames.hidden}`;\n } else {\n attributes.class = this.config.classNames.hidden;\n }\n\n return utils.createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (utils.is.empty(text)) {\n return null;\n }\n\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const button = utils.createElement('button');\n const attributes = Object.assign({}, attr);\n let type = utils.toCamelCase(buttonType);\n\n let toggle = false;\n let label;\n let icon;\n let labelPressed;\n let iconPressed;\n\n if (!('type' in attributes)) {\n attributes.type = 'button';\n }\n\n if ('class' in attributes) {\n if (attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n toggle = true;\n label = 'play';\n labelPressed = 'pause';\n icon = 'play';\n iconPressed = 'pause';\n break;\n\n case 'mute':\n toggle = true;\n label = 'mute';\n labelPressed = 'unmute';\n icon = 'volume';\n iconPressed = 'muted';\n break;\n\n case 'captions':\n toggle = true;\n label = 'enableCaptions';\n labelPressed = 'disableCaptions';\n icon = 'captions-off';\n iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n toggle = true;\n label = 'enterFullscreen';\n labelPressed = 'exitFullscreen';\n icon = 'enter-fullscreen';\n iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n label = 'play';\n icon = 'play';\n break;\n\n default:\n label = type;\n icon = buttonType;\n }\n\n // Setup toggle icon and labels\n if (toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));\n button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));\n button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));\n\n // Add aria attributes\n attributes['aria-pressed'] = false;\n } else {\n button.appendChild(controls.createIcon.call(this, icon));\n button.appendChild(controls.createLabel.call(this, label));\n }\n\n // Merge attributes\n utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n\n utils.setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!utils.is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek label\n const label = utils.createElement(\n 'label',\n {\n for: attributes.id,\n id: `${attributes.id}-label`,\n class: this.config.classNames.hidden,\n },\n i18n.get(type, this.config),\n );\n\n // Seek input\n const input = utils.createElement(\n 'input',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-labelledby': `${attributes.id}-label`,\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return {\n label,\n input,\n };\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = utils.createElement(\n 'progress',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(utils.createElement('span', null, '0'));\n\n let suffix = '';\n switch (type) {\n case 'played':\n suffix = i18n.get('played', this.config);\n break;\n\n case 'buffer':\n suffix = i18n.get('buffered', this.config);\n break;\n\n default:\n break;\n }\n\n progress.textContent = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = utils.createElement('div', utils.extend(attributes, {\n class: `plyr__time ${attributes.class}`,\n 'aria-label': i18n.get(type, this.config),\n }), '00:00');\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Create a settings menu item\n createMenuItem(value, list, type, title, badge = null, checked = false) {\n const item = utils.createElement('li');\n\n const label = utils.createElement('label', {\n class: this.config.classNames.control,\n });\n\n const radio = utils.createElement(\n 'input',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'radio',\n name: `plyr-${type}`,\n value,\n checked,\n class: 'plyr__sr-only',\n }),\n );\n\n const faux = utils.createElement('span', { hidden: '' });\n\n label.appendChild(radio);\n label.appendChild(faux);\n label.insertAdjacentHTML('beforeend', title);\n\n if (utils.is.element(badge)) {\n label.appendChild(badge);\n }\n\n item.appendChild(label);\n list.appendChild(item);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !utils.is.element(this.elements.inputs.seek) ||\n !utils.is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.inputs.seek.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (utils.is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (utils.is.event(event) && [\n 'mouseenter',\n 'mouseleave',\n ].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Hide/show a tab\n toggleTab(setting, toggle) {\n utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);\n },\n\n // Set the quality menu\n // TODO: Vimeo support\n setQualityMenu(options) {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panes.quality.querySelector('ul');\n\n // Set options if passed and filter based on config\n if (utils.is.array(options)) {\n this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n let label = '';\n\n switch (quality) {\n case 2160:\n label = '4K';\n break;\n\n case 1440:\n case 1080:\n case 720:\n label = 'HD';\n break;\n\n case 576:\n case 480:\n label = 'SD';\n break;\n\n default:\n break;\n }\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n const label = controls.getLabel.call(this, 'quality', quality);\n controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Translate a value into a nice label\n // TODO: Localisation\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (utils.is.number(value)) {\n return `${value}p`;\n }\n\n return utils.toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panes[setting];\n let value = null;\n let list = container;\n\n switch (setting) {\n case 'captions':\n if (this.captions.active) {\n if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) {\n value = this.captions.language;\n } else {\n value = 'enabled';\n }\n } else {\n value = '';\n }\n\n break;\n\n default:\n value = !utils.is.empty(input) ? input : this[setting];\n\n // Get default\n if (utils.is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n\n break;\n }\n\n // Get the list if we need to\n if (!utils.is.element(list)) {\n list = pane && pane.querySelector('ul');\n }\n\n // If there's no list it means it's not been rendered...\n if (!utils.is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`input[value=\"${value}\"]`);\n\n if (utils.is.element(target)) {\n target.checked = true;\n }\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panes.loop.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.loop, false);\n utils.toggleHidden(this.elements.settings.panes.loop, false);\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.loop.options);\n controls.toggleTab.call(this, 'loop', toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n options.forEach(option => {\n const item = utils.createElement('li');\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panes.captions.querySelector('ul');\n\n // Toggle the pane and tab\n const toggle = captions.getTracks.call(this).length;\n controls.toggleTab.call(this, type, toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Re-map the tracks into just the data we need\n const tracks = captions.getTracks.call(this).map(track => ({\n language: !utils.is.empty(track.language) ? track.language : 'enabled',\n label: captions.getLabel.call(this, track),\n }));\n\n // Add the \"Disabled\" option to turn off captions\n tracks.unshift({\n language: '',\n label: i18n.get('disabled', this.config),\n });\n\n // Generate options\n tracks.forEach(track => {\n controls.createMenuItem.call(\n this,\n track.language,\n list,\n 'language',\n track.label,\n track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null,\n track.language.toLowerCase() === this.captions.language.toLowerCase(),\n );\n });\n\n // Store reference\n this.options.captions = tracks.map(track => track.language);\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Do nothing if not selected\n if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) {\n return;\n }\n\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.speed)) {\n return;\n }\n\n const type = 'speed';\n\n // Set the speed options\n if (utils.is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the list to populate\n const list = this.elements.settings.panes.speed.querySelector('ul');\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Create items\n this.options.speed.forEach(speed => {\n const label = controls.getLabel.call(this, 'speed', speed);\n controls.createMenuItem.call(this, speed, list, type, label);\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { tabs } = this.elements.settings;\n const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);\n\n utils.toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Show/hide menu\n toggleMenu(event) {\n const { form } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!utils.is.element(form) || !utils.is.element(button)) {\n return;\n }\n\n const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');\n\n if (utils.is.event(event)) {\n const isMenuItem = utils.is.element(form) && form.contains(event.target);\n const isButton = event.target === this.elements.buttons.settings;\n\n // If the click was inside the form or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && !isButton && show)) {\n return;\n }\n\n // Prevent the toggle being caught by the doc listener\n if (isButton) {\n event.stopPropagation();\n }\n }\n\n // Set form and button attributes\n if (utils.is.element(button)) {\n button.setAttribute('aria-expanded', show);\n }\n\n if (utils.is.element(form)) {\n utils.toggleHidden(form, !show);\n utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n if (show) {\n form.removeAttribute('tabindex');\n } else {\n form.setAttribute('tabindex', -1);\n }\n }\n },\n\n // Get the natural size of a tab\n getTabSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Prevent input's being unchecked due to the name being identical\n Array.from(clone.querySelectorAll('input[name]')).forEach(input => {\n const name = input.getAttribute('name');\n input.setAttribute('name', `${name}-clone`);\n });\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n utils.removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Toggle Menu\n showTab(target = '') {\n const { menu } = this.elements.settings;\n const pane = document.getElementById(target);\n\n // Nothing to show, bail\n if (!utils.is.element(pane)) {\n return;\n }\n\n // Are we targetting a tab? If not, bail\n const isTab = pane.getAttribute('role') === 'tabpanel';\n if (!isTab) {\n return;\n }\n\n // Hide all other tabs\n // Get other tabs\n const current = menu.querySelector('[role=\"tabpanel\"]:not([hidden])');\n const container = current.parentNode;\n\n // Set other toggles to be expanded false\n Array.from(menu.querySelectorAll(`[aria-controls=\"${current.getAttribute('id')}\"]`)).forEach(toggle => {\n toggle.setAttribute('aria-expanded', false);\n });\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getTabSize.call(this, pane);\n\n // Restore auto height/width\n const restore = e => {\n // We're only bothered about height and width on the container\n if (e.target !== container || ![\n 'width',\n 'height',\n ].includes(e.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n utils.off(container, utils.transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n utils.on(container, utils.transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n utils.toggleHidden(current, true);\n current.setAttribute('tabindex', -1);\n\n // Set attributes on target\n utils.toggleHidden(pane, false);\n\n const tabs = utils.getElements.call(this, `[aria-controls=\"${target}\"]`);\n Array.from(tabs).forEach(tab => {\n tab.setAttribute('aria-expanded', true);\n });\n pane.removeAttribute('tabindex');\n\n // Focus the first item\n pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Do nothing if we want no controls\n if (utils.is.empty(this.config.controls)) {\n return null;\n }\n\n // Create the container\n const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n const seek = controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n });\n progress.appendChild(seek.label);\n progress.appendChild(seek.input);\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = utils.createElement(\n 'span',\n {\n role: 'tooltip',\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n container.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n const volume = utils.createElement('div', {\n class: 'plyr__volume',\n });\n\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n const range = controls.createRange.call(\n this,\n 'volume',\n utils.extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n );\n volume.appendChild(range.label);\n volume.appendChild(range.input);\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n const menu = utils.createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n menu.appendChild(\n controls.createButton.call(this, 'settings', {\n id: `plyr-settings-toggle-${data.id}`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const form = utils.createElement('form', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tablist',\n tabindex: -1,\n });\n\n const inner = utils.createElement('div');\n\n const home = utils.createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tabpanel',\n });\n\n // Create the tab list\n const tabs = utils.createElement('ul', {\n role: 'tablist',\n });\n\n // Build the tabs\n this.config.settings.forEach(type => {\n const tab = utils.createElement('li', {\n role: 'tab',\n hidden: '',\n });\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n id: `plyr-settings-${data.id}-${type}-tab`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-${type}`,\n 'aria-expanded': false,\n }),\n i18n.get(type, this.config),\n );\n\n const value = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n button.appendChild(value);\n tab.appendChild(button);\n tabs.appendChild(tab);\n\n this.elements.settings.tabs[type] = tab;\n });\n\n home.appendChild(tabs);\n inner.appendChild(home);\n\n // Build the panes\n this.config.settings.forEach(type => {\n const pane = utils.createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,\n role: 'tabpanel',\n tabindex: -1,\n });\n\n const back = utils.createElement(\n 'button',\n {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-home`,\n 'aria-expanded': false,\n },\n i18n.get(type, this.config),\n );\n\n pane.appendChild(back);\n\n const options = utils.createElement('ul');\n\n pane.appendChild(options);\n inner.appendChild(pane);\n\n this.elements.settings.panes[type] = pane;\n });\n\n form.appendChild(inner);\n menu.appendChild(form);\n container.appendChild(menu);\n\n this.elements.settings.form = form;\n this.elements.settings.menu = menu;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n utils.loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {\n // String or HTMLElement passed as the option\n container = this.config.controls;\n } else if (utils.is.function(this.config.controls)) {\n // A custom function to build controls\n // The function can return a HTMLElement or String\n container = this.config.controls.call(this, props);\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([\n key,\n value,\n ]) => {\n result = utils.replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (utils.is.string(this.config.controls)) {\n container = replace(container);\n } else if (utils.is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (utils.is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!utils.is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML\n if (utils.is.element(container)) {\n target.appendChild(container);\n } else if (container) {\n target.insertAdjacentHTML('beforeend', container);\n }\n\n // Find the elements if need be\n if (!utils.is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Edge sometimes doesn't finish the paint so force a redraw\n if (window.navigator.userAgent.includes('Edge')) {\n utils.repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const labels = utils.getElements.call(\n this,\n [\n this.config.selectors.controls.wrapper,\n ' ',\n this.config.selectors.labels,\n ' .',\n this.config.classNames.hidden,\n ].join(''),\n );\n\n Array.from(labels).forEach(label => {\n utils.toggleClass(label, this.config.classNames.hidden, false);\n utils.toggleClass(label, this.config.classNames.tooltip, true);\n label.setAttribute('role', 'tooltip');\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Set default language if not set\n const stored = this.storage.get('language');\n\n if (!utils.is.empty(stored)) {\n this.captions.language = stored;\n }\n\n if (utils.is.empty(this.captions.language)) {\n this.captions.language = this.config.captions.language.toLowerCase();\n }\n\n // Set captions enabled state if not set\n if (!utils.is.boolean(this.captions.active)) {\n const active = this.storage.get('captions');\n\n if (utils.is.boolean(active)) {\n this.captions.active = active;\n } else {\n this.captions.active = this.config.captions.active;\n }\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!utils.is.element(this.elements.captions)) {\n this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));\n\n utils.insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Set the class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));\n\n // Get tracks\n const tracks = captions.getTracks.call(this);\n\n // If no caption file exists, hide container for caption text\n if (utils.is.empty(tracks)) {\n return;\n }\n\n // Get browser info\n const browser = utils.getBrowser();\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const href = utils.parseUrl(src);\n\n if (href.hostname !== window.location.href.hostname && [\n 'http:',\n 'https:',\n ].includes(href.protocol)) {\n utils\n .fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n utils.removeElement(track);\n });\n }\n });\n }\n\n // Set language\n captions.setLanguage.call(this);\n\n // Enable UI\n captions.show.call(this);\n\n // Set available languages in list\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Set the captions language\n setLanguage() {\n // Setup HTML5 track rendering\n if (this.isHTML5 && this.isVideo) {\n captions.getTracks.call(this).forEach(track => {\n // Show track\n utils.on(track, 'cuechange', event => captions.setCue.call(this, event));\n\n // Turn off native caption rendering to avoid double captions\n // eslint-disable-next-line\n track.mode = 'hidden';\n });\n\n // Get current track\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Check if suported kind\n if (utils.is.track(currentTrack)) {\n // If we change the active track while a cue is already displayed we need to update it\n if (Array.from(currentTrack.activeCues || []).length) {\n captions.setCue.call(this, currentTrack);\n }\n }\n } else if (this.isVimeo && this.captions.active) {\n this.embed.enableTextTrack(this.language);\n }\n },\n\n // Get the tracks\n getTracks() {\n // Return empty array at least\n if (utils.is.nullOrUndefined(this.media)) {\n return [];\n }\n\n // Only get accepted kinds\n return Array.from(this.media.textTracks || []).filter(track => [\n 'captions',\n 'subtitles',\n ].includes(track.kind));\n },\n\n // Get the current track for the current language\n getCurrentTrack() {\n const tracks = captions.getTracks.call(this);\n\n if (!tracks.length) {\n return null;\n }\n\n // Get track based on current language\n let track = tracks.find(track => track.language.toLowerCase() === this.language);\n\n // Get the <track> with default attribute\n if (!track) {\n track = utils.getElement.call(this, 'track[default]');\n }\n\n // Get the first track\n if (!track) {\n [track] = tracks;\n }\n\n return track;\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (utils.is.track(currentTrack)) {\n if (!utils.is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!utils.is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Display active caption if it contains text\n setCue(input) {\n // Get the track from the event if needed\n const track = utils.is.event(input) ? input.target : input;\n const { activeCues } = track;\n const active = activeCues.length && activeCues[0];\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Only display current track\n if (track !== currentTrack) {\n return;\n }\n\n // Display a cue, if there is one\n if (utils.is.cue(active)) {\n captions.setText.call(this, active.getCueAsHTML());\n } else {\n captions.setText.call(this, null);\n }\n\n utils.dispatchEvent.call(this, this.media, 'cuechange');\n },\n\n // Set the current caption\n setText(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (utils.is.element(this.elements.captions)) {\n const content = utils.createElement('span');\n\n // Empty the container\n utils.emptyElement(this.elements.captions);\n\n // Default to empty\n const caption = !utils.is.nullOrUndefined(input) ? input : '';\n\n // Set the span content\n if (utils.is.string(caption)) {\n content.textContent = caption.trim();\n } else {\n content.appendChild(caption);\n }\n\n // Set new caption text\n this.elements.captions.appendChild(content);\n } else {\n this.debug.warn('No captions element to render to');\n }\n },\n\n // Display captions container and button (for initialization)\n show() {\n // Try to load the value from storage\n let active = this.storage.get('captions');\n\n // Otherwise fall back to the default config\n if (!utils.is.boolean(active)) {\n ({ active } = this.config.captions);\n } else {\n this.captions.active = active;\n }\n\n if (active) {\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true);\n utils.toggleState(this.elements.buttons.captions, true);\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [\n 4320,\n 2880,\n 2160,\n 1440,\n 1080,\n 720,\n 576,\n 480,\n 360,\n 240,\n 'default', // YouTube's \"auto\"\n ],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: (navigator.language || navigator.userLanguage).split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: [\n 'captions',\n 'quality',\n 'speed',\n ],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n },\n\n // URLs\n urls: {\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n ads: 'plyr__ads',\n control: 'plyr__control',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n error: 'plyr--has-error',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// ==========================================================================\n\nimport utils from './utils';\n\nconst browser = utils.getBrowser();\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (utils.is.element(button)) {\n utils.toggleState(button, this.active);\n }\n\n // Trigger an event\n utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n utils.trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n // TODO: Filter for target??\n onChange.call(this);\n });\n\n // Fullscreen toggle on double click\n utils.on(this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (utils.is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n\n prefixes.some(pre => {\n if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native) {\n return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.playing) {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!utils.is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!utils.is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.player.currentTime = this.player.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n this.player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n this.player.muted = !this.player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.player.forward();\n break;\n\n case 37:\n // Arrow back\n this.player.rewind();\n break;\n\n case 70:\n // F key\n this.player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n this.player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.player.loop = !this.player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) {\n this.player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n this.player.touch = true;\n\n // Add touch class\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);\n\n // Clean up\n utils.off(document.body, 'touchstart', this.firstTouch);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n // Keyboard shortcuts\n if (this.player.config.keyboard.global) {\n utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n utils.on(document.body, 'touchstart', this.firstTouch);\n }\n\n // Container listeners\n container() {\n // Keyboard shortcuts\n if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {\n utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.player.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.player.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.player.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => {\n this.player.toggleControls(event);\n });\n }\n }\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));\n\n // Display duration\n utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event));\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n utils.on(this.player.media, 'loadeddata', () => {\n utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);\n utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);\n });\n\n // Handle the media finishing\n utils.on(this.player.media, 'ended', () => {\n // Show poster on end\n if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {\n // Restart\n this.player.restart();\n }\n });\n\n // Check for buffer progress\n utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event));\n\n // Handle volume changes\n utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event));\n\n // Handle play/pause\n utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));\n\n // Loading state\n utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));\n\n // Check if media failed to load\n // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n utils.on(this.player.media, 'playing', () => {\n if (!this.player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (this.player.ads.enabled && !this.player.ads.initialized) {\n // Wait for manager response\n this.player.ads.managerPromise.then(() => this.player.ads.play()).catch(() => this.player.play());\n }\n });\n\n // Click video\n if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this.player, `.${this.player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!utils.is.element(wrapper)) {\n return;\n }\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.player.config.hideControls && this.player.touch && !this.player.paused) {\n return;\n }\n\n if (this.player.paused) {\n this.player.play();\n } else if (this.player.ended) {\n this.player.restart();\n this.player.play();\n } else {\n this.player.pause();\n }\n });\n }\n\n // Disable right click\n if (this.player.supported.ui && this.player.config.disableContextMenu) {\n utils.on(\n this.player.elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n utils.on(this.player.media, 'volumechange', () => {\n // Save to storage\n this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });\n });\n\n // Speed change\n utils.on(this.player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'speed');\n\n // Save to storage\n this.player.storage.set({ speed: this.player.speed });\n });\n\n // Quality request\n utils.on(this.player.media, 'qualityrequested', event => {\n // Save to storage\n this.player.storage.set({ quality: event.detail.quality });\n });\n\n // Quality change\n utils.on(this.player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);\n });\n\n // Caption language change\n utils.on(this.player.media, 'languagechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ language: this.player.language });\n });\n\n // Captions toggle\n utils.on(this.player.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ captions: this.player.captions.active });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.player.media, this.player.config.events.concat([\n 'keyup',\n 'keydown',\n ]).join(' '), event => {\n let detail = {};\n\n // Get error details from media\n if (event.type === 'error') {\n detail = this.player.media.error;\n }\n\n utils.dispatchEvent.call(this.player, this.player.elements.container, event.type, true, detail);\n });\n }\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Run default and custom handlers\n const proxy = (event, defaultHandler, customHandlerKey) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(this.player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && utils.is.function(defaultHandler)) {\n defaultHandler.call(this.player, event);\n }\n };\n\n // Trigger custom and default handlers\n const on = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n\n utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n };\n\n // Play/pause toggle\n on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play');\n\n // Pause\n on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');\n\n // Rewind\n on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');\n\n // Rewind\n on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');\n\n // Mute toggle\n on(\n this.player.elements.buttons.mute,\n 'click',\n () => {\n this.player.muted = !this.player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions);\n\n // Fullscreen toggle\n on(\n this.player.elements.buttons.fullscreen,\n 'click',\n () => {\n this.player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n on(\n this.player.elements.buttons.pip,\n 'click',\n () => {\n this.player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');\n\n // Settings menu\n on(this.player.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this.player, event);\n });\n\n // Settings menu\n on(this.player.elements.settings.form, 'click', event => {\n event.stopPropagation();\n\n // Go back to home tab on click\n const showHomeTab = () => {\n const id = `plyr-settings-${this.player.id}-home`;\n controls.showTab.call(this.player, id);\n };\n\n // Settings menu items - use event delegation as items are added/removed\n if (utils.matches(event.target, this.player.config.selectors.inputs.language)) {\n proxy(\n event,\n () => {\n this.player.language = event.target.value;\n showHomeTab();\n },\n 'language',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.quality)) {\n proxy(\n event,\n () => {\n this.player.quality = event.target.value;\n showHomeTab();\n },\n 'quality',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.speed)) {\n proxy(\n event,\n () => {\n this.player.speed = parseFloat(event.target.value);\n showHomeTab();\n },\n 'speed',\n );\n } else {\n const tab = event.target;\n controls.showTab.call(this.player, tab.getAttribute('aria-controls'));\n }\n });\n\n // Seek\n on(\n this.player.elements.inputs.seek,\n inputEvent,\n event => {\n this.player.currentTime = event.target.value / event.target.max * this.player.duration;\n },\n 'seek',\n );\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) {\n on(this.player.elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (this.player.currentTime === 0) {\n return;\n }\n\n this.player.config.invertTime = !this.player.config.invertTime;\n ui.timeUpdate.call(this.player);\n });\n }\n\n // Volume\n on(\n this.player.elements.inputs.volume,\n inputEvent,\n event => {\n this.player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n on(utils.getElements.call(this.player, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this.player, event.target);\n });\n }\n\n // Seek tooltip\n on(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event));\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mouseenter mouseleave', event => {\n this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.player.elements.controls.pressed = [\n 'mousedown',\n 'touchstart',\n ].includes(event.type);\n });\n\n // Focus in/out on controls\n on(this.player.elements.controls, 'focusin focusout', event => {\n this.player.toggleControls(event);\n });\n }\n\n // Mouse wheel for volume\n on(\n this.player.elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.player.decreaseVolume(step);\n direction = -1;\n } else {\n this.player.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.player.increaseVolume(step);\n direction = 1;\n } else {\n this.player.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n\n // Reset on destroy\n clear() {\n this.global(false);\n }\n}\n\nexport default Listeners;\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from './../captions';\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n vimeo.setAspectRatio.call(this);\n\n // Load the API if not already\n if (!utils.is.object(window.Vimeo)) {\n utils\n .loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // Set aspect ratio\n // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n if (this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n // muted: player.muted,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n };\n const params = utils.buildUrlParams(options);\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = utils.parseVimeoId(source);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = utils.format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Inject the package\n const wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = utils.replaceElement(wrapper, player.media);\n\n // Get poster image\n utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (utils.is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set attribute\n player.media.setAttribute('poster', url.href);\n\n // Update\n ui.setPoster.call(player);\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play().then(() => {\n player.media.paused = false;\n });\n };\n\n player.media.pause = () => {\n player.embed.pause().then(() => {\n player.media.paused = true;\n });\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time).catch(() => {\n // Do nothing\n });\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([\n player.embed.getVideoWidth(),\n player.embed.getVideoHeight(),\n ]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.setText.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n utils.dispatchEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\n// Standardise YouTube quality unit\nfunction mapQualityUnit(input) {\n switch (input) {\n case 'hd2160':\n return 2160;\n\n case 2160:\n return 'hd2160';\n\n case 'hd1440':\n return 1440;\n\n case 1440:\n return 'hd1440';\n\n case 'hd1080':\n return 1080;\n\n case 1080:\n return 'hd1080';\n\n case 'hd720':\n return 720;\n\n case 720:\n return 'hd720';\n\n case 'large':\n return 480;\n\n case 480:\n return 'large';\n\n case 'medium':\n return 360;\n\n case 360:\n return 'medium';\n\n case 'small':\n return 240;\n\n case 240:\n return 'small';\n\n default:\n return 'default';\n }\n}\n\nfunction mapQualityUnits(levels) {\n if (utils.is.empty(levels)) {\n return levels;\n }\n\n return utils.dedupe(levels.map(level => mapQualityUnit(level)));\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n youtube.setAspectRatio.call(this);\n\n // Setup API\n if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n utils.loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (utils.is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (utils.is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (utils.is.string(key) && !utils.is.empty(key)) {\n const url = utils.format(this.config.urls.youtube.api, videoId, key);\n\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // Set aspect ratio\n setAspectRatio() {\n const ratio = this.config.ratio.split(':');\n this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`;\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = utils.parseYouTubeId(source);\n const id = utils.generateId(player.provider);\n const container = utils.createElement('div', { id });\n player.media = utils.replaceElement(container, player.media);\n\n // Set poster image\n player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId));\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n playerVars: {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: 1, // Allow iOS inline playback\n\n // Tracking for stats\n // origin: window ? `${window.location.protocol}//${window.location.host}` : null,\n widget_referrer: window ? window.location.href : null,\n\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n },\n events: {\n onError(event) {\n // If we've already fired an error, don't do it again\n // YouTube fires onError twice\n if (utils.is.object(player.media.error)) {\n return;\n }\n\n const detail = {\n code: event.data,\n };\n\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n switch (event.data) {\n case 2:\n detail.message =\n 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.';\n break;\n\n case 5:\n detail.message =\n 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';\n break;\n\n case 100:\n detail.message =\n 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';\n break;\n\n case 101:\n case 150:\n detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';\n break;\n\n default:\n detail.message = 'An unknown error occured';\n break;\n }\n\n player.media.error = detail;\n\n utils.dispatchEvent.call(player, player.media, 'error');\n },\n onPlaybackQualityChange() {\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: player.media.quality,\n });\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n instance.playVideo();\n };\n\n player.media.pause = () => {\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n return mapQualityUnit(instance.getPlaybackQuality());\n },\n set(input) {\n const quality = input;\n\n // Set via API\n instance.setPlaybackQuality(mapQualityUnit(quality));\n\n // Trigger request event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality,\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n utils.dispatchEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n player.media.paused = true;\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n utils.dispatchEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // If we were seeking, fire seeked event\n if (player.media.seeking) {\n utils.dispatchEvent.call(player, player.media, 'seeked');\n }\n player.media.seeking = false;\n\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n\n utils.dispatchEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n\n // Get quality\n controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));\n\n break;\n\n case 2:\n player.media.paused = true;\n\n utils.dispatchEvent.call(player, player.media, 'pause');\n\n break;\n\n default:\n break;\n }\n\n utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport utils from './utils';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = utils.createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isEmbed) {\n switch (this.provider) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n } else if (this.isHTML5) {\n html5.extend.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport i18n from '../i18n';\nimport utils from '../utils';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.publisherId = player.config.ads.publisherId;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId);\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) {\n utils\n .loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the default tag URL\n get tagUrl() {\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${utils.buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = utils.createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = utils.formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!utils.is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (utils.is.element(seekElement)) {\n const cuePercentage = 100 / this.player.duration * cuePoint;\n const cue = utils.createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Get skippable state\n // TODO: Skip button\n // this.player.debug.warn(this.manager.getAdSkippableState());\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n utils.dispatchEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('seeking', () => {\n time = this.player.currentTime;\n return time;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (utils.is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (utils.is.array(handlers)) {\n handlers.forEach(handler => {\n if (utils.is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!utils.is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!utils.is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport { providers } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n this.type = input.type;\n this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;\n\n // Check for support\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // Create new markup\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n this.media = utils.createElement('video');\n break;\n\n case 'html5:audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n this.media = utils.createElement('div', {\n src: input.sources[0].src,\n });\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!utils.is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport utils from './utils';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (utils.is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return utils.is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (utils.is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.3.6\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport Console from './console';\nimport controls from './controls';\nimport defaults from './defaults';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport { providers, types } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n captions: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n let params = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (utils.is.element(iframe)) {\n // Detect provider\n url = iframe.getAttribute('src');\n this.provider = utils.getProviderByUrl(url);\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n params = utils.getUrlParams(url);\n if (!utils.is.empty(params)) {\n const truthy = [\n '1',\n 'true',\n ];\n\n if (truthy.includes(params.autoplay)) {\n this.config.autoplay = true;\n }\n if (truthy.includes(params.loop)) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(params.playsinline);\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!utils.is.element(this.elements.container)) {\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n }\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n this.ads = new Ads(this);\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!utils.is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !utils.is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = utils.is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (utils.is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (utils.is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // True duration\n const realDuration = this.media ? Number(this.media.duration) : 0;\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!utils.is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n }\n\n if (!utils.is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!utils.is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n let quality = null;\n\n if (!utils.is.empty(input)) {\n quality = Number(input);\n }\n\n if (!utils.is.number(quality) || quality === 0) {\n quality = this.storage.get('quality');\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.selected;\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.default;\n }\n\n if (!this.options.quality.length) {\n return;\n }\n\n if (!this.options.quality.includes(quality)) {\n const closest = utils.closest(this.options.quality, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);\n quality = closest;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n ui.setPoster.call(this);\n }\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);\n\n // Nothing to change...\n if (this.captions.active === show) {\n return;\n }\n\n // Set global\n this.captions.active = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.active);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n /**\n * Set the captions language\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // If empty string is passed, assume disable captions\n if (utils.is.empty(input)) {\n this.toggleCaptions(false);\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // Check for support\n if (!this.options.captions.includes(language)) {\n this.debug.warn(`Unsupported language option: ${language}`);\n return;\n }\n\n // Ensure captions are enabled\n this.toggleCaptions(true);\n\n // Enabled only\n if (language === 'enabled') {\n return;\n }\n\n // If nothing to change, bail\n if (this.language === language) {\n return;\n }\n\n // Update config\n this.captions.language = language;\n\n // Clear caption\n captions.setText.call(this, null);\n\n // Update captions\n captions.setLanguage.call(this);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n }\n\n /**\n * Get the current captions language\n */\n get language() {\n return this.captions.language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} toggle - Whether to show the controls\n */\n toggleControls(toggle) {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Don't hide if no UI support or it's audio\n if (!this.supported.ui || this.isAudio) {\n return;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n\n // Get toggle state if not set\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Events that show the controls\n const showEvents = [\n 'touchstart',\n 'touchmove',\n 'mouseenter',\n 'mousemove',\n 'focusin',\n ];\n\n // Events that delay hiding\n const delayEvents = [\n 'touchmove',\n 'touchend',\n 'mousemove',\n ];\n\n // Whether to show controls\n show = showEvents.includes(toggle.type);\n\n // Delay hiding on move events\n if (delayEvents.includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (!this.touch && toggle.type === 'focusin') {\n delay = 3000;\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer on every call\n clearTimeout(this.timers.controls);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.paused || this.loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.paused || this.loading) {\n return;\n }\n\n // Delay for hiding on touch\n if (this.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || this.playing) {\n this.timers.controls = setTimeout(() => {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Restore transition behaviour\n if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) {\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false);\n }\n\n // Set hideControls class\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, this.config.hideControls);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n utils.removeElement(this.elements.buttons.play);\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n this.listeners.clear();\n\n // Replace the container with the original element provided\n utils.replaceElement(this.elements.original, this.elements.container);\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Type specific stuff\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n case 'html5:audio':\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n case 'youtube:video':\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && utils.is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo:video':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return utils.loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (utils.is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (utils.is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (utils.is.array(selector)) {\n targets = selector.filter(i => utils.is.element(i));\n }\n\n if (utils.is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nexport default Plyr;\n","// ==========================================================================\n// Plyr Polyfilled Build\n// plyr.js v3.3.6\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport 'babel-polyfill';\nimport 'custom-event-polyfill';\nimport Plyr from './plyr';\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.polyfilled.min.js b/dist/plyr.polyfilled.min.js index 7c96e88e..57202b83 100644 --- a/dist/plyr.polyfilled.min.js +++ b/dist/plyr.polyfilled.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e,t){return e(t={exports:{}},t.exports),t.exports}var n=t(function(e){var t=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)}),i=t(function(e){var t=e.exports={version:"2.5.3"};"number"==typeof __e&&(__e=t)}),r=(i.version,function(e){return"object"==typeof e?null!==e:"function"==typeof e}),s=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e},o=function(e){try{return!!e()}catch(e){return!0}},a=!o(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}),l=n.document,c=r(l)&&r(l.createElement),u=function(e){return c?l.createElement(e):{}},d=!a&&!o(function(){return 7!=Object.defineProperty(u("div"),"a",{get:function(){return 7}}).a}),f=function(e,t){if(!r(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!r(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")},h=Object.defineProperty,p={f:a?Object.defineProperty:function(e,t,n){if(s(e),t=f(t,!0),s(n),d)try{return h(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},g=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}},m=a?function(e,t,n){return p.f(e,t,g(1,n))}:function(e,t,n){return e[t]=n,e},y={}.hasOwnProperty,v=function(e,t){return y.call(e,t)},b=0,w=Math.random(),E=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++b+w).toString(36))},k=t(function(e){var t=E("src"),r=Function.toString,s=(""+r).split("toString");i.inspectSource=function(e){return r.call(e)},(e.exports=function(e,i,r,o){var a="function"==typeof r;a&&(v(r,"name")||m(r,"name",i)),e[i]!==r&&(a&&(v(r,t)||m(r,t,e[i]?""+e[i]:s.join(String(i)))),e===n?e[i]=r:o?e[i]?e[i]=r:m(e,i,r):(delete e[i],m(e,i,r)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[t]||r.call(this)})}),S=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e},T=function(e,t,n){if(S(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,i){return e.call(t,n,i)};case 3:return function(n,i,r){return e.call(t,n,i,r)}}return function(){return e.apply(t,arguments)}},A=function(e,t,r){var s,o,a,l,c=e&A.F,u=e&A.G,d=e&A.S,f=e&A.P,h=e&A.B,p=u?n:d?n[t]||(n[t]={}):(n[t]||{}).prototype,g=u?i:i[t]||(i[t]={}),y=g.prototype||(g.prototype={});for(s in u&&(r=t),r)a=((o=!c&&p&&void 0!==p[s])?p:r)[s],l=h&&o?T(a,n):f&&"function"==typeof a?T(Function.call,a):a,p&&k(p,s,a,e&A.U),g[s]!=a&&m(g,s,l),f&&y[s]!=a&&(y[s]=a)};n.core=i,A.F=1,A.G=2,A.S=4,A.P=8,A.B=16,A.W=32,A.U=64,A.R=128;for(var _,C=A,P=E("typed_array"),x=E("view"),M=!(!n.ArrayBuffer||!n.DataView),L=M,N=0,O="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");N<9;)(_=n[O[N++]])?(m(_.prototype,P,!0),m(_.prototype,x,!0)):L=!1;var j={ABV:M,CONSTR:L,TYPED:P,VIEW:x},I=function(e,t,n){for(var i in t)k(e,i,t[i],n);return e},F=function(e,t,n,i){if(!(e instanceof t)||void 0!==i&&i in e)throw TypeError(n+": incorrect invocation!");return e},R=Math.ceil,q=Math.floor,B=function(e){return isNaN(e=+e)?0:(e>0?q:R)(e)},V=Math.min,D=function(e){return e>0?V(B(e),9007199254740991):0},U=function(e){if(void 0===e)return 0;var t=B(e),n=D(t);if(t!==n)throw RangeError("Wrong length!");return n},H={}.toString,W=function(e){return H.call(e).slice(8,-1)},z=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==W(e)?e.split(""):Object(e)},G=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e},Y=function(e){return z(G(e))},K=Math.max,Q=Math.min,J=function(e,t){return(e=B(e))<0?K(e+t,0):Q(e,t)},$=function(e){return function(t,n,i){var r,s=Y(t),o=D(s.length),a=J(i,o);if(e&&n!=n){for(;o>a;)if((r=s[a++])!=r)return!0}else for(;o>a;a++)if((e||a in s)&&s[a]===n)return e||a||0;return!e&&-1}},X=n["__core-js_shared__"]||(n["__core-js_shared__"]={}),Z=function(e){return X[e]||(X[e]={})},ee=Z("keys"),te=function(e){return ee[e]||(ee[e]=E(e))},ne=$(!1),ie=te("IE_PROTO"),re=function(e,t){var n,i=Y(e),r=0,s=[];for(n in i)n!=ie&&v(i,n)&&s.push(n);for(;t.length>r;)v(i,n=t[r++])&&(~ne(s,n)||s.push(n));return s},se="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),oe=se.concat("length","prototype"),ae={f:Object.getOwnPropertyNames||function(e){return re(e,oe)}},le=function(e){return Object(G(e))},ce=function(e){for(var t=le(this),n=D(t.length),i=arguments.length,r=J(i>1?arguments[1]:void 0,n),s=i>2?arguments[2]:void 0,o=void 0===s?n:J(s,n);o>r;)t[r++]=e;return t},ue=t(function(e){var t=Z("wks"),i=n.Symbol,r="function"==typeof i;(e.exports=function(e){return t[e]||(t[e]=r&&i[e]||(r?i:E)("Symbol."+e))}).store=t}),de=p.f,fe=ue("toStringTag"),he=function(e,t,n){e&&!v(e=n?e:e.prototype,fe)&&de(e,fe,{configurable:!0,value:t})},pe=t(function(e,t){var i=ae.f,r=p.f,s="prototype",l="Wrong index!",c=n.ArrayBuffer,u=n.DataView,d=n.Math,f=n.RangeError,h=n.Infinity,g=c,y=d.abs,v=d.pow,b=d.floor,w=d.log,E=d.LN2,k=a?"_b":"buffer",S=a?"_l":"byteLength",T=a?"_o":"byteOffset";function A(e,t,n){var i,r,s,o=new Array(n),a=8*n-t-1,l=(1<<a)-1,c=l>>1,u=23===t?v(2,-24)-v(2,-77):0,d=0,f=e<0||0===e&&1/e<0?1:0;for((e=y(e))!=e||e===h?(r=e!=e?1:0,i=l):(i=b(w(e)/E),e*(s=v(2,-i))<1&&(i--,s*=2),(e+=i+c>=1?u/s:u*v(2,1-c))*s>=2&&(i++,s/=2),i+c>=l?(r=0,i=l):i+c>=1?(r=(e*s-1)*v(2,t),i+=c):(r=e*v(2,c-1)*v(2,t),i=0));t>=8;o[d++]=255&r,r/=256,t-=8);for(i=i<<t|r,a+=t;a>0;o[d++]=255&i,i/=256,a-=8);return o[--d]|=128*f,o}function _(e,t,n){var i,r=8*n-t-1,s=(1<<r)-1,o=s>>1,a=r-7,l=n-1,c=e[l--],u=127&c;for(c>>=7;a>0;u=256*u+e[l],l--,a-=8);for(i=u&(1<<-a)-1,u>>=-a,a+=t;a>0;i=256*i+e[l],l--,a-=8);if(0===u)u=1-o;else{if(u===s)return i?NaN:c?-h:h;i+=v(2,t),u-=o}return(c?-1:1)*i*v(2,u-t)}function C(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]}function P(e){return[255&e]}function x(e){return[255&e,e>>8&255]}function M(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function L(e){return A(e,52,8)}function N(e){return A(e,23,4)}function O(e,t,n){r(e[s],t,{get:function(){return this[n]}})}function R(e,t,n,i){var r=U(+n);if(r+t>e[S])throw f(l);var s=e[k]._b,o=r+e[T],a=s.slice(o,o+t);return i?a:a.reverse()}function q(e,t,n,i,r,s){var o=U(+n);if(o+t>e[S])throw f(l);for(var a=e[k]._b,c=o+e[T],u=i(+r),d=0;d<t;d++)a[c+d]=u[s?d:t-d-1]}if(j.ABV){if(!o(function(){c(1)})||!o(function(){new c(-1)})||o(function(){return new c,new c(1.5),new c(NaN),"ArrayBuffer"!=c.name})){for(var V,H=(c=function(e){return F(this,c),new g(U(e))})[s]=g[s],W=i(g),z=0;W.length>z;)(V=W[z++])in c||m(c,V,g[V]);H.constructor=c}var G=new u(new c(2)),Y=u[s].setInt8;G.setInt8(0,2147483648),G.setInt8(1,2147483649),!G.getInt8(0)&&G.getInt8(1)||I(u[s],{setInt8:function(e,t){Y.call(this,e,t<<24>>24)},setUint8:function(e,t){Y.call(this,e,t<<24>>24)}},!0)}else c=function(e){F(this,c,"ArrayBuffer");var t=U(e);this._b=ce.call(new Array(t),0),this[S]=t},u=function(e,t,n){F(this,u,"DataView"),F(e,c,"DataView");var i=e[S],r=B(t);if(r<0||r>i)throw f("Wrong offset!");if(r+(n=void 0===n?i-r:D(n))>i)throw f("Wrong length!");this[k]=e,this[T]=r,this[S]=n},a&&(O(c,"byteLength","_l"),O(u,"buffer","_b"),O(u,"byteLength","_l"),O(u,"byteOffset","_o")),I(u[s],{getInt8:function(e){return R(this,1,e)[0]<<24>>24},getUint8:function(e){return R(this,1,e)[0]},getInt16:function(e){var t=R(this,2,e,arguments[1]);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=R(this,2,e,arguments[1]);return t[1]<<8|t[0]},getInt32:function(e){return C(R(this,4,e,arguments[1]))},getUint32:function(e){return C(R(this,4,e,arguments[1]))>>>0},getFloat32:function(e){return _(R(this,4,e,arguments[1]),23,4)},getFloat64:function(e){return _(R(this,8,e,arguments[1]),52,8)},setInt8:function(e,t){q(this,1,e,P,t)},setUint8:function(e,t){q(this,1,e,P,t)},setInt16:function(e,t){q(this,2,e,x,t,arguments[2])},setUint16:function(e,t){q(this,2,e,x,t,arguments[2])},setInt32:function(e,t){q(this,4,e,M,t,arguments[2])},setUint32:function(e,t){q(this,4,e,M,t,arguments[2])},setFloat32:function(e,t){q(this,4,e,N,t,arguments[2])},setFloat64:function(e,t){q(this,8,e,L,t,arguments[2])}});he(c,"ArrayBuffer"),he(u,"DataView"),m(u[s],j.VIEW,!0),t.ArrayBuffer=c,t.DataView=u}),ge=ue("species"),me=function(e,t){var n,i=s(e).constructor;return void 0===i||void 0==(n=s(i)[ge])?t:S(n)},ye=ue("species"),ve=function(e){var t=n[e];a&&t&&!t[ye]&&p.f(t,ye,{configurable:!0,get:function(){return this}})},be=n.ArrayBuffer,we=pe.ArrayBuffer,Ee=pe.DataView,ke=j.ABV&&be.isView,Se=we.prototype.slice,Te=j.VIEW;C(C.G+C.W+C.F*(be!==we),{ArrayBuffer:we}),C(C.S+C.F*!j.CONSTR,"ArrayBuffer",{isView:function(e){return ke&&ke(e)||r(e)&&Te in e}}),C(C.P+C.U+C.F*o(function(){return!new we(2).slice(1,void 0).byteLength}),"ArrayBuffer",{slice:function(e,t){if(void 0!==Se&&void 0===t)return Se.call(s(this),e);for(var n=s(this).byteLength,i=J(e,n),r=J(void 0===t?n:t,n),o=new(me(this,we))(D(r-i)),a=new Ee(this),l=new Ee(o),c=0;i<r;)l.setUint8(c++,a.getUint8(i++));return o}}),ve("ArrayBuffer");var Ae=ue("toStringTag"),_e="Arguments"==W(function(){return arguments}()),Ce=function(e){var t,n,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),Ae))?n:_e?W(t):"Object"==(i=W(t))&&"function"==typeof t.callee?"Arguments":i},Pe={},xe=ue("iterator"),Me=Array.prototype,Le=function(e){return void 0!==e&&(Pe.Array===e||Me[xe]===e)},Ne=Object.keys||function(e){return re(e,se)},Oe=a?Object.defineProperties:function(e,t){s(e);for(var n,i=Ne(t),r=i.length,o=0;r>o;)p.f(e,n=i[o++],t[n]);return e},je=n.document,Ie=je&&je.documentElement,Fe=te("IE_PROTO"),Re=function(){},qe=function(){var e,t=u("iframe"),n=se.length;for(t.style.display="none",Ie.appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),qe=e.F;n--;)delete qe.prototype[se[n]];return qe()},Be=Object.create||function(e,t){var n;return null!==e?(Re.prototype=s(e),n=new Re,Re.prototype=null,n[Fe]=e):n=qe(),void 0===t?n:Oe(n,t)},Ve=te("IE_PROTO"),De=Object.prototype,Ue=Object.getPrototypeOf||function(e){return e=le(e),v(e,Ve)?e[Ve]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?De:null},He=ue("iterator"),We=i.getIteratorMethod=function(e){if(void 0!=e)return e[He]||e["@@iterator"]||Pe[Ce(e)]},ze=Array.isArray||function(e){return"Array"==W(e)},Ge=ue("species"),Ye=function(e,t){return new(function(e){var t;return ze(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!ze(t.prototype)||(t=void 0),r(t)&&null===(t=t[Ge])&&(t=void 0)),void 0===t?Array:t}(e))(t)},Ke=function(e,t){var n=1==e,i=2==e,r=3==e,s=4==e,o=6==e,a=5==e||o,l=t||Ye;return function(t,c,u){for(var d,f,h=le(t),p=z(h),g=T(c,u,3),m=D(p.length),y=0,v=n?l(t,m):i?l(t,0):void 0;m>y;y++)if((a||y in p)&&(f=g(d=p[y],y,h),e))if(n)v[y]=f;else if(f)switch(e){case 3:return!0;case 5:return d;case 6:return y;case 2:v.push(d)}else if(s)return!1;return o?-1:r||s?s:v}},Qe=ue("unscopables"),Je=Array.prototype;void 0==Je[Qe]&&m(Je,Qe,{});var $e=function(e){Je[Qe][e]=!0},Xe=function(e,t){return{value:t,done:!!e}},Ze={};m(Ze,ue("iterator"),function(){return this});var et=function(e,t,n){e.prototype=Be(Ze,{next:g(1,n)}),he(e,t+" Iterator")},tt=ue("iterator"),nt=!([].keys&&"next"in[].keys()),it=function(){return this},rt=function(e,t,n,i,r,s,o){et(n,t,i);var a,l,c,u=function(e){if(!nt&&e in p)return p[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},d=t+" Iterator",f="values"==r,h=!1,p=e.prototype,g=p[tt]||p["@@iterator"]||r&&p[r],y=!nt&&g||u(r),b=r?f?u("entries"):y:void 0,w="Array"==t&&p.entries||g;if(w&&(c=Ue(w.call(new e)))!==Object.prototype&&c.next&&(he(c,d,!0),v(c,tt)||m(c,tt,it)),f&&g&&"values"!==g.name&&(h=!0,y=function(){return g.call(this)}),(nt||h||!p[tt])&&m(p,tt,y),Pe[t]=y,Pe[d]=it,r)if(a={values:f?y:u("values"),keys:s?y:u("keys"),entries:b},o)for(l in a)l in p||k(p,l,a[l]);else C(C.P+C.F*(nt||h),t,a);return a},st=rt(Array,"Array",function(e,t){this._t=Y(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,Xe(1)):Xe(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values");Pe.Arguments=Pe.Array,$e("keys"),$e("values"),$e("entries");var ot=ue("iterator"),at=!1;try{[7][ot]().return=function(){at=!0}}catch(e){}var lt=function(e,t){if(!t&&!at)return!1;var n=!1;try{var i=[7],r=i[ot]();r.next=function(){return{done:n=!0}},i[ot]=function(){return r},e(i)}catch(e){}return n},ct=[].copyWithin||function(e,t){var n=le(this),i=D(n.length),r=J(e,i),s=J(t,i),o=arguments.length>2?arguments[2]:void 0,a=Math.min((void 0===o?i:J(o,i))-s,i-r),l=1;for(s<r&&r<s+a&&(l=-1,s+=a-1,r+=a-1);a-- >0;)s in n?n[r]=n[s]:delete n[r],r+=l,s+=l;return n},ut={f:{}.propertyIsEnumerable},dt=Object.getOwnPropertyDescriptor,ft={f:a?dt:function(e,t){if(e=Y(e),t=f(t,!0),d)try{return dt(e,t)}catch(e){}if(v(e,t))return g(!ut.f.call(e,t),e[t])}},ht=t(function(e){if(a){var t=n,i=o,s=C,l=j,c=pe,u=T,d=F,h=g,y=m,b=I,w=B,k=D,S=U,A=J,_=f,P=v,x=Ce,M=r,L=le,N=Le,O=Be,R=Ue,q=ae.f,V=We,H=E,W=ue,z=Ke,G=$,Y=me,K=st,Q=Pe,X=lt,Z=ve,ee=ce,te=ct,ne=p,ie=ft,re=ne.f,se=ie.f,oe=t.RangeError,de=t.TypeError,fe=t.Uint8Array,he=Array.prototype,ge=c.ArrayBuffer,ye=c.DataView,be=z(0),we=z(2),Ee=z(3),ke=z(4),Se=z(5),Te=z(6),Ae=G(!0),_e=G(!1),xe=K.values,Me=K.keys,Ne=K.entries,Oe=he.lastIndexOf,je=he.reduce,Ie=he.reduceRight,Fe=he.join,Re=he.sort,qe=he.slice,Ve=he.toString,De=he.toLocaleString,He=W("iterator"),ze=W("toStringTag"),Ge=H("typed_constructor"),Ye=H("def_constructor"),Qe=l.CONSTR,Je=l.TYPED,$e=l.VIEW,Xe=z(1,function(e,t){return it(Y(e,e[Ye]),t)}),Ze=i(function(){return 1===new fe(new Uint16Array([1]).buffer)[0]}),et=!!fe&&!!fe.prototype.set&&i(function(){new fe(1).set({})}),tt=function(e,t){var n=w(e);if(n<0||n%t)throw oe("Wrong offset!");return n},nt=function(e){if(M(e)&&Je in e)return e;throw de(e+" is not a typed array!")},it=function(e,t){if(!(M(e)&&Ge in e))throw de("It is not a typed array constructor!");return new e(t)},rt=function(e,t){return ot(Y(e,e[Ye]),t)},ot=function(e,t){for(var n=0,i=t.length,r=it(e,i);i>n;)r[n]=t[n++];return r},at=function(e,t,n){re(e,t,{get:function(){return this._d[n]}})},ut=function(e){var t,n,i,r,s,o,a=L(e),l=arguments.length,c=l>1?arguments[1]:void 0,d=void 0!==c,f=V(a);if(void 0!=f&&!N(f)){for(o=f.call(a),i=[],t=0;!(s=o.next()).done;t++)i.push(s.value);a=i}for(d&&l>2&&(c=u(c,arguments[2],2)),t=0,n=k(a.length),r=it(this,n);n>t;t++)r[t]=d?c(a[t],t):a[t];return r},dt=function(){for(var e=0,t=arguments.length,n=it(this,t);t>e;)n[e]=arguments[e++];return n},ht=!!fe&&i(function(){De.call(new fe(1))}),pt=function(){return De.apply(ht?qe.call(nt(this)):nt(this),arguments)},gt={copyWithin:function(e,t){return te.call(nt(this),e,t,arguments.length>2?arguments[2]:void 0)},every:function(e){return ke(nt(this),e,arguments.length>1?arguments[1]:void 0)},fill:function(e){return ee.apply(nt(this),arguments)},filter:function(e){return rt(this,we(nt(this),e,arguments.length>1?arguments[1]:void 0))},find:function(e){return Se(nt(this),e,arguments.length>1?arguments[1]:void 0)},findIndex:function(e){return Te(nt(this),e,arguments.length>1?arguments[1]:void 0)},forEach:function(e){be(nt(this),e,arguments.length>1?arguments[1]:void 0)},indexOf:function(e){return _e(nt(this),e,arguments.length>1?arguments[1]:void 0)},includes:function(e){return Ae(nt(this),e,arguments.length>1?arguments[1]:void 0)},join:function(e){return Fe.apply(nt(this),arguments)},lastIndexOf:function(e){return Oe.apply(nt(this),arguments)},map:function(e){return Xe(nt(this),e,arguments.length>1?arguments[1]:void 0)},reduce:function(e){return je.apply(nt(this),arguments)},reduceRight:function(e){return Ie.apply(nt(this),arguments)},reverse:function(){for(var e,t=nt(this).length,n=Math.floor(t/2),i=0;i<n;)e=this[i],this[i++]=this[--t],this[t]=e;return this},some:function(e){return Ee(nt(this),e,arguments.length>1?arguments[1]:void 0)},sort:function(e){return Re.call(nt(this),e)},subarray:function(e,t){var n=nt(this),i=n.length,r=A(e,i);return new(Y(n,n[Ye]))(n.buffer,n.byteOffset+r*n.BYTES_PER_ELEMENT,k((void 0===t?i:A(t,i))-r))}},mt=function(e,t){return rt(this,qe.call(nt(this),e,t))},yt=function(e){nt(this);var t=tt(arguments[1],1),n=this.length,i=L(e),r=k(i.length),s=0;if(r+t>n)throw oe("Wrong length!");for(;s<r;)this[t+s]=i[s++]},vt={entries:function(){return Ne.call(nt(this))},keys:function(){return Me.call(nt(this))},values:function(){return xe.call(nt(this))}},bt=function(e,t){return M(e)&&e[Je]&&"symbol"!=typeof t&&t in e&&String(+t)==String(t)},wt=function(e,t){return bt(e,t=_(t,!0))?h(2,e[t]):se(e,t)},Et=function(e,t,n){return!(bt(e,t=_(t,!0))&&M(n)&&P(n,"value"))||P(n,"get")||P(n,"set")||n.configurable||P(n,"writable")&&!n.writable||P(n,"enumerable")&&!n.enumerable?re(e,t,n):(e[t]=n.value,e)};Qe||(ie.f=wt,ne.f=Et),s(s.S+s.F*!Qe,"Object",{getOwnPropertyDescriptor:wt,defineProperty:Et}),i(function(){Ve.call({})})&&(Ve=De=function(){return Fe.call(this)});var kt=b({},gt);b(kt,vt),y(kt,He,vt.values),b(kt,{slice:mt,set:yt,constructor:function(){},toString:Ve,toLocaleString:pt}),at(kt,"buffer","b"),at(kt,"byteOffset","o"),at(kt,"byteLength","l"),at(kt,"length","e"),re(kt,ze,{get:function(){return this[Je]}}),e.exports=function(e,n,r,o){var a=e+((o=!!o)?"Clamped":"")+"Array",c="get"+e,u="set"+e,f=t[a],h=f||{},p=f&&R(f),g=!f||!l.ABV,m={},v=f&&f.prototype,b=function(e,t){re(e,t,{get:function(){return function(e,t){var i=e._d;return i.v[c](t*n+i.o,Ze)}(this,t)},set:function(e){return function(e,t,i){var r=e._d;o&&(i=(i=Math.round(i))<0?0:i>255?255:255&i),r.v[u](t*n+r.o,i,Ze)}(this,t,e)},enumerable:!0})};g?(f=r(function(e,t,i,r){d(e,f,a,"_d");var s,o,l,c,u=0,h=0;if(M(t)){if(!(t instanceof ge||"ArrayBuffer"==(c=x(t))||"SharedArrayBuffer"==c))return Je in t?ot(f,t):ut.call(f,t);s=t,h=tt(i,n);var p=t.byteLength;if(void 0===r){if(p%n)throw oe("Wrong length!");if((o=p-h)<0)throw oe("Wrong length!")}else if((o=k(r)*n)+h>p)throw oe("Wrong length!");l=o/n}else l=S(t),s=new ge(o=l*n);for(y(e,"_d",{b:s,o:h,l:o,e:l,v:new ye(s)});u<l;)b(e,u++)}),v=f.prototype=O(kt),y(v,"constructor",f)):i(function(){f(1)})&&i(function(){new f(-1)})&&X(function(e){new f,new f(null),new f(1.5),new f(e)},!0)||(f=r(function(e,t,i,r){var s;return d(e,f,a),M(t)?t instanceof ge||"ArrayBuffer"==(s=x(t))||"SharedArrayBuffer"==s?void 0!==r?new h(t,tt(i,n),r):void 0!==i?new h(t,tt(i,n)):new h(t):Je in t?ot(f,t):ut.call(f,t):new h(S(t))}),be(p!==Function.prototype?q(h).concat(q(p)):q(h),function(e){e in f||y(f,e,h[e])}),f.prototype=v,v.constructor=f);var w=v[He],E=!!w&&("values"==w.name||void 0==w.name),T=vt.values;y(f,Ge,!0),y(v,Je,a),y(v,$e,!0),y(v,Ye,f),(o?new f(1)[ze]==a:ze in v)||re(v,ze,{get:function(){return a}}),m[a]=f,s(s.G+s.W+s.F*(f!=h),m),s(s.S,a,{BYTES_PER_ELEMENT:n}),s(s.S+s.F*i(function(){h.of.call(f,1)}),a,{from:ut,of:dt}),"BYTES_PER_ELEMENT"in v||y(v,"BYTES_PER_ELEMENT",n),s(s.P,a,gt),Z(a),s(s.P+s.F*et,a,{set:yt}),s(s.P+s.F*!E,a,vt),v.toString!=Ve&&(v.toString=Ve),s(s.P+s.F*i(function(){new f(1).slice()}),a,{slice:mt}),s(s.P+s.F*(i(function(){return[1,2].toLocaleString()!=new f([1,2]).toLocaleString()})||!i(function(){v.toLocaleString.call([1,2])})),a,{toLocaleString:pt}),Q[a]=E?w:T,E||y(v,He,T)}}else e.exports=function(){}});ht("Int8",1,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Uint8",1,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Uint8",1,function(e){return function(t,n,i){return e(this,t,n,i)}},!0),ht("Int16",2,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Uint16",2,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Int32",4,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Uint32",4,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Float32",4,function(e){return function(t,n,i){return e(this,t,n,i)}}),ht("Float64",8,function(e){return function(t,n,i){return e(this,t,n,i)}});var pt=function(e,t,n,i){try{return i?t(s(n)[0],n[1]):t(n)}catch(t){var r=e.return;throw void 0!==r&&s(r.call(e)),t}},gt=t(function(e){var t={},n={},i=e.exports=function(e,i,r,o,a){var l,c,u,d,f=a?function(){return e}:We(e),h=T(r,o,i?2:1),p=0;if("function"!=typeof f)throw TypeError(e+" is not iterable!");if(Le(f)){for(l=D(e.length);l>p;p++)if((d=i?h(s(c=e[p])[0],c[1]):h(e[p]))===t||d===n)return d}else for(u=f.call(e);!(c=u.next()).done;)if((d=pt(u,h,c.value,i))===t||d===n)return d};i.BREAK=t,i.RETURN=n}),mt=t(function(e){var t=E("meta"),n=p.f,i=0,s=Object.isExtensible||function(){return!0},a=!o(function(){return s(Object.preventExtensions({}))}),l=function(e){n(e,t,{value:{i:"O"+ ++i,w:{}}})},c=e.exports={KEY:t,NEED:!1,fastKey:function(e,n){if(!r(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!v(e,t)){if(!s(e))return"F";if(!n)return"E";l(e)}return e[t].i},getWeak:function(e,n){if(!v(e,t)){if(!s(e))return!0;if(!n)return!1;l(e)}return e[t].w},onFreeze:function(e){return a&&c.NEED&&s(e)&&!v(e,t)&&l(e),e}}}),yt=(mt.KEY,mt.NEED,mt.fastKey,mt.getWeak,mt.onFreeze,function(e,t){if(!r(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e}),vt=p.f,bt=mt.fastKey,wt=a?"_s":"size",Et=function(e,t){var n,i=bt(t);if("F"!==i)return e._i[i];for(n=e._f;n;n=n.n)if(n.k==t)return n},kt={getConstructor:function(e,t,n,i){var r=e(function(e,s){F(e,r,t,"_i"),e._t=t,e._i=Be(null),e._f=void 0,e._l=void 0,e[wt]=0,void 0!=s&>(s,n,e[i],e)});return I(r.prototype,{clear:function(){for(var e=yt(this,t),n=e._i,i=e._f;i;i=i.n)i.r=!0,i.p&&(i.p=i.p.n=void 0),delete n[i.i];e._f=e._l=void 0,e[wt]=0},delete:function(e){var n=yt(this,t),i=Et(n,e);if(i){var r=i.n,s=i.p;delete n._i[i.i],i.r=!0,s&&(s.n=r),r&&(r.p=s),n._f==i&&(n._f=r),n._l==i&&(n._l=s),n[wt]--}return!!i},forEach:function(e){yt(this,t);for(var n,i=T(e,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(i(n.v,n.k,this);n&&n.r;)n=n.p},has:function(e){return!!Et(yt(this,t),e)}}),a&&vt(r.prototype,"size",{get:function(){return yt(this,t)[wt]}}),r},def:function(e,t,n){var i,r,s=Et(e,t);return s?s.v=n:(e._l=s={i:r=bt(t,!0),k:t,v:n,p:i=e._l,n:void 0,r:!1},e._f||(e._f=s),i&&(i.n=s),e[wt]++,"F"!==r&&(e._i[r]=s)),e},getEntry:Et,setStrong:function(e,t,n){rt(e,t,function(e,n){this._t=yt(e,t),this._k=n,this._l=void 0},function(){for(var e=this._k,t=this._l;t&&t.r;)t=t.p;return this._t&&(this._l=t=t?t.n:this._t._f)?Xe(0,"keys"==e?t.k:"values"==e?t.v:[t.k,t.v]):(this._t=void 0,Xe(1))},n?"entries":"values",!n,!0),ve(t)}},St=function(e,t){if(s(e),!r(t)&&null!==t)throw TypeError(t+": can't set as prototype!")},Tt={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,n){try{(n=T(Function.call,ft.f(Object.prototype,"__proto__").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,i){return St(e,i),t?e.__proto__=i:n(e,i),e}}({},!1):void 0),check:St},At=Tt.set,_t=function(e,t,i,s,a,l){var c=n[e],u=c,d=a?"set":"add",f=u&&u.prototype,h={},p=function(e){var t=f[e];k(f,e,"delete"==e?function(e){return!(l&&!r(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(l&&!r(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return l&&!r(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,n){return t.call(this,0===e?0:e,n),this})};if("function"==typeof u&&(l||f.forEach&&!o(function(){(new u).entries().next()}))){var g=new u,m=g[d](l?{}:-0,1)!=g,y=o(function(){g.has(1)}),v=lt(function(e){new u(e)}),b=!l&&o(function(){for(var e=new u,t=5;t--;)e[d](t,t);return!e.has(-0)});v||((u=t(function(t,n){F(t,u,e);var i=function(e,t,n){var i,s=t.constructor;return s!==n&&"function"==typeof s&&(i=s.prototype)!==n.prototype&&r(i)&&At&&At(e,i),e}(new c,t,u);return void 0!=n&>(n,a,i[d],i),i})).prototype=f,f.constructor=u),(y||b)&&(p("delete"),p("has"),a&&p("get")),(b||m)&&p(d),l&&f.clear&&delete f.clear}else u=s.getConstructor(t,e,a,d),I(u.prototype,i),mt.NEED=!0;return he(u,e),h[e]=u,C(C.G+C.W+C.F*(u!=c),h),l||s.setStrong(u,e,a),u},Ct=(_t("Map",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{get:function(e){var t=kt.getEntry(yt(this,"Map"),e);return t&&t.v},set:function(e,t){return kt.def(yt(this,"Map"),0===e?0:e,t)}},kt,!0),_t("Set",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{add:function(e){return kt.def(yt(this,"Set"),e=0===e?0:e,e)}},kt),{f:Object.getOwnPropertySymbols}),Pt=Object.assign,xt=!Pt||o(function(){var e={},t={},n=Symbol(),i="abcdefghijklmnopqrst";return e[n]=7,i.split("").forEach(function(e){t[e]=e}),7!=Pt({},e)[n]||Object.keys(Pt({},t)).join("")!=i})?function(e,t){for(var n=le(e),i=arguments.length,r=1,s=Ct.f,o=ut.f;i>r;)for(var a,l=z(arguments[r++]),c=s?Ne(l).concat(s(l)):Ne(l),u=c.length,d=0;u>d;)o.call(l,a=c[d++])&&(n[a]=l[a]);return n}:Pt,Mt=mt.getWeak,Lt=Ke(5),Nt=Ke(6),Ot=0,jt=function(e){return e._l||(e._l=new It)},It=function(){this.a=[]},Ft=function(e,t){return Lt(e.a,function(e){return e[0]===t})};It.prototype={get:function(e){var t=Ft(this,e);if(t)return t[1]},has:function(e){return!!Ft(this,e)},set:function(e,t){var n=Ft(this,e);n?n[1]=t:this.a.push([e,t])},delete:function(e){var t=Nt(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}};var Rt={getConstructor:function(e,t,n,i){var s=e(function(e,r){F(e,s,t,"_i"),e._t=t,e._i=Ot++,e._l=void 0,void 0!=r&>(r,n,e[i],e)});return I(s.prototype,{delete:function(e){if(!r(e))return!1;var n=Mt(e);return!0===n?jt(yt(this,t)).delete(e):n&&v(n,this._i)&&delete n[this._i]},has:function(e){if(!r(e))return!1;var n=Mt(e);return!0===n?jt(yt(this,t)).has(e):n&&v(n,this._i)}}),s},def:function(e,t,n){var i=Mt(s(t),!0);return!0===i?jt(e).set(t,n):i[e._i]=n,e},ufstore:jt};t(function(e){var t,n=Ke(0),i=mt.getWeak,s=Object.isExtensible,a=Rt.ufstore,l={},c=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},u={get:function(e){if(r(e)){var t=i(e);return!0===t?a(yt(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return Rt.def(yt(this,"WeakMap"),e,t)}},d=e.exports=_t("WeakMap",c,u,Rt,!0,!0);o(function(){return 7!=(new d).set((Object.freeze||Object)(l),7).get(l)})&&(t=Rt.getConstructor(c,"WeakMap"),xt(t.prototype,u),mt.NEED=!0,n(["delete","has","get","set"],function(e){var n=d.prototype,i=n[e];k(n,e,function(n,o){if(r(n)&&!s(n)){this._f||(this._f=new t);var a=this._f[e](n,o);return"set"==e?this:a}return i.call(this,n,o)})}))});_t("WeakSet",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{add:function(e){return Rt.def(yt(this,"WeakSet"),e,!0)}},Rt,!1,!0);var qt=(n.Reflect||{}).apply,Bt=Function.apply;C(C.S+C.F*!o(function(){qt(function(){})}),"Reflect",{apply:function(e,t,n){var i=S(e),r=s(n);return qt?qt(i,t,r):Bt.call(i,t,r)}});var Vt=function(e,t,n){var i=void 0===n;switch(t.length){case 0:return i?e():e.call(n);case 1:return i?e(t[0]):e.call(n,t[0]);case 2:return i?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return i?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return i?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}return e.apply(n,t)},Dt=[].slice,Ut={},Ht=Function.bind||function(e){var t=S(this),n=Dt.call(arguments,1),i=function(){var r=n.concat(Dt.call(arguments));return this instanceof i?function(e,t,n){if(!(t in Ut)){for(var i=[],r=0;r<t;r++)i[r]="a["+r+"]";Ut[t]=Function("F,a","return new F("+i.join(",")+")")}return Ut[t](e,n)}(t,r.length,r):Vt(t,r,e)};return r(t.prototype)&&(i.prototype=t.prototype),i},Wt=(n.Reflect||{}).construct,zt=o(function(){function e(){}return!(Wt(function(){},[],e)instanceof e)}),Gt=!o(function(){Wt(function(){})});C(C.S+C.F*(zt||Gt),"Reflect",{construct:function(e,t){S(e),s(t);var n=arguments.length<3?e:S(arguments[2]);if(Gt&&!zt)return Wt(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var i=[null];return i.push.apply(i,t),new(Ht.apply(e,i))}var o=n.prototype,a=Be(r(o)?o:Object.prototype),l=Function.apply.call(e,a,t);return r(l)?l:a}}),C(C.S+C.F*o(function(){Reflect.defineProperty(p.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(e,t,n){s(e),t=f(t,!0),s(n);try{return p.f(e,t,n),!0}catch(e){return!1}}});var Yt=ft.f;C(C.S,"Reflect",{deleteProperty:function(e,t){var n=Yt(s(e),t);return!(n&&!n.configurable)&&delete e[t]}}),C(C.S,"Reflect",{get:function e(t,n){var i,o,a=arguments.length<3?t:arguments[2];return s(t)===a?t[n]:(i=ft.f(t,n))?v(i,"value")?i.value:void 0!==i.get?i.get.call(a):void 0:r(o=Ue(t))?e(o,n,a):void 0}}),C(C.S,"Reflect",{getOwnPropertyDescriptor:function(e,t){return ft.f(s(e),t)}}),C(C.S,"Reflect",{getPrototypeOf:function(e){return Ue(s(e))}}),C(C.S,"Reflect",{has:function(e,t){return t in e}});var Kt=Object.isExtensible;C(C.S,"Reflect",{isExtensible:function(e){return s(e),!Kt||Kt(e)}});var Qt=n.Reflect,Jt=Qt&&Qt.ownKeys||function(e){var t=ae.f(s(e)),n=Ct.f;return n?t.concat(n(e)):t};C(C.S,"Reflect",{ownKeys:Jt});var $t=Object.preventExtensions;C(C.S,"Reflect",{preventExtensions:function(e){s(e);try{return $t&&$t(e),!0}catch(e){return!1}}}),C(C.S,"Reflect",{set:function e(t,n,i){var o,a,l=arguments.length<4?t:arguments[3],c=ft.f(s(t),n);if(!c){if(r(a=Ue(t)))return e(a,n,i,l);c=g(0)}return v(c,"value")?!(!1===c.writable||!r(l)||((o=ft.f(l,n)||g(0)).value=i,p.f(l,n,o),0)):void 0!==c.set&&(c.set.call(l,i),!0)}}),Tt&&C(C.S,"Reflect",{setPrototypeOf:function(e,t){Tt.check(e,t);try{return Tt.set(e,t),!0}catch(e){return!1}}});var Xt,Zt,en,tn=n.process,nn=n.setImmediate,rn=n.clearImmediate,sn=n.MessageChannel,on=n.Dispatch,an=0,ln={},cn=function(){var e=+this;if(ln.hasOwnProperty(e)){var t=ln[e];delete ln[e],t()}},un=function(e){cn.call(e.data)};nn&&rn||(nn=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return ln[++an]=function(){Vt("function"==typeof e?e:Function(e),t)},Xt(an),an},rn=function(e){delete ln[e]},"process"==W(tn)?Xt=function(e){tn.nextTick(T(cn,e,1))}:on&&on.now?Xt=function(e){on.now(T(cn,e,1))}:sn?(en=(Zt=new sn).port2,Zt.port1.onmessage=un,Xt=T(en.postMessage,en,1)):n.addEventListener&&"function"==typeof postMessage&&!n.importScripts?(Xt=function(e){n.postMessage(e+"","*")},n.addEventListener("message",un,!1)):Xt="onreadystatechange"in u("script")?function(e){Ie.appendChild(u("script")).onreadystatechange=function(){Ie.removeChild(this),cn.call(e)}}:function(e){setTimeout(T(cn,e,1),0)});var dn={set:nn,clear:rn},fn=dn.set,hn=n.MutationObserver||n.WebKitMutationObserver,pn=n.process,gn=n.Promise,mn="process"==W(pn);var yn,vn,bn,wn,En={f:function(e){return new function(e){var t,n;this.promise=new e(function(e,i){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=i}),this.resolve=S(t),this.reject=S(n)}(e)}},kn=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}},Sn=dn.set,Tn=function(){var e,t,i,r=function(){var n,r;for(mn&&(n=pn.domain)&&n.exit();e;){r=e.fn,e=e.next;try{r()}catch(n){throw e?i():t=void 0,n}}t=void 0,n&&n.enter()};if(mn)i=function(){pn.nextTick(r)};else if(!hn||n.navigator&&n.navigator.standalone)if(gn&&gn.resolve){var s=gn.resolve();i=function(){s.then(r)}}else i=function(){fn.call(n,r)};else{var o=!0,a=document.createTextNode("");new hn(r).observe(a,{characterData:!0}),i=function(){a.data=o=!o}}return function(n){var r={fn:n,next:void 0};t&&(t.next=r),e||(e=r,i()),t=r}}(),An=n.TypeError,_n=n.process,Cn=n.Promise,Pn="process"==Ce(_n),xn=function(){},Mn=vn=En.f,Ln=!!function(){try{var e=Cn.resolve(1),t=(e.constructor={})[ue("species")]=function(e){e(xn,xn)};return(Pn||"function"==typeof PromiseRejectionEvent)&&e.then(xn)instanceof t}catch(e){}}(),Nn=function(e){var t;return!(!r(e)||"function"!=typeof(t=e.then))&&t},On=function(e,t){if(!e._n){e._n=!0;var n=e._c;Tn(function(){for(var i=e._v,r=1==e._s,s=0,o=function(t){var n,s,o=r?t.ok:t.fail,a=t.resolve,l=t.reject,c=t.domain;try{o?(r||(2==e._h&&Fn(e),e._h=1),!0===o?n=i:(c&&c.enter(),n=o(i),c&&c.exit()),n===t.promise?l(An("Promise-chain cycle")):(s=Nn(n))?s.call(n,a,l):a(n)):l(i)}catch(e){l(e)}};n.length>s;)o(n[s++]);e._c=[],e._n=!1,t&&!e._h&&jn(e)})}},jn=function(e){Sn.call(n,function(){var t,i,r,s=e._v,o=In(e);if(o&&(t=kn(function(){Pn?_n.emit("unhandledRejection",s,e):(i=n.onunhandledrejection)?i({promise:e,reason:s}):(r=n.console)&&r.error&&r.error("Unhandled promise rejection",s)}),e._h=Pn||In(e)?2:1),e._a=void 0,o&&t.e)throw t.v})},In=function(e){return 1!==e._h&&0===(e._a||e._c).length},Fn=function(e){Sn.call(n,function(){var t;Pn?_n.emit("rejectionHandled",e):(t=n.onrejectionhandled)&&t({promise:e,reason:e._v})})},Rn=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),On(t,!0))},qn=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw An("Promise can't be resolved itself");(t=Nn(e))?Tn(function(){var i={_w:n,_d:!1};try{t.call(e,T(qn,i,1),T(Rn,i,1))}catch(e){Rn.call(i,e)}}):(n._v=e,n._s=1,On(n,!1))}catch(e){Rn.call({_w:n,_d:!1},e)}}};Ln||(Cn=function(e){F(this,Cn,"Promise","_h"),S(e),yn.call(this);try{e(T(qn,this,1),T(Rn,this,1))}catch(e){Rn.call(this,e)}},(yn=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=I(Cn.prototype,{then:function(e,t){var n=Mn(me(this,Cn));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=Pn?_n.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&On(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),bn=function(){var e=new yn;this.promise=e,this.resolve=T(qn,e,1),this.reject=T(Rn,e,1)},En.f=Mn=function(e){return e===Cn||e===wn?new bn(e):vn(e)}),C(C.G+C.W+C.F*!Ln,{Promise:Cn}),he(Cn,"Promise"),ve("Promise"),wn=i.Promise,C(C.S+C.F*!Ln,"Promise",{reject:function(e){var t=Mn(this);return(0,t.reject)(e),t.promise}}),C(C.S+C.F*!Ln,"Promise",{resolve:function(e){return function(e,t){if(s(e),r(t)&&t.constructor===e)return t;var n=En.f(e);return(0,n.resolve)(t),n.promise}(this,e)}}),C(C.S+C.F*!(Ln&<(function(e){Cn.all(e).catch(xn)})),"Promise",{all:function(e){var t=this,n=Mn(t),i=n.resolve,r=n.reject,s=kn(function(){var n=[],s=0,o=1;gt(e,!1,function(e){var a=s++,l=!1;n.push(void 0),o++,t.resolve(e).then(function(e){l||(l=!0,n[a]=e,--o||i(n))},r)}),--o||i(n)});return s.e&&r(s.v),n.promise},race:function(e){var t=this,n=Mn(t),i=n.reject,r=kn(function(){gt(e,!1,function(e){t.resolve(e).then(n.resolve,i)})});return r.e&&i(r.v),n.promise}});var Bn={f:ue},Vn=p.f,Dn=function(e){var t=i.Symbol||(i.Symbol=n.Symbol||{});"_"==e.charAt(0)||e in t||Vn(t,e,{value:Bn.f(e)})},Un=ae.f,Hn={}.toString,Wn="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],zn={f:function(e){return Wn&&"[object Window]"==Hn.call(e)?function(e){try{return Un(e)}catch(e){return Wn.slice()}}(e):Un(Y(e))}},Gn=mt.KEY,Yn=ft.f,Kn=p.f,Qn=zn.f,Jn=n.Symbol,$n=n.JSON,Xn=$n&&$n.stringify,Zn=ue("_hidden"),ei=ue("toPrimitive"),ti={}.propertyIsEnumerable,ni=Z("symbol-registry"),ii=Z("symbols"),ri=Z("op-symbols"),si=Object.prototype,oi="function"==typeof Jn,ai=n.QObject,li=!ai||!ai.prototype||!ai.prototype.findChild,ci=a&&o(function(){return 7!=Be(Kn({},"a",{get:function(){return Kn(this,"a",{value:7}).a}})).a})?function(e,t,n){var i=Yn(si,t);i&&delete si[t],Kn(e,t,n),i&&e!==si&&Kn(si,t,i)}:Kn,ui=function(e){var t=ii[e]=Be(Jn.prototype);return t._k=e,t},di=oi&&"symbol"==typeof Jn.iterator?function(e){return"symbol"==typeof e}:function(e){return e instanceof Jn},fi=function(e,t,n){return e===si&&fi(ri,t,n),s(e),t=f(t,!0),s(n),v(ii,t)?(n.enumerable?(v(e,Zn)&&e[Zn][t]&&(e[Zn][t]=!1),n=Be(n,{enumerable:g(0,!1)})):(v(e,Zn)||Kn(e,Zn,g(1,{})),e[Zn][t]=!0),ci(e,t,n)):Kn(e,t,n)},hi=function(e,t){s(e);for(var n,i=function(e){var t=Ne(e),n=Ct.f;if(n)for(var i,r=n(e),s=ut.f,o=0;r.length>o;)s.call(e,i=r[o++])&&t.push(i);return t}(t=Y(t)),r=0,o=i.length;o>r;)fi(e,n=i[r++],t[n]);return e},pi=function(e){var t=ti.call(this,e=f(e,!0));return!(this===si&&v(ii,e)&&!v(ri,e))&&(!(t||!v(this,e)||!v(ii,e)||v(this,Zn)&&this[Zn][e])||t)},gi=function(e,t){if(e=Y(e),t=f(t,!0),e!==si||!v(ii,t)||v(ri,t)){var n=Yn(e,t);return!n||!v(ii,t)||v(e,Zn)&&e[Zn][t]||(n.enumerable=!0),n}},mi=function(e){for(var t,n=Qn(Y(e)),i=[],r=0;n.length>r;)v(ii,t=n[r++])||t==Zn||t==Gn||i.push(t);return i},yi=function(e){for(var t,n=e===si,i=Qn(n?ri:Y(e)),r=[],s=0;i.length>s;)!v(ii,t=i[s++])||n&&!v(si,t)||r.push(ii[t]);return r};oi||(k((Jn=function(){if(this instanceof Jn)throw TypeError("Symbol is not a constructor!");var e=E(arguments.length>0?arguments[0]:void 0),t=function(n){this===si&&t.call(ri,n),v(this,Zn)&&v(this[Zn],e)&&(this[Zn][e]=!1),ci(this,e,g(1,n))};return a&&li&&ci(si,e,{configurable:!0,set:t}),ui(e)}).prototype,"toString",function(){return this._k}),ft.f=gi,p.f=fi,ae.f=zn.f=mi,ut.f=pi,Ct.f=yi,a&&k(si,"propertyIsEnumerable",pi,!0),Bn.f=function(e){return ui(ue(e))}),C(C.G+C.W+C.F*!oi,{Symbol:Jn});for(var vi="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),bi=0;vi.length>bi;)ue(vi[bi++]);for(var wi=Ne(ue.store),Ei=0;wi.length>Ei;)Dn(wi[Ei++]);C(C.S+C.F*!oi,"Symbol",{for:function(e){return v(ni,e+="")?ni[e]:ni[e]=Jn(e)},keyFor:function(e){if(!di(e))throw TypeError(e+" is not a symbol!");for(var t in ni)if(ni[t]===e)return t},useSetter:function(){li=!0},useSimple:function(){li=!1}}),C(C.S+C.F*!oi,"Object",{create:function(e,t){return void 0===t?Be(e):hi(Be(e),t)},defineProperty:fi,defineProperties:hi,getOwnPropertyDescriptor:gi,getOwnPropertyNames:mi,getOwnPropertySymbols:yi}),$n&&C(C.S+C.F*(!oi||o(function(){var e=Jn();return"[null]"!=Xn([e])||"{}"!=Xn({a:e})||"{}"!=Xn(Object(e))})),"JSON",{stringify:function(e){for(var t,n,i=[e],s=1;arguments.length>s;)i.push(arguments[s++]);if(n=t=i[1],(r(t)||void 0!==e)&&!di(e))return ze(t)||(t=function(e,t){if("function"==typeof n&&(t=n.call(this,e,t)),!di(t))return t}),i[1]=t,Xn.apply($n,i)}}),Jn.prototype[ei]||m(Jn.prototype,ei,Jn.prototype.valueOf),he(Jn,"Symbol"),he(Math,"Math",!0),he(n.JSON,"JSON",!0);var ki=function(e,t){var n=(i.Object||{})[e]||Object[e],r={};r[e]=t(n),C(C.S+C.F*o(function(){n(1)}),"Object",r)},Si=mt.onFreeze;ki("freeze",function(e){return function(t){return e&&r(t)?e(Si(t)):t}});var Ti=mt.onFreeze;ki("seal",function(e){return function(t){return e&&r(t)?e(Ti(t)):t}});var Ai=mt.onFreeze;ki("preventExtensions",function(e){return function(t){return e&&r(t)?e(Ai(t)):t}}),ki("isFrozen",function(e){return function(t){return!r(t)||!!e&&e(t)}}),ki("isSealed",function(e){return function(t){return!r(t)||!!e&&e(t)}}),ki("isExtensible",function(e){return function(t){return!!r(t)&&(!e||e(t))}});var _i=ft.f;ki("getOwnPropertyDescriptor",function(){return function(e,t){return _i(Y(e),t)}}),ki("getPrototypeOf",function(){return function(e){return Ue(le(e))}}),ki("keys",function(){return function(e){return Ne(le(e))}}),ki("getOwnPropertyNames",function(){return zn.f}),C(C.S+C.F,"Object",{assign:xt});var Ci=Object.is||function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t};C(C.S,"Object",{is:Ci});var Pi=p.f,xi=Function.prototype,Mi=/^\s*function ([^ (]*)/;"name"in xi||a&&Pi(xi,"name",{configurable:!0,get:function(){try{return(""+this).match(Mi)[1]}catch(e){return""}}}),C(C.S,"String",{raw:function(e){for(var t=Y(e.raw),n=D(t.length),i=arguments.length,r=[],s=0;n>s;)r.push(String(t[s++])),s<i&&r.push(String(arguments[s]));return r.join("")}});var Li=String.fromCharCode,Ni=String.fromCodePoint;C(C.S+C.F*(!!Ni&&1!=Ni.length),"String",{fromCodePoint:function(e){for(var t,n=[],i=arguments.length,r=0;i>r;){if(t=+arguments[r++],J(t,1114111)!==t)throw RangeError(t+" is not a valid code point");n.push(t<65536?Li(t):Li(55296+((t-=65536)>>10),t%1024+56320))}return n.join("")}});var Oi,ji=(Oi=!1,function(e,t){var n,i,r=String(G(e)),s=B(t),o=r.length;return s<0||s>=o?Oi?"":void 0:(n=r.charCodeAt(s))<55296||n>56319||s+1===o||(i=r.charCodeAt(s+1))<56320||i>57343?Oi?r.charAt(s):n:Oi?r.slice(s,s+2):i-56320+(n-55296<<10)+65536});C(C.P,"String",{codePointAt:function(e){return ji(this,e)}});var Ii=function(e){var t=String(G(this)),n="",i=B(e);if(i<0||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(t+=t))1&i&&(n+=t);return n};C(C.P,"String",{repeat:Ii});var Fi=ue("match"),Ri=function(e){var t;return r(e)&&(void 0!==(t=e[Fi])?!!t:"RegExp"==W(e))},qi=function(e,t,n){if(Ri(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(G(e))},Bi=ue("match"),Vi=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[Bi]=!1,!"/./"[e](t)}catch(e){}}return!0},Di="".startsWith;C(C.P+C.F*Vi("startsWith"),"String",{startsWith:function(e){var t=qi(this,e,"startsWith"),n=D(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),i=String(e);return Di?Di.call(t,i,n):t.slice(n,n+i.length)===i}});var Ui="".endsWith;C(C.P+C.F*Vi("endsWith"),"String",{endsWith:function(e){var t=qi(this,e,"endsWith"),n=arguments.length>1?arguments[1]:void 0,i=D(t.length),r=void 0===n?i:Math.min(D(n),i),s=String(e);return Ui?Ui.call(t,s,r):t.slice(r-s.length,r)===s}});C(C.P+C.F*Vi("includes"),"String",{includes:function(e){return!!~qi(this,e,"includes").indexOf(e,arguments.length>1?arguments[1]:void 0)}});a&&"g"!=/./g.flags&&p.f(RegExp.prototype,"flags",{configurable:!0,get:function(){var e=s(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}});var Hi=function(e,t,n){var i=ue(e),r=n(G,i,""[e]),s=r[0],a=r[1];o(function(){var t={};return t[i]=function(){return 7},7!=""[e](t)})&&(k(String.prototype,e,s),m(RegExp.prototype,i,2==t?function(e,t){return a.call(e,this,t)}:function(e){return a.call(e,this)}))};Hi("match",1,function(e,t,n){return[function(n){var i=e(this),r=void 0==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},n]}),Hi("replace",2,function(e,t,n){return[function(i,r){var s=e(this),o=void 0==i?void 0:i[t];return void 0!==o?o.call(i,s,r):n.call(String(s),i,r)},n]}),Hi("split",2,function(e,t,n){var i=Ri,r=n,s=[].push;if("c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length){var o=void 0===/()??/.exec("")[1];n=function(e,t){var n=String(this);if(void 0===e&&0===t)return[];if(!i(e))return r.call(n,e,t);var a,l,c,u,d,f=[],h=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),p=0,g=void 0===t?4294967295:t>>>0,m=new RegExp(e.source,h+"g");for(o||(a=new RegExp("^"+m.source+"$(?!\\s)",h));(l=m.exec(n))&&!((c=l.index+l[0].length)>p&&(f.push(n.slice(p,l.index)),!o&&l.length>1&&l[0].replace(a,function(){for(d=1;d<arguments.length-2;d++)void 0===arguments[d]&&(l[d]=void 0)}),l.length>1&&l.index<n.length&&s.apply(f,l.slice(1)),u=l[0].length,p=c,f.length>=g));)m.lastIndex===l.index&&m.lastIndex++;return p===n.length?!u&&m.test("")||f.push(""):f.push(n.slice(p)),f.length>g?f.slice(0,g):f}}else"0".split(void 0,0).length&&(n=function(e,t){return void 0===e&&0===t?[]:r.call(this,e,t)});return[function(i,r){var s=e(this),o=void 0==i?void 0:i[t];return void 0!==o?o.call(i,s,r):n.call(String(s),i,r)},n]}),Hi("search",1,function(e,t,n){return[function(n){var i=e(this),r=void 0==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},n]});var Wi=function(e,t,n){t in e?p.f(e,t,g(0,n)):e[t]=n};C(C.S+C.F*!lt(function(e){}),"Array",{from:function(e){var t,n,i,r,s=le(e),o="function"==typeof this?this:Array,a=arguments.length,l=a>1?arguments[1]:void 0,c=void 0!==l,u=0,d=We(s);if(c&&(l=T(l,a>2?arguments[2]:void 0,2)),void 0==d||o==Array&&Le(d))for(n=new o(t=D(s.length));t>u;u++)Wi(n,u,c?l(s[u],u):s[u]);else for(r=d.call(s),n=new o;!(i=r.next()).done;u++)Wi(n,u,c?pt(r,l,[i.value,u],!0):i.value);return n.length=u,n}}),C(C.S+C.F*o(function(){function e(){}return!(Array.of.call(e)instanceof e)}),"Array",{of:function(){for(var e=0,t=arguments.length,n=new("function"==typeof this?this:Array)(t);t>e;)Wi(n,e,arguments[e++]);return n.length=t,n}}),C(C.P,"Array",{copyWithin:ct}),$e("copyWithin");var zi=Ke(5),Gi=!0;"find"in[]&&Array(1).find(function(){Gi=!1}),C(C.P+C.F*Gi,"Array",{find:function(e){return zi(this,e,arguments.length>1?arguments[1]:void 0)}}),$e("find");var Yi=Ke(6),Ki=!0;"findIndex"in[]&&Array(1).findIndex(function(){Ki=!1}),C(C.P+C.F*Ki,"Array",{findIndex:function(e){return Yi(this,e,arguments.length>1?arguments[1]:void 0)}}),$e("findIndex"),C(C.P,"Array",{fill:ce}),$e("fill");var Qi=n.isFinite;C(C.S,"Number",{isFinite:function(e){return"number"==typeof e&&Qi(e)}});var Ji=Math.floor,$i=function(e){return!r(e)&&isFinite(e)&&Ji(e)===e};C(C.S,"Number",{isInteger:$i});var Xi=Math.abs;C(C.S,"Number",{isSafeInteger:function(e){return $i(e)&&Xi(e)<=9007199254740991}}),C(C.S,"Number",{isNaN:function(e){return e!=e}}),C(C.S,"Number",{EPSILON:Math.pow(2,-52)}),C(C.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991}),C(C.S,"Number",{MAX_SAFE_INTEGER:9007199254740991});var Zi=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:Math.log(1+e)},er=Math.sqrt,tr=Math.acosh;C(C.S+C.F*!(tr&&710==Math.floor(tr(Number.MAX_VALUE))&&tr(1/0)==1/0),"Math",{acosh:function(e){return(e=+e)<1?NaN:e>94906265.62425156?Math.log(e)+Math.LN2:Zi(e-1+er(e-1)*er(e+1))}});var nr=Math.asinh;C(C.S+C.F*!(nr&&1/nr(0)>0),"Math",{asinh:function e(t){return isFinite(t=+t)&&0!=t?t<0?-e(-t):Math.log(t+Math.sqrt(t*t+1)):t}});var ir=Math.atanh;C(C.S+C.F*!(ir&&1/ir(-0)<0),"Math",{atanh:function(e){return 0==(e=+e)?e:Math.log((1+e)/(1-e))/2}});var rr=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1};C(C.S,"Math",{cbrt:function(e){return rr(e=+e)*Math.pow(Math.abs(e),1/3)}}),C(C.S,"Math",{clz32:function(e){return(e>>>=0)?31-Math.floor(Math.log(e+.5)*Math.LOG2E):32}});var sr=Math.exp;C(C.S,"Math",{cosh:function(e){return(sr(e=+e)+sr(-e))/2}});var or=Math.expm1,ar=!or||or(10)>22025.465794806718||or(10)<22025.465794806718||-2e-17!=or(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:Math.exp(e)-1}:or;C(C.S+C.F*(ar!=Math.expm1),"Math",{expm1:ar});var lr=Math.pow,cr=lr(2,-52),ur=lr(2,-23),dr=lr(2,127)*(2-ur),fr=lr(2,-126),hr=Math.fround||function(e){var t,n,i=Math.abs(e),r=rr(e);return i<fr?r*(i/fr/ur+1/cr-1/cr)*fr*ur:(n=(t=(1+ur/cr)*i)-(t-i))>dr||n!=n?r*(1/0):r*n};C(C.S,"Math",{fround:hr});var pr=Math.abs;C(C.S,"Math",{hypot:function(e,t){for(var n,i,r=0,s=0,o=arguments.length,a=0;s<o;)a<(n=pr(arguments[s++]))?(r=r*(i=a/n)*i+1,a=n):r+=n>0?(i=n/a)*i:n;return a===1/0?1/0:a*Math.sqrt(r)}});var gr=Math.imul;C(C.S+C.F*o(function(){return-5!=gr(4294967295,5)||2!=gr.length}),"Math",{imul:function(e,t){var n=+e,i=+t,r=65535&n,s=65535&i;return 0|r*s+((65535&n>>>16)*s+r*(65535&i>>>16)<<16>>>0)}}),C(C.S,"Math",{log1p:Zi}),C(C.S,"Math",{log10:function(e){return Math.log(e)*Math.LOG10E}}),C(C.S,"Math",{log2:function(e){return Math.log(e)/Math.LN2}}),C(C.S,"Math",{sign:rr});var mr=Math.exp;C(C.S+C.F*o(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(e){return Math.abs(e=+e)<1?(ar(e)-ar(-e))/2:(mr(e-1)-mr(-e-1))*(Math.E/2)}});var yr=Math.exp;C(C.S,"Math",{tanh:function(e){var t=ar(e=+e),n=ar(-e);return t==1/0?1:n==1/0?-1:(t-n)/(yr(e)+yr(-e))}}),C(C.S,"Math",{trunc:function(e){return(e>0?Math.floor:Math.ceil)(e)}});var vr=$(!0);C(C.P,"Array",{includes:function(e){return vr(this,e,arguments.length>1?arguments[1]:void 0)}}),$e("includes");var br=ut.f,wr=function(e){return function(t){for(var n,i=Y(t),r=Ne(i),s=r.length,o=0,a=[];s>o;)br.call(i,n=r[o++])&&a.push(e?[n,i[n]]:i[n]);return a}},Er=wr(!1);C(C.S,"Object",{values:function(e){return Er(e)}});var kr=wr(!0);C(C.S,"Object",{entries:function(e){return kr(e)}}),C(C.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n,i=Y(e),r=ft.f,s=Jt(i),o={},a=0;s.length>a;)void 0!==(n=r(i,t=s[a++]))&&Wi(o,t,n);return o}});var Sr=function(e,t,n,i){var r=String(G(e)),s=r.length,o=void 0===n?" ":String(n),a=D(t);if(a<=s||""==o)return r;var l=a-s,c=Ii.call(o,Math.ceil(l/o.length));return c.length>l&&(c=c.slice(0,l)),i?c+r:r+c},Tr=n.navigator,Ar=Tr&&Tr.userAgent||"";C(C.P+C.F*/Version\/10\.\d+(\.\d+)? Safari\//.test(Ar),"String",{padStart:function(e){return Sr(this,e,arguments.length>1?arguments[1]:void 0,!0)}}),C(C.P+C.F*/Version\/10\.\d+(\.\d+)? Safari\//.test(Ar),"String",{padEnd:function(e){return Sr(this,e,arguments.length>1?arguments[1]:void 0,!1)}});var _r=[].slice,Cr=/MSIE .\./.test(Ar),Pr=function(e){return function(t,n){var i=arguments.length>2,r=!!i&&_r.call(arguments,2);return e(i?function(){("function"==typeof t?t:Function(t)).apply(this,r)}:t,n)}};C(C.G+C.B+C.F*Cr,{setTimeout:Pr(n.setTimeout),setInterval:Pr(n.setInterval)}),C(C.G+C.B,{setImmediate:dn.set,clearImmediate:dn.clear});for(var xr=ue("iterator"),Mr=ue("toStringTag"),Lr=Pe.Array,Nr={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},Or=Ne(Nr),jr=0;jr<Or.length;jr++){var Ir,Fr=Or[jr],Rr=Nr[Fr],qr=n[Fr],Br=qr&&qr.prototype;if(Br&&(Br[xr]||m(Br,xr,Lr),Br[Mr]||m(Br,Mr,Fr),Pe[Fr]=Lr,Rr))for(Ir in st)Br[Ir]||k(Br,Ir,st[Ir],!0)}t(function(t){!function(e){var n,i=Object.prototype,r=i.hasOwnProperty,s="function"==typeof Symbol?Symbol:{},o=s.iterator||"@@iterator",a=s.asyncIterator||"@@asyncIterator",l=s.toStringTag||"@@toStringTag",c=e.regeneratorRuntime;if(c)t.exports=c;else{(c=e.regeneratorRuntime=t.exports).wrap=b;var u="suspendedStart",d="suspendedYield",f="executing",h="completed",p={},g={};g[o]=function(){return this};var m=Object.getPrototypeOf,y=m&&m(m(M([])));y&&y!==i&&r.call(y,o)&&(g=y);var v=S.prototype=E.prototype=Object.create(g);k.prototype=v.constructor=S,S.constructor=k,S[l]=k.displayName="GeneratorFunction",c.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===k||"GeneratorFunction"===(t.displayName||t.name))},c.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,S):(e.__proto__=S,l in e||(e[l]="GeneratorFunction")),e.prototype=Object.create(v),e},c.awrap=function(e){return{__await:e}},T(A.prototype),A.prototype[a]=function(){return this},c.AsyncIterator=A,c.async=function(e,t,n,i){var r=new A(b(e,t,n,i));return c.isGeneratorFunction(t)?r:r.next().then(function(e){return e.done?e.value:r.next()})},T(v),v[l]="Generator",v[o]=function(){return this},v.toString=function(){return"[object Generator]"},c.keys=function(e){var t=[];for(var n in e)t.push(n);return t.reverse(),function n(){for(;t.length;){var i=t.pop();if(i in e)return n.value=i,n.done=!1,n}return n.done=!0,n}},c.values=M,x.prototype={constructor:x,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=n,this.done=!1,this.delegate=null,this.method="next",this.arg=n,this.tryEntries.forEach(P),!e)for(var t in this)"t"===t.charAt(0)&&r.call(this,t)&&!isNaN(+t.slice(1))&&(this[t]=n)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var t=this;function i(i,r){return a.type="throw",a.arg=e,t.next=i,r&&(t.method="next",t.arg=n),!!r}for(var s=this.tryEntries.length-1;s>=0;--s){var o=this.tryEntries[s],a=o.completion;if("root"===o.tryLoc)return i("end");if(o.tryLoc<=this.prev){var l=r.call(o,"catchLoc"),c=r.call(o,"finallyLoc");if(l&&c){if(this.prev<o.catchLoc)return i(o.catchLoc,!0);if(this.prev<o.finallyLoc)return i(o.finallyLoc)}else if(l){if(this.prev<o.catchLoc)return i(o.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<o.finallyLoc)return i(o.finallyLoc)}}}},abrupt:function(e,t){for(var n=this.tryEntries.length-1;n>=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&r.call(i,"finallyLoc")&&this.prev<i.finallyLoc){var s=i;break}}s&&("break"===e||"continue"===e)&&s.tryLoc<=t&&t<=s.finallyLoc&&(s=null);var o=s?s.completion:{};return o.type=e,o.arg=t,s?(this.method="next",this.next=s.finallyLoc,p):this.complete(o)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),p},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),P(n),p}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var i=n.completion;if("throw"===i.type){var r=i.arg;P(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,i){return this.delegate={iterator:M(e),resultName:t,nextLoc:i},"next"===this.method&&(this.arg=n),p}}}function b(e,t,n,i){var r=t&&t.prototype instanceof E?t:E,s=Object.create(r.prototype),o=new x(i||[]);return s._invoke=function(e,t,n){var i=u;return function(r,s){if(i===f)throw new Error("Generator is already running");if(i===h){if("throw"===r)throw s;return L()}for(n.method=r,n.arg=s;;){var o=n.delegate;if(o){var a=_(o,n);if(a){if(a===p)continue;return a}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(i===u)throw i=h,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);i=f;var l=w(e,t,n);if("normal"===l.type){if(i=n.done?h:d,l.arg===p)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(i=h,n.method="throw",n.arg=l.arg)}}}(e,n,o),s}function w(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}function E(){}function k(){}function S(){}function T(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function A(t){function n(e,i,s,o){var a=w(t[e],t,i);if("throw"!==a.type){var l=a.arg,c=l.value;return c&&"object"==typeof c&&r.call(c,"__await")?Promise.resolve(c.__await).then(function(e){n("next",e,s,o)},function(e){n("throw",e,s,o)}):Promise.resolve(c).then(function(e){l.value=e,s(l)},o)}o(a.arg)}var i;"object"==typeof e.process&&e.process.domain&&(n=e.process.domain.bind(n)),this._invoke=function(e,t){function r(){return new Promise(function(i,r){n(e,t,i,r)})}return i=i?i.then(r,r):r()}}function _(e,t){var i=e.iterator[t.method];if(i===n){if(t.delegate=null,"throw"===t.method){if(e.iterator.return&&(t.method="return",t.arg=n,_(e,t),"throw"===t.method))return p;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return p}var r=w(i,e.iterator,t.arg);if("throw"===r.type)return t.method="throw",t.arg=r.arg,t.delegate=null,p;var s=r.arg;return s?s.done?(t[e.resultName]=s.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=n),t.delegate=null,p):s:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,p)}function C(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function P(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function x(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(C,this),this.reset(!0)}function M(e){if(e){var t=e[o];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var i=-1,s=function t(){for(;++i<e.length;)if(r.call(e,i))return t.value=e[i],t.done=!1,t;return t.value=n,t.done=!0,t};return s.next=s}}return{next:L}}function L(){return{value:n,done:!0}}}("object"==typeof e?e:"object"==typeof window?window:"object"==typeof self?self:e)});try{var Vr=new window.CustomEvent("test");if(Vr.preventDefault(),!0!==Vr.defaultPrevented)throw new Error("Could not prevent default")}catch(e){var Dr=function(e,t){var n,i;return t=t||{bubbles:!1,cancelable:!1,detail:void 0},(n=document.createEvent("CustomEvent")).initCustomEvent(e,t.bubbles,t.cancelable,t.detail),i=n.preventDefault,n.preventDefault=function(){i.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(e){this.defaultPrevented=!0}},n};Dr.prototype=window.Event.prototype,window.CustomEvent=Dr}var Ur,Hr=t(function(e,t){var n;n=function(){var e=function(){},t={},n={},i={};function r(e,t){if(e){var r=i[e];if(n[e]=t,r)for(;r.length;)r[0](e,t),r.splice(0,1)}}function s(t,n){t.call&&(t={success:t}),n.length?(t.error||e)(n):(t.success||e)(t)}function o(t,n,i,r){var s,a,l=document,c=i.async,u=(i.numRetries||0)+1,d=i.before||e,f=t.replace(/^(css|img)!/,"");r=r||0,/(^css!|\.css$)/.test(t)?(s=!0,(a=l.createElement("link")).rel="stylesheet",a.href=f):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(a=l.createElement("img")).src=f:((a=l.createElement("script")).src=t,a.async=void 0===c||c),a.onload=a.onerror=a.onbeforeload=function(e){var l=e.type[0];if(s&&"hideFocus"in a)try{a.sheet.cssText.length||(l="e")}catch(e){l="e"}if("e"==l&&(r+=1)<u)return o(t,n,i,r);n(t,l,e.defaultPrevented)},!1!==d(t,a)&&l.head.appendChild(a)}function a(e,n,i){var a,l;if(n&&n.trim&&(a=n),l=(a?i:n)||{},a){if(a in t)throw"LoadJS";t[a]=!0}!function(e,t,n){var i,r,s=(e=e.push?e:[e]).length,a=s,l=[];for(i=function(e,n,i){if("e"==n&&l.push(e),"b"==n){if(!i)return;l.push(e)}--s||t(l)},r=0;r<a;r++)o(e[r],i,n)}(e,function(e){s(l,e),r(a,e)},l)}return a.ready=function(e,t){return function(e,t){var r,s,o,a=[],l=(e=e.push?e:[e]).length,c=l;for(r=function(e,n){n.length&&a.push(e),--c||t(a)};l--;)s=e[l],(o=n[s])?r(s,o):(i[s]=i[s]||[]).push(r)}(e,function(e){s(t,e)}),a},a.done=function(e){r(e,[])},a.reset=function(){t={},n={},i={}},a.isDefined=function(e){return e in t},a},e.exports=n()}),Wr={html5:"html5",youtube:"youtube",vimeo:"vimeo"},zr={audio:"audio",video:"video"},Gr=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},Yr=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),Kr=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},Qr=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],i=!0,r=!1,s=void 0;try{for(var o,a=e[Symbol.iterator]();!(i=(o=a.next()).done)&&(n.push(o.value),!t||n.length!==t);i=!0);}catch(e){r=!0,s=e}finally{try{!i&&a.return&&a.return()}finally{if(r)throw s}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),Jr={is:{plyr:function(e){return this.instanceof(e,window.Plyr)},object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.nullOrUndefined(e)&&Array.isArray(e)},weakMap:function(e){return this.instanceof(e,window.WeakMap)},nodeList:function(e){return this.instanceof(e,window.NodeList)},element:function(e){return this.instanceof(e,window.Element)},textNode:function(e){return this.getConstructor(e)===Text},event:function(e){return this.instanceof(e,window.Event)},cue:function(e){return this.instanceof(e,window.TextTrackCue)||this.instanceof(e,window.VTTCue)},track:function(e){return this.instanceof(e,TextTrack)||!this.nullOrUndefined(e)&&this.string(e.kind)},url:function(e){return!this.nullOrUndefined(e)&&/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(e)},nullOrUndefined:function(e){return null===e||void 0===e},empty:function(e){return this.nullOrUndefined(e)||(this.string(e)||this.array(e)||this.nodeList(e))&&!e.length||this.object(e)&&!Object.keys(e).length},instanceof:function(e,t){return Boolean(e&&t&&e instanceof t)},getConstructor:function(e){return this.nullOrUndefined(e)?null:e.constructor}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},fetch:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(n,i){try{var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.addEventListener("load",function(){if("text"===t)try{n(JSON.parse(r.responseText))}catch(e){n(r.responseText)}else n(r.response)}),r.addEventListener("error",function(){throw new Error(r.statusText)}),r.open("GET",e,!0),r.responseType=t,r.send()}catch(e){i(e)}})},loadScript:function(e){return new Promise(function(t,n){Hr(e,{success:t,error:n})})},loadSprite:function(e,t){if(Jr.is.string(e)){var n=Jr.is.string(t),i=function(){return document.querySelectorAll("#"+t).length};if(!n||!i()){var r=document.createElement("div");if(Jr.toggleHidden(r,!0),n&&r.setAttribute("id",t),$r.storage){var s=window.localStorage.getItem("cache-"+t);if(null!==s){var o=JSON.parse(s);return void a.call(r,o.content)}}Jr.fetch(e).then(function(e){Jr.is.empty(e)||($r.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:e})),a.call(r,e))}).catch(function(){})}}function a(e){n&&i()||(this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0]))}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},wrap:function(e,t){var n=e.length?e:[e];Array.from(n).reverse().forEach(function(e,n){var i=n>0?t.cloneNode(!0):t,r=e.parentNode,s=e.nextSibling;i.appendChild(e),s?r.insertBefore(i,s):r.appendChild(i)})},createElement:function(e,t,n){var i=document.createElement(e);return Jr.is.object(t)&&Jr.setAttributes(i,t),Jr.is.string(n)&&(i.textContent=n),i},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},insertElement:function(e,t,n,i){t.appendChild(Jr.createElement(e,n,i))},removeElement:function(e){Jr.is.nodeList(e)||Jr.is.array(e)?Array.from(e).forEach(Jr.removeElement):Jr.is.element(e)&&Jr.is.element(e.parentNode)&&e.parentNode.removeChild(e)},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},replaceElement:function(e,t){return Jr.is.element(t)&&Jr.is.element(t.parentNode)&&Jr.is.element(e)?(t.parentNode.replaceChild(e,t),e):null},setAttributes:function(e,t){Jr.is.element(e)&&!Jr.is.empty(t)&&Object.entries(t).forEach(function(t){var n=Qr(t,2),i=n[0],r=n[1];e.setAttribute(i,r)})},getAttributesFromSelector:function(e,t){if(!Jr.is.string(e)||Jr.is.empty(e))return{};var n={},i=t;return e.split(",").forEach(function(e){var t=e.trim(),r=t.replace(".",""),s=t.replace(/[[\]]/g,"").split("="),o=s[0],a=s.length>1?s[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":Jr.is.object(i)&&Jr.is.string(i.class)&&(i.class+=" "+r),n.class=r;break;case"#":n.id=t.replace("#","");break;case"[":n[o]=a}}),n},toggleHidden:function(e,t){if(Jr.is.element(e)){var n=t;Jr.is.boolean(n)||(n=!e.hasAttribute("hidden")),n?e.setAttribute("hidden",""):e.removeAttribute("hidden")}},toggleClass:function(e,t,n){if(Jr.is.element(e)){var i=e.classList.contains(t);return e.classList[n?"add":"remove"](t),n&&!i||!n&&i}return null},hasClass:function(e,t){return Jr.is.element(e)&&e.classList.contains(t)},matches:function(e,t){var n={Element:Element};var i=n.matches||n.webkitMatchesSelector||n.mozMatchesSelector||n.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return i.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(Jr.is.element(e)){var n=Jr.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=n[0],r=n[n.length-1],s=function(e){if("Tab"===e.key&&9===e.keyCode){var t=Jr.getFocusElement();t!==r||e.shiftKey?t===i&&e.shiftKey&&(r.focus(),e.preventDefault()):(i.focus(),e.preventDefault())}};t?Jr.on(this.elements.container,"keydown",s,!1):Jr.off(this.elements.container,"keydown",s,!1)}},toggleListener:function(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3],r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(!Jr.is.empty(e)&&!Jr.is.empty(t)&&Jr.is.function(n))if(Jr.is.nodeList(e)||Jr.is.array(e))Array.from(e).forEach(function(e){e instanceof Node&&Jr.toggleListener.call(null,e,t,n,i,r,s)});else{var o=t.split(" "),a=s;$r.passiveListeners&&(a={passive:r,capture:s}),o.forEach(function(t){e[i?"addEventListener":"removeEventListener"](t,n,a)})}},on:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments[2],i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Jr.toggleListener(e,t,n,!0,i,r)},off:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments[2],i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Jr.toggleListener(e,t,n,!1,i,r)},dispatchEvent:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(Jr.is.element(e)&&!Jr.is.empty(t)){var r=new CustomEvent(t,{bubbles:n,detail:Object.assign({},i,{plyr:Jr.is.plyr(this)?this:null})});e.dispatchEvent(r)}},toggleState:function(e,t){if(Jr.is.array(e)||Jr.is.nodeList(e))Array.from(e).forEach(function(e){return Jr.toggleState(e,t)});else if(Jr.is.element(e)){var n="true"===e.getAttribute("aria-pressed"),i=Jr.is.boolean(t)?t:!n;e.setAttribute("aria-pressed",i)}},format:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];return Jr.is.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return Jr.is.string(n[t])?n[t]:""})},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},getHours:function(e){return parseInt(e/60/60%60,10)},getMinutes:function(e){return parseInt(e/60%60,10)},getSeconds:function(e){return parseInt(e%60,10)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!Jr.is.number(e))return this.formatTime(null,t,n);var i=function(e){return("0"+e).slice(-2)},r=this.getHours(e),s=this.getMinutes(e),o=this.getSeconds(e);return t||r>0?r+=":":r="",(n?"-":"")+r+i(s)+":"+i(o)},replaceAll:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g,"\\$1"),"g"),n.toString())},toTitleCase:function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})},toPascalCase:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=Jr.replaceAll(e,"-"," "),e=Jr.replaceAll(e,"_"," "),e=Jr.toTitleCase(e),Jr.replaceAll(e," ","")},toCamelCase:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=Jr.toPascalCase(e)).charAt(0).toLowerCase()+e.slice(1)},extend:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,n=Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];if(!n.length)return e;var r=n.shift();return Jr.is.object(r)?(Object.keys(r).forEach(function(t){Jr.is.object(r[t])?(Object.keys(e).includes(t)||Object.assign(e,Kr({},t,{})),Jr.extend(e[t],r[t])):Object.assign(e,Kr({},t,r[t]))}),Jr.extend.apply(Jr,[e].concat(function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}(n)))):e},dedupe:function(e){return Jr.is.array(e)?e.filter(function(t,n){return e.indexOf(t)===n}):e},closest:function(e,t){return Jr.is.array(e)&&e.length?e.reduce(function(e,n){return Math.abs(n-t)<Math.abs(e-t)?n:e}):null},getProviderByUrl:function(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/.test(e)?Wr.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?Wr.vimeo:null},parseYouTubeId:function(e){if(Jr.is.empty(e))return null;return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:e},parseVimeoId:function(e){if(Jr.is.empty(e))return null;if(Jr.is.number(Number(e)))return e;return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e},parseUrl:function(e){var t=document.createElement("a");return t.href=e,t},getUrlParams:function(e){var t=e;(e.startsWith("http://")||e.startsWith("https://"))&&(t=this.parseUrl(e).search);return this.is.empty(t)?null:t.slice(t.indexOf("?")+1).split("&").reduce(function(e,t){var n=t.split("="),i=Qr(n,2),r=i[0],s=i[1];return Object.assign(e,Kr({},r,decodeURIComponent(s)))},{})},buildUrlParams:function(e){return Jr.is.object(e)?Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&"):""},stripHTML:function(e){var t=document.createDocumentFragment(),n=document.createElement("div");return t.appendChild(n),n.innerHTML=e,t.firstChild.innerText},getAspectRatio:function(e,t){var n=function e(t,n){return 0===n?t:e(n,t%n)}(e,t);return e/n+":"+t/n},get transitionEndEvent(){var e=document.createElement("span"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n=Object.keys(t).find(function(t){return void 0!==e.style[t]});return!!Jr.is.string(n)&&t[n]},repaint:function(e){setTimeout(function(){Jr.toggleHidden(e,!0),e.offsetHeight,Jr.toggleHidden(e,!1)},0)}},$r={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,n){var i=!1,r=!1,s=Jr.getBrowser(),o=s.isIPhone&&n&&$r.playsinline;switch(t+":"+e){case"html5:video":r=(i=$r.video)&&$r.rangeInput&&(!s.isIPhone||o);break;case"html5:audio":r=(i=$r.audio)&&$r.rangeInput;break;case"youtube:video":case"vimeo:video":i=!0,r=$r.rangeInput&&(!s.isIPhone||o);break;default:r=(i=$r.audio&&$r.video)&&$r.rangeInput}return{api:i,ui:r}},pip:!Jr.getBrowser().isIPhone&&Jr.is.function(Jr.createElement("video").webkitSetPresentationMode),airplay:Jr.is.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){var t=this.media;try{if(!this.isHTML5||!Jr.is.function(t.canPlayType))return!1;if(e.includes("codecs="))return t.canPlayType(e).replace(/no/,"");if(this.isVideo)switch(e){case"video/webm":return t.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,"");case"video/mp4":return t.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,"");case"video/ogg":return t.canPlayType('video/ogg; codecs="theora"').replace(/no/,"");default:return!1}else if(this.isAudio)switch(e){case"audio/mpeg":return t.canPlayType("audio/mpeg;").replace(/no/,"");case"audio/ogg":return t.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,"");case"audio/wav":return t.canPlayType('audio/wav; codecs="1"').replace(/no/,"");default:return!1}}catch(e){return!1}return!1},textTracks:"textTracks"in document.createElement("video"),passiveListeners:function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t)}catch(e){}return e}(),rangeInput:(Ur=document.createElement("input"),Ur.type="range","range"===Ur.type),touch:"ontouchstart"in document.documentElement,transitions:!1!==Jr.transitionEndEvent,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},Xr={getSources:function(){return this.isHTML5?this.media.querySelectorAll("source"):null},getQualityOptions:function(){if(!this.isHTML5)return null;var e=Xr.getSources.call(this);if(Jr.is.empty(e))return null;var t=Array.from(e).filter(function(e){return!Jr.is.empty(e.getAttribute("size"))});return Jr.is.empty(t)?null:Jr.dedupe(t.map(function(e){return Number(e.getAttribute("size"))}))},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=Xr.getSources.call(e);if(Jr.is.empty(t))return null;var n=Array.from(t).filter(function(t){return t.getAttribute("src")===e.source});return Jr.is.empty(n)?null:Number(n[0].getAttribute("size"))},set:function(t){var n=Xr.getSources.call(e);if(!Jr.is.empty(n)){var i=Array.from(n).filter(function(e){return Number(e.getAttribute("size"))===t});if(!Jr.is.empty(i)){var r=i.filter(function(t){return $r.mime.call(e,t.getAttribute("type"))});if(!Jr.is.empty(r)){Jr.dispatchEvent.call(e,e.media,"qualityrequested",!1,{quality:t});var s=e.currentTime,o=e.playing;e.media.src=r[0].getAttribute("src"),e.media.load(),o&&e.play(),e.currentTime=s,Jr.dispatchEvent.call(e,e.media,"qualitychange",!1,{quality:t})}}}}})}},cancelRequests:function(){this.isHTML5&&(Jr.removeElement(Xr.getSources()),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}},Zr=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(Jr.is.empty(e)||Jr.is.empty(t)||!Object.keys(t.i18n).includes(e))return"";var n=t.i18n[e],i={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(i).forEach(function(e){var t=Qr(e,2),i=t[0],r=t[1];n=Jr.replaceAll(n,i,r)}),n},es=Jr.getBrowser(),ts={addStyleHook:function(){Jr.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),Jr.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for "+this.provider+" "+this.type),void ts.toggleNativeControls.call(this,!0);Jr.is.element(this.elements.controls)||(is.inject.call(this),this.listeners.controls()),ts.toggleNativeControls.call(this),rs.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,ts.updateVolume.call(this),ts.timeUpdate.call(this),ts.checkPlaying.call(this),Jr.toggleClass(this.elements.container,this.config.classNames.pip.supported,$r.pip&&this.isHTML5&&this.isVideo),Jr.toggleClass(this.elements.container,this.config.classNames.airplay.supported,$r.airplay&&this.isHTML5),Jr.toggleClass(this.elements.container,this.config.classNames.isIos,es.isIos),Jr.toggleClass(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){Jr.dispatchEvent.call(e,e.media,"ready")},0),ts.setTitle.call(this),ts.setPoster.call(this)},setTitle:function(){var e=Zr("play",this.config);if(Jr.is.string(this.config.title)&&!Jr.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),Jr.is.nodeList(this.elements.buttons.play)&&Array.from(this.elements.buttons.play).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=Jr.getElement.call(this,"iframe");if(!Jr.is.element(t))return;var n=Jr.is.empty(this.config.title)?"video":this.config.title,i=Zr("frameTitle",this.config);t.setAttribute("title",i.replace("{title}",n))}},setPoster:function(){if(Jr.is.element(this.elements.poster)&&!Jr.is.empty(this.poster)){var e=this.poster.split(",");this.elements.poster.style.backgroundImage=e.map(function(e){return"url('"+e+"')"}).join(",")}},checkPlaying:function(e){Jr.toggleClass(this.elements.container,this.config.classNames.playing,this.playing),Jr.toggleClass(this.elements.container,this.config.classNames.paused,this.paused),Jr.toggleClass(this.elements.container,this.config.classNames.stopped,this.stopped),Jr.toggleState(this.elements.buttons.play,this.playing),Jr.is.event(e)&&"timeupdate"===e.type||this.toggleControls(!this.playing)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){Jr.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},checkFailed:function(){var e=this;this.failed=3===this.media.networkState,this.failed&&(Jr.toggleClass(this.elements.container,this.config.classNames.loading,!1),Jr.toggleClass(this.elements.container,this.config.classNames.error,!0)),clearTimeout(this.timers.failed),this.timers.loading=setTimeout(function(){Jr.toggleClass(e.elements.container,e.config.classNames.loading,e.loading),e.toggleControls(e.loading)},this.loading?250:0)},updateVolume:function(){this.supported.ui&&(Jr.is.element(this.elements.inputs.volume)&&ts.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),Jr.is.element(this.elements.buttons.mute)&&Jr.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;Jr.is.element(e)&&(e.value=t,is.updateRangeFill.call(this,e))},setProgress:function(e,t){var n=Jr.is.number(t)?t:0,i=Jr.is.element(e)?e:this.elements.display.buffer;if(Jr.is.element(i)){i.value=n;var r=i.getElementsByTagName("span")[0];Jr.is.element(r)&&(r.childNodes[0].nodeValue=n)}},updateProgress:function(e){if(this.supported.ui&&Jr.is.event(e)){var t=0;if(e)switch(e.type){case"timeupdate":case"seeking":t=Jr.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&ts.setRange.call(this,this.elements.inputs.seek,t);break;case"playing":case"progress":ts.setProgress.call(this,this.elements.display.buffer,100*this.buffered)}}},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(Jr.is.element(e)&&Jr.is.number(t)){var i=Jr.getHours(this.duration)>0;e.textContent=Jr.formatTime(t,i,n)}},timeUpdate:function(e){var t=!Jr.is.element(this.elements.display.duration)&&this.config.invertTime;ts.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||ts.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui){var e=Jr.is.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&ts.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&ts.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),is.updateSeekTooltip.call(this)}}},ns=Jr.getBrowser(),is={updateRangeFill:function(e){var t=Jr.is.event(e)?e.target:e;Jr.is.element(t)&&"range"===t.getAttribute("type")&&(t.setAttribute("aria-valuenow",t.value),ns.isWebkit&&t.style.setProperty("--value",t.value/t.max*100+"%"))},getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||ns.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=Jr.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:Jr.getElements.call(this,this.config.selectors.buttons.play),pause:Jr.getElement.call(this,this.config.selectors.buttons.pause),restart:Jr.getElement.call(this,this.config.selectors.buttons.restart),rewind:Jr.getElement.call(this,this.config.selectors.buttons.rewind),fastForward:Jr.getElement.call(this,this.config.selectors.buttons.fastForward),mute:Jr.getElement.call(this,this.config.selectors.buttons.mute),pip:Jr.getElement.call(this,this.config.selectors.buttons.pip),airplay:Jr.getElement.call(this,this.config.selectors.buttons.airplay),settings:Jr.getElement.call(this,this.config.selectors.buttons.settings),captions:Jr.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:Jr.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=Jr.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:Jr.getElement.call(this,this.config.selectors.inputs.seek),volume:Jr.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:Jr.getElement.call(this,this.config.selectors.display.buffer),currentTime:Jr.getElement.call(this,this.config.selectors.display.currentTime),duration:Jr.getElement.call(this,this.config.selectors.display.duration)},Jr.is.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var n=is.getIconUrl.call(this),i=(n.cors?"":n.url)+"#"+this.config.iconPrefix,r=document.createElementNS("http://www.w3.org/2000/svg","svg");Jr.setAttributes(r,Jr.extend(t,{role:"presentation",focusable:"false"}));var s=document.createElementNS("http://www.w3.org/2000/svg","use"),o=i+"-"+e;return"href"in s?s.setAttributeNS("http://www.w3.org/1999/xlink","href",o):s.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),r.appendChild(s),r},createLabel:function(e,t){var n=Zr(e,this.config),i=Object.assign({},t);switch(e){case"pip":n="PIP";break;case"airplay":n="AirPlay"}return"class"in i?i.class+=" "+this.config.classNames.hidden:i.class=this.config.classNames.hidden,Jr.createElement("span",i,n)},createBadge:function(e){if(Jr.is.empty(e))return null;var t=Jr.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(Jr.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var n=Jr.createElement("button"),i=Object.assign({},t),r=Jr.toCamelCase(e),s=!1,o=void 0,a=void 0,l=void 0,c=void 0;switch("type"in i||(i.type="button"),"class"in i?i.class.includes(this.config.classNames.control)&&(i.class+=" "+this.config.classNames.control):i.class=this.config.classNames.control,e){case"play":s=!0,o="play",l="pause",a="play",c="pause";break;case"mute":s=!0,o="mute",l="unmute",a="volume",c="muted";break;case"captions":s=!0,o="enableCaptions",l="disableCaptions",a="captions-off",c="captions-on";break;case"fullscreen":s=!0,o="enterFullscreen",l="exitFullscreen",a="enter-fullscreen",c="exit-fullscreen";break;case"play-large":i.class+=" "+this.config.classNames.control+"--overlaid",r="play",o="play",a="play";break;default:o=r,a=e}return s?(n.appendChild(is.createIcon.call(this,c,{class:"icon--pressed"})),n.appendChild(is.createIcon.call(this,a,{class:"icon--not-pressed"})),n.appendChild(is.createLabel.call(this,l,{class:"label--pressed"})),n.appendChild(is.createLabel.call(this,o,{class:"label--not-pressed"})),i["aria-pressed"]=!1):(n.appendChild(is.createIcon.call(this,a)),n.appendChild(is.createLabel.call(this,o))),Jr.extend(i,Jr.getAttributesFromSelector(this.config.selectors.buttons[r],i)),Jr.setAttributes(n,i),"play"===r?(Jr.is.array(this.elements.buttons[r])||(this.elements.buttons[r]=[]),this.elements.buttons[r].push(n)):this.elements.buttons[r]=n,n},createRange:function(e,t){var n=Jr.createElement("label",{for:t.id,id:t.id+"-label",class:this.config.classNames.hidden},Zr(e,this.config)),i=Jr.createElement("input",Jr.extend(Jr.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-labelledby":t.id+"-label","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=i,is.updateRangeFill.call(this,i),{label:n,input:i}},createProgress:function(e,t){var n=Jr.createElement("progress",Jr.extend(Jr.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){n.appendChild(Jr.createElement("span",null,"0"));var i="";switch(e){case"played":i=Zr("played",this.config);break;case"buffer":i=Zr("buffered",this.config)}n.textContent="% "+i.toLowerCase()}return this.elements.display[e]=n,n},createTime:function(e){var t=Jr.getAttributesFromSelector(this.config.selectors.display[e]),n=Jr.createElement("div",Jr.extend(t,{class:"plyr__time "+t.class,"aria-label":Zr(e,this.config)}),"00:00");return this.elements.display[e]=n,n},createMenuItem:function(e,t,n,i){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,s=arguments.length>5&&void 0!==arguments[5]&&arguments[5],o=Jr.createElement("li"),a=Jr.createElement("label",{class:this.config.classNames.control}),l=Jr.createElement("input",Jr.extend(Jr.getAttributesFromSelector(this.config.selectors.inputs[n]),{type:"radio",name:"plyr-"+n,value:e,checked:s,class:"plyr__sr-only"})),c=Jr.createElement("span",{hidden:""});a.appendChild(l),a.appendChild(c),a.insertAdjacentHTML("beforeend",i),Jr.is.element(r)&&a.appendChild(r),o.appendChild(a),t.appendChild(o)},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&Jr.is.element(this.elements.inputs.seek)&&Jr.is.element(this.elements.display.seekTooltip)&&0!==this.duration){var n=0,i=this.elements.inputs.seek.getBoundingClientRect(),r=this.config.classNames.tooltip+"--visible",s=function(e){Jr.toggleClass(t.elements.display.seekTooltip,r,e)};if(this.touch)s(!1);else{if(Jr.is.event(e))n=100/i.width*(e.pageX-i.left);else{if(!Jr.hasClass(this.elements.display.seekTooltip,r))return;n=parseFloat(this.elements.display.seekTooltip.style.left,10)}n<0?n=0:n>100&&(n=100),ts.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*n),this.elements.display.seekTooltip.style.left=n+"%",Jr.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s("mouseenter"===e.type)}}},toggleTab:function(e,t){Jr.toggleHidden(this.elements.settings.tabs[e],!t)},setQualityMenu:function(e){var t=this;if(Jr.is.element(this.elements.settings.panes.quality)){var n=this.elements.settings.panes.quality.querySelector("ul");Jr.is.array(e)&&(this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}));var i=!Jr.is.empty(this.options.quality)&&this.options.quality.length>1;if(is.toggleTab.call(this,"quality",i),is.checkMenu.call(this),i){Jr.emptyElement(n);this.options.quality.sort(function(e,n){var i=t.config.quality.options;return i.indexOf(e)>i.indexOf(n)?1:-1}).forEach(function(e){var i=is.getLabel.call(t,"quality",e);is.createMenuItem.call(t,e,n,"quality",i,function(e){var n="";switch(e){case 2160:n="4K";break;case 1440:case 1080:case 720:n="HD";break;case 576:case 480:n="SD"}return n.length?is.createBadge.call(t,n):null}(e))}),is.updateSetting.call(this,"quality",n)}}},getLabel:function(e,t){switch(e){case"speed":return 1===t?Zr("normal",this.config):t+"×";case"quality":return Jr.is.number(t)?t+"p":Jr.toTitleCase(t);case"captions":return rs.getLabel.call(this);default:return null}},updateSetting:function(e,t,n){var i=this.elements.settings.panes[e],r=null,s=t;switch(e){case"captions":r=this.captions.active?this.options.captions.length>2||!this.options.captions.some(function(e){return"enabled"===e})?this.captions.language:"enabled":"";break;default:if(r=Jr.is.empty(n)?this[e]:n,Jr.is.empty(r)&&(r=this.config[e].default),!Jr.is.empty(this.options[e])&&!this.options[e].includes(r))return void this.debug.warn("Unsupported value of '"+r+"' for "+e);if(!this.config[e].options.includes(r))return void this.debug.warn("Disabled value of '"+r+"' for "+e)}if(Jr.is.element(s)||(s=i&&i.querySelector("ul")),Jr.is.element(s)){this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=is.getLabel.call(this,e,r);var o=s&&s.querySelector('input[value="'+r+'"]');Jr.is.element(o)&&(o.checked=!0)}},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),n=rs.getTracks.call(this).length;if(is.toggleTab.call(this,"captions",n),Jr.emptyElement(t),is.checkMenu.call(this),n){var i=rs.getTracks.call(this).map(function(t){return{language:Jr.is.empty(t.language)?"enabled":t.language,label:rs.getLabel.call(e,t)}});i.unshift({language:"",label:Zr("disabled",this.config)}),i.forEach(function(n){is.createMenuItem.call(e,n.language,t,"language",n.label,"enabled"!==n.language?is.createBadge.call(e,n.language.toUpperCase()):null,n.language.toLowerCase()===e.captions.language.toLowerCase())}),this.options.captions=i.map(function(e){return e.language}),is.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;if(this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&Jr.is.element(this.elements.settings.panes.speed)){Jr.is.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var n=!Jr.is.empty(this.options.speed)&&this.options.speed.length>1;if(is.toggleTab.call(this,"speed",n),is.checkMenu.call(this),n){var i=this.elements.settings.panes.speed.querySelector("ul");Jr.emptyElement(i),this.options.speed.forEach(function(e){var n=is.getLabel.call(t,"speed",e);is.createMenuItem.call(t,e,i,"speed",n)}),is.updateSetting.call(this,"speed",i)}}},checkMenu:function(){var e=this.elements.settings.tabs,t=!Jr.is.empty(e)&&Object.values(e).some(function(e){return!e.hidden});Jr.toggleHidden(this.elements.settings.menu,!t)},toggleMenu:function(e){var t=this.elements.settings.form,n=this.elements.buttons.settings;if(Jr.is.element(t)&&Jr.is.element(n)){var i=Jr.is.boolean(e)?e:Jr.is.element(t)&&t.hasAttribute("hidden");if(Jr.is.event(e)){var r=Jr.is.element(t)&&t.contains(e.target),s=e.target===this.elements.buttons.settings;if(r||!r&&!s&&i)return;s&&e.stopPropagation()}Jr.is.element(n)&&n.setAttribute("aria-expanded",i),Jr.is.element(t)&&(Jr.toggleHidden(t,!i),Jr.toggleClass(this.elements.container,this.config.classNames.menu.open,i),i?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))}},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var n=t.scrollWidth,i=t.scrollHeight;return Jr.removeElement(t),{width:n,height:i}},showTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=this.elements.settings.menu,n=document.getElementById(e);if(Jr.is.element(n)&&"tabpanel"===n.getAttribute("role")){var i=t.querySelector('[role="tabpanel"]:not([hidden])'),r=i.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+i.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),$r.transitions&&!$r.reducedMotion){r.style.width=i.scrollWidth+"px",r.style.height=i.scrollHeight+"px";var s=is.getTabSize.call(this,n);Jr.on(r,Jr.transitionEndEvent,function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",Jr.off(r,Jr.transitionEndEvent,e))}),r.style.width=s.width+"px",r.style.height=s.height+"px"}Jr.toggleHidden(i,!0),i.setAttribute("tabindex",-1),Jr.toggleHidden(n,!1);var o=Jr.getElements.call(this,'[aria-controls="'+e+'"]');Array.from(o).forEach(function(e){e.setAttribute("aria-expanded",!0)}),n.removeAttribute("tabindex"),n.querySelectorAll("button:not(:disabled), input:not(:disabled), [tabindex]")[0].focus()}},create:function(e){var t=this;if(Jr.is.empty(this.config.controls))return null;var n=Jr.createElement("div",Jr.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&n.appendChild(is.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&n.appendChild(is.createButton.call(this,"rewind")),this.config.controls.includes("play")&&n.appendChild(is.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&n.appendChild(is.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var i=Jr.createElement("div",Jr.getAttributesFromSelector(this.config.selectors.progress)),r=is.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(i.appendChild(r.label),i.appendChild(r.input),i.appendChild(is.createProgress.call(this,"buffer")),this.config.tooltips.seek){var s=Jr.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");i.appendChild(s),this.elements.display.seekTooltip=s}this.elements.progress=i,n.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&n.appendChild(is.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&n.appendChild(is.createTime.call(this,"duration")),this.config.controls.includes("mute")&&n.appendChild(is.createButton.call(this,"mute")),this.config.controls.includes("volume")){var o=Jr.createElement("div",{class:"plyr__volume"}),a={max:1,step:.05,value:this.config.volume},l=is.createRange.call(this,"volume",Jr.extend(a,{id:"plyr-volume-"+e.id}));o.appendChild(l.label),o.appendChild(l.input),this.elements.volume=o,n.appendChild(o)}if(this.config.controls.includes("captions")&&n.appendChild(is.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!Jr.is.empty(this.config.settings)){var c=Jr.createElement("div",{class:"plyr__menu",hidden:""});c.appendChild(is.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var u=Jr.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,hidden:"","aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),d=Jr.createElement("div"),f=Jr.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),h=Jr.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(n){var i=Jr.createElement("li",{role:"tab",hidden:""}),r=Jr.createElement("button",Jr.extend(Jr.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+n+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+n,"aria-expanded":!1}),Zr(n,t.config)),s=Jr.createElement("span",{class:t.config.classNames.menu.value});s.innerHTML=e[n],r.appendChild(s),i.appendChild(r),h.appendChild(i),t.elements.settings.tabs[n]=i}),f.appendChild(h),d.appendChild(f),this.config.settings.forEach(function(n){var i=Jr.createElement("div",{id:"plyr-settings-"+e.id+"-"+n,hidden:"","aria-labelled-by":"plyr-settings-"+e.id+"-"+n+"-tab",role:"tabpanel",tabindex:-1}),r=Jr.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},Zr(n,t.config));i.appendChild(r);var s=Jr.createElement("ul");i.appendChild(s),d.appendChild(i),t.elements.settings.panes[n]=i}),u.appendChild(d),c.appendChild(u),n.appendChild(c),this.elements.settings.form=u,this.elements.settings.menu=c}return this.config.controls.includes("pip")&&$r.pip&&n.appendChild(is.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&$r.airplay&&n.appendChild(is.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&n.appendChild(is.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(is.createButton.call(this,"play-large")),this.elements.controls=n,this.isHTML5&&is.setQualityMenu.call(this,Xr.getQualityOptions.call(this)),is.setSpeedMenu.call(this),n},inject:function(){var e=this;if(this.config.loadSprite){var t=is.getIconUrl.call(this);t.cors&&Jr.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var n=null;this.elements.controls=null;var i={id:this.id,seektime:this.config.seekTime,title:this.config.title},r=!0;Jr.is.string(this.config.controls)||Jr.is.element(this.config.controls)?n=this.config.controls:Jr.is.function(this.config.controls)?n=this.config.controls.call(this,i):(n=is.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:rs.getLabel.call(this)}),r=!1);var s=function(e){var t=e;return Object.entries(i).forEach(function(e){var n=Qr(e,2),i=n[0],r=n[1];t=Jr.replaceAll(t,"{"+i+"}",r)}),t};r&&(Jr.is.string(this.config.controls)?n=s(n):Jr.is.element(n)&&(n.innerHTML=s(n.innerHTML)));var o=void 0;if(Jr.is.string(this.config.selectors.controls.container)&&(o=document.querySelector(this.config.selectors.controls.container)),Jr.is.element(o)||(o=this.elements.container),Jr.is.element(n)?o.appendChild(n):n&&o.insertAdjacentHTML("beforeend",n),Jr.is.element(this.elements.controls)||is.findElements.call(this),window.navigator.userAgent.includes("Edge")&&Jr.repaint(o),this.config.tooltips.controls){var a=Jr.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(a).forEach(function(t){Jr.toggleClass(t,e.config.classNames.hidden,!1),Jr.toggleClass(t,e.config.classNames.tooltip,!0),t.setAttribute("role","tooltip")})}}},rs={setup:function(){if(this.supported.ui){var e=this.storage.get("language");if(Jr.is.empty(e)||(this.captions.language=e),Jr.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()),!Jr.is.boolean(this.captions.active)){var t=this.storage.get("captions");Jr.is.boolean(t)?this.captions.active=t:this.captions.active=this.config.captions.active}if(!this.isVideo||this.isYouTube||this.isHTML5&&!$r.textTracks)Jr.is.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&is.setCaptionsMenu.call(this);else{Jr.is.element(this.elements.captions)||(this.elements.captions=Jr.createElement("div",Jr.getAttributesFromSelector(this.config.selectors.captions)),Jr.insertAfter(this.elements.captions,this.elements.wrapper)),Jr.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!Jr.is.empty(rs.getTracks.call(this)));var n=rs.getTracks.call(this);if(!Jr.is.empty(n)){if(Jr.getBrowser().isIE&&window.URL){var i=this.media.querySelectorAll("track");Array.from(i).forEach(function(e){var t=e.getAttribute("src"),n=Jr.parseUrl(t);n.hostname!==window.location.href.hostname&&["http:","https:"].includes(n.protocol)&&Jr.fetch(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){Jr.removeElement(e)})})}rs.setLanguage.call(this),rs.show.call(this),Jr.is.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&is.setCaptionsMenu.call(this)}}}},setLanguage:function(){var e=this;if(this.isHTML5&&this.isVideo){rs.getTracks.call(this).forEach(function(t){Jr.on(t,"cuechange",function(t){return rs.setCue.call(e,t)}),t.mode="hidden"});var t=rs.getCurrentTrack.call(this);Jr.is.track(t)&&Array.from(t.activeCues||[]).length&&rs.setCue.call(this,t)}else this.isVimeo&&this.captions.active&&this.embed.enableTextTrack(this.language)},getTracks:function(){return Jr.is.nullOrUndefined(this.media)?[]:Array.from(this.media.textTracks||[]).filter(function(e){return["captions","subtitles"].includes(e.kind)})},getCurrentTrack:function(){var e=this,t=rs.getTracks.call(this);if(!t.length)return null;var n=t.find(function(t){return t.language.toLowerCase()===e.language});(n||(n=Jr.getElement.call(this,"track[default]")),n)||(n=Qr(t,1)[0]);return n},getLabel:function(e){var t=e;return!Jr.is.track(t)&&$r.textTracks&&this.captions.active&&(t=rs.getCurrentTrack.call(this)),Jr.is.track(t)?Jr.is.empty(t.label)?Jr.is.empty(t.language)?Zr("enabled",this.config):e.language.toUpperCase():t.label:Zr("disabled",this.config)},setCue:function(e){var t=Jr.is.event(e)?e.target:e,n=t.activeCues,i=n.length&&n[0];t===rs.getCurrentTrack.call(this)&&(Jr.is.cue(i)?rs.setText.call(this,i.getCueAsHTML()):rs.setText.call(this,null),Jr.dispatchEvent.call(this,this.media,"cuechange"))},setText:function(e){if(this.supported.ui)if(Jr.is.element(this.elements.captions)){var t=Jr.createElement("span");Jr.emptyElement(this.elements.captions);var n=Jr.is.nullOrUndefined(e)?"":e;Jr.is.string(n)?t.textContent=n.trim():t.appendChild(n),this.elements.captions.appendChild(t)}else this.debug.warn("No captions element to render to")},show:function(){var e=this.storage.get("captions");Jr.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(Jr.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),Jr.toggleState(this.elements.buttons.captions,!0))}},ss=function(){},os=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];Gr(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return Yr(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):ss}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):ss}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):ss}}]),e}(),as={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.3.6/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240,"default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:(navigator.language||navigator.userLanguage).split("-")[0]},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad"},urls:{vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet",poster:"https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",ads:"plyr__ads",control:"plyr__control",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",error:"plyr--has-error",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:""}},ls=Jr.getBrowser();function cs(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;Jr.is.element(e)&&Jr.toggleState(e,this.active),Jr.dispatchEvent(this.target,this.active?"enterfullscreen":"exitfullscreen",!0),ls.isIos||Jr.trapFocus.call(this.player,this.target,this.active)}}function us(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];e?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=e?"hidden":"",Jr.toggleClass(this.target,this.player.config.classNames.fullscreen.fallback,e),cs.call(this)}var ds=function(){function e(t){var n=this;Gr(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},Jr.on(document,"ms"===this.prefix?"MSFullscreenChange":this.prefix+"fullscreenchange",function(){cs.call(n)}),Jr.on(this.player.elements.container,"dblclick",function(e){Jr.is.element(n.player.elements.controls)&&n.player.elements.controls.contains(e.target)||n.toggle()}),this.update()}return Yr(e,[{key:"update",value:function(){this.enabled?this.player.debug.log((e.native?"Native":"Fallback")+" fullscreen enabled"):this.player.debug.log("Fullscreen not supported and fallback disabled"),Jr.toggleClass(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(ls.isIos&&this.player.config.fullscreen.iosNative?this.player.playing&&this.target.webkitEnterFullscreen():e.native?this.prefix?Jr.is.empty(this.prefix)||this.target[this.prefix+"Request"+this.property]():this.target.requestFullscreen():us.call(this,!0))}},{key:"exit",value:function(){if(this.enabled)if(ls.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(e.native)if(this.prefix){if(!Jr.is.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document[""+this.prefix+t+this.property]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document);else us.call(this,!1)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(e.native?(this.prefix?document[""+this.prefix+this.property+"Element"]:document.fullscreenElement)===this.target:Jr.hasClass(this.target,this.player.config.classNames.fullscreen.fallback))}},{key:"target",get:function(){return ls.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(Jr.is.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!Jr.is.function(document[t+"ExitFullscreen"])&&!Jr.is.function(document[t+"CancelFullScreen"]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}(),fs=Jr.getBrowser(),hs=function(){function e(t){Gr(this,e),this.player=t,this.lastKey=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.firstTouch=this.firstTouch.bind(this)}return Yr(e,[{key:"handleKey",value:function(e){var t=this,n=e.keyCode?e.keyCode:e.which,i="keydown"===e.type,r=i&&n===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&Jr.is.number(n)){if(i){var s=Jr.getFocusElement();if(Jr.is.element(s)&&Jr.matches(s,this.player.config.selectors.editable))return;switch([48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67,73,76,79].includes(n)&&(e.preventDefault(),e.stopPropagation()),n){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:r||(t.player.currentTime=t.player.duration/10*(n-48));break;case 32:case 75:r||this.player.togglePlay();break;case 38:this.player.increaseVolume(.1);break;case 40:this.player.decreaseVolume(.1);break;case 77:r||(this.player.muted=!this.player.muted);break;case 39:this.player.forward();break;case 37:this.player.rewind();break;case 70:this.player.fullscreen.toggle();break;case 67:r||this.player.toggleCaptions();break;case 76:this.player.loop=!this.player.loop}!this.player.fullscreen.enabled&&this.player.fullscreen.active&&27===n&&this.player.fullscreen.toggle(),this.lastKey=n}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){is.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){this.player.touch=!0,Jr.toggleClass(this.player.elements.container,this.player.config.classNames.isTouch,!0),Jr.off(document.body,"touchstart",this.firstTouch)}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.player.config.keyboard.global&&Jr.toggleListener(window,"keydown keyup",this.handleKey,e,!1),Jr.toggleListener(document.body,"click",this.toggleMenu,e),Jr.on(document.body,"touchstart",this.firstTouch)}},{key:"container",value:function(){var e=this;!this.player.config.keyboard.global&&this.player.config.keyboard.focused&&Jr.on(this.player.elements.container,"keydown keyup",this.handleKey,!1),Jr.on(this.player.elements.container,"focusout",function(t){Jr.toggleClass(t.target,e.player.config.classNames.tabFocus,!1)}),Jr.on(this.player.elements.container,"keydown",function(t){9===t.keyCode&&setTimeout(function(){Jr.toggleClass(Jr.getFocusElement(),e.player.config.classNames.tabFocus,!0)},0)}),this.player.config.hideControls&&Jr.on(this.player.elements.container,"mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen",function(t){e.player.toggleControls(t)})}},{key:"media",value:function(){var e=this;if(Jr.on(this.player.media,"timeupdate seeking",function(t){return ts.timeUpdate.call(e.player,t)}),Jr.on(this.player.media,"durationchange loadeddata loadedmetadata",function(t){return ts.durationUpdate.call(e.player,t)}),Jr.on(this.player.media,"loadeddata",function(){Jr.toggleHidden(e.player.elements.volume,!e.player.hasAudio),Jr.toggleHidden(e.player.elements.buttons.mute,!e.player.hasAudio)}),Jr.on(this.player.media,"ended",function(){e.player.isHTML5&&e.player.isVideo&&e.player.config.resetOnEnd&&e.player.restart()}),Jr.on(this.player.media,"progress playing",function(t){return ts.updateProgress.call(e.player,t)}),Jr.on(this.player.media,"volumechange",function(t){return ts.updateVolume.call(e.player,t)}),Jr.on(this.player.media,"playing play pause ended emptied timeupdate",function(t){return ts.checkPlaying.call(e.player,t)}),Jr.on(this.player.media,"waiting canplay seeked playing",function(t){return ts.checkLoading.call(e.player,t)}),Jr.on(this.player.media,"playing",function(){e.player.ads&&e.player.ads.enabled&&!e.player.ads.initialized&&e.player.ads.managerPromise.then(function(){return e.player.ads.play()}).catch(function(){return e.player.play()})}),this.player.supported.ui&&this.player.config.clickToPlay&&!this.player.isAudio){var t=Jr.getElement.call(this.player,"."+this.player.config.classNames.video);if(!Jr.is.element(t))return;Jr.on(t,"click",function(){e.player.config.hideControls&&e.player.touch&&!e.player.paused||(e.player.paused?e.player.play():e.player.ended?(e.player.restart(),e.player.play()):e.player.pause())})}this.player.supported.ui&&this.player.config.disableContextMenu&&Jr.on(this.player.elements.wrapper,"contextmenu",function(e){e.preventDefault()},!1),Jr.on(this.player.media,"volumechange",function(){e.player.storage.set({volume:e.player.volume,muted:e.player.muted})}),Jr.on(this.player.media,"ratechange",function(){is.updateSetting.call(e.player,"speed"),e.player.storage.set({speed:e.player.speed})}),Jr.on(this.player.media,"qualityrequested",function(t){e.player.storage.set({quality:t.detail.quality})}),Jr.on(this.player.media,"qualitychange",function(t){is.updateSetting.call(e.player,"quality",null,t.detail.quality)}),Jr.on(this.player.media,"languagechange",function(){is.updateSetting.call(e.player,"captions"),e.player.storage.set({language:e.player.language})}),Jr.on(this.player.media,"captionsenabled captionsdisabled",function(){is.updateSetting.call(e.player,"captions"),e.player.storage.set({captions:e.player.captions.active})}),Jr.on(this.player.media,this.player.config.events.concat(["keyup","keydown"]).join(" "),function(t){var n={};"error"===t.type&&(n=e.player.media.error),Jr.dispatchEvent.call(e.player,e.player.elements.container,t.type,!0,n)})}},{key:"controls",value:function(){var e=this,t=fs.isIE?"change":"input",n=function(t,n,i){var r=e.player.config.listeners[i],s=!0;Jr.is.function(r)&&(s=r.call(e.player,t)),s&&Jr.is.function(n)&&n.call(e.player,t)},i=function(t,i,r,s){var o=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],a=e.player.config.listeners[s],l=Jr.is.function(a);Jr.on(t,i,function(e){return n(e,r,s)},o&&!l)};i(this.player.elements.buttons.play,"click",this.player.togglePlay,"play"),i(this.player.elements.buttons.restart,"click",this.player.restart,"restart"),i(this.player.elements.buttons.rewind,"click",this.player.rewind,"rewind"),i(this.player.elements.buttons.fastForward,"click",this.player.forward,"fastForward"),i(this.player.elements.buttons.mute,"click",function(){e.player.muted=!e.player.muted},"mute"),i(this.player.elements.buttons.captions,"click",this.player.toggleCaptions),i(this.player.elements.buttons.fullscreen,"click",function(){e.player.fullscreen.toggle()},"fullscreen"),i(this.player.elements.buttons.pip,"click",function(){e.player.pip="toggle"},"pip"),i(this.player.elements.buttons.airplay,"click",this.player.airplay,"airplay"),i(this.player.elements.buttons.settings,"click",function(t){is.toggleMenu.call(e.player,t)}),i(this.player.elements.settings.form,"click",function(t){t.stopPropagation();var i=function(){var t="plyr-settings-"+e.player.id+"-home";is.showTab.call(e.player,t)};if(Jr.matches(t.target,e.player.config.selectors.inputs.language))n(t,function(){e.player.language=t.target.value,i()},"language");else if(Jr.matches(t.target,e.player.config.selectors.inputs.quality))n(t,function(){e.player.quality=t.target.value,i()},"quality");else if(Jr.matches(t.target,e.player.config.selectors.inputs.speed))n(t,function(){e.player.speed=parseFloat(t.target.value),i()},"speed");else{var r=t.target;is.showTab.call(e.player,r.getAttribute("aria-controls"))}}),i(this.player.elements.inputs.seek,t,function(t){e.player.currentTime=t.target.value/t.target.max*e.player.duration},"seek"),this.player.config.toggleInvert&&!Jr.is.element(this.player.elements.display.duration)&&i(this.player.elements.display.currentTime,"click",function(){0!==e.player.currentTime&&(e.player.config.invertTime=!e.player.config.invertTime,ts.timeUpdate.call(e.player))}),i(this.player.elements.inputs.volume,t,function(t){e.player.volume=t.target.value},"volume"),fs.isWebkit&&i(Jr.getElements.call(this.player,'input[type="range"]'),"input",function(t){is.updateRangeFill.call(e.player,t.target)}),i(this.player.elements.progress,"mouseenter mouseleave mousemove",function(t){return is.updateSeekTooltip.call(e.player,t)}),this.player.config.hideControls&&(i(this.player.elements.controls,"mouseenter mouseleave",function(t){e.player.elements.controls.hover=!e.player.touch&&"mouseenter"===t.type}),i(this.player.elements.controls,"mousedown mouseup touchstart touchend touchcancel",function(t){e.player.elements.controls.pressed=["mousedown","touchstart"].includes(t.type)}),i(this.player.elements.controls,"focusin focusout",function(t){e.player.toggleControls(t)})),i(this.player.elements.inputs.volume,"wheel",function(t){var n=t.webkitDirectionInvertedFromDevice,i=0;(t.deltaY<0||t.deltaX>0)&&(n?(e.player.decreaseVolume(.02),i=-1):(e.player.increaseVolume(.02),i=1)),(t.deltaY>0||t.deltaX<0)&&(n?(e.player.increaseVolume(.02),i=1):(e.player.decreaseVolume(.02),i=-1)),(1===i&&e.player.media.volume<1||-1===i&&e.player.media.volume>0)&&t.preventDefault()},"volume",!1)}},{key:"clear",value:function(){this.global(!1)}}]),e}(),ps={setup:function(){var e=this;Jr.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),ps.setAspectRatio.call(this),Jr.is.object(window.Vimeo)?ps.ready.call(this):Jr.loadScript(this.config.urls.vimeo.sdk).then(function(){ps.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},setAspectRatio:function(e){var t=Jr.is.string(e)?e.split(":"):this.config.ratio.split(":"),n=100/t[0]*t[1];if(this.elements.wrapper.style.paddingBottom=n+"%",this.supported.ui){var i=(240-n)/4.8;this.media.style.transform="translateY(-"+i+"%)"}},ready:function(){var e=this,t=this,n={loop:t.config.loop.active,autoplay:t.autoplay,byline:!1,portrait:!1,title:!1,speed:!0,transparent:0,gesture:"media",playsinline:!this.config.fullscreen.iosNative},i=Jr.buildUrlParams(n),r=t.media.getAttribute("src");Jr.is.empty(r)&&(r=t.media.getAttribute(t.config.attributes.embed.id));var s=Jr.parseVimeoId(r),o=Jr.createElement("iframe"),a=Jr.format(t.config.urls.vimeo.iframe,s,i);o.setAttribute("src",a),o.setAttribute("allowfullscreen",""),o.setAttribute("allowtransparency",""),o.setAttribute("allow","autoplay");var l=Jr.createElement("div",{class:t.config.classNames.embedContainer});l.appendChild(o),t.media=Jr.replaceElement(l,t.media),Jr.fetch(Jr.format(t.config.urls.vimeo.api,s),"json").then(function(e){if(!Jr.is.empty(e)){var n=new URL(e[0].thumbnail_large);n.pathname=n.pathname.split("_")[0]+".jpg",t.media.setAttribute("poster",n.href),ts.setPoster.call(t)}}),t.embed=new window.Vimeo.Player(o,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){t.embed.play().then(function(){t.media.paused=!1})},t.media.pause=function(){t.embed.pause().then(function(){t.media.paused=!0})},t.media.stop=function(){t.pause(),t.currentTime=0};var c=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return c},set:function(e){var n=t.media.paused;t.media.seeking=!0,Jr.dispatchEvent.call(t,t.media,"seeking"),t.embed.setCurrentTime(e).catch(function(){}),n&&t.pause()}});var u=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return u},set:function(e){t.embed.setPlaybackRate(e).then(function(){u=e,Jr.dispatchEvent.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&is.setSpeedMenu.call(t,[])})}});var d=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return d},set:function(e){t.embed.setVolume(e).then(function(){d=e,Jr.dispatchEvent.call(t,t.media,"volumechange")})}});var f=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return f},set:function(e){var n=!!Jr.is.boolean(e)&&e;t.embed.setVolume(n?0:t.config.volume).then(function(){f=n,Jr.dispatchEvent.call(t,t.media,"volumechange")})}});var h=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return h},set:function(e){var n=Jr.is.boolean(e)?e:t.config.loop.active;t.embed.setLoop(n).then(function(){h=n})}});var p=void 0;t.embed.getVideoUrl().then(function(e){p=e}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return p}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(t){var n=Jr.getAspectRatio(t[0],t[1]);ps.setAspectRatio.call(e,n)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(n){t.config.title=n,ts.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){c=e,Jr.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,Jr.dispatchEvent.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,rs.setup.call(t)}),t.embed.on("cuechange",function(e){var n=null;e.cues.length&&(n=Jr.stripHTML(e.cues[0].text)),rs.setText.call(t,n)}),t.embed.on("loaded",function(){Jr.is.element(t.embed.element)&&t.supported.ui&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){t.media.paused&&Jr.dispatchEvent.call(t,t.media,"play"),t.media.paused=!1,Jr.dispatchEvent.call(t,t.media,"playing")}),t.embed.on("pause",function(){t.media.paused=!0,Jr.dispatchEvent.call(t,t.media,"pause")}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,c=e.seconds,Jr.dispatchEvent.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,Jr.dispatchEvent.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&Jr.dispatchEvent.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,Jr.dispatchEvent.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,Jr.dispatchEvent.call(t,t.media,"seeked"),Jr.dispatchEvent.call(t,t.media,"play")}),t.embed.on("ended",function(){t.media.paused=!0,Jr.dispatchEvent.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,Jr.dispatchEvent.call(t,t.media,"error")}),setTimeout(function(){return ts.build.call(t)},0)}};function gs(e){switch(e){case"hd2160":return 2160;case 2160:return"hd2160";case"hd1440":return 1440;case 1440:return"hd1440";case"hd1080":return 1080;case 1080:return"hd1080";case"hd720":return 720;case 720:return"hd720";case"large":return 480;case 480:return"large";case"medium":return 360;case 360:return"medium";case"small":return 240;case 240:return"small";default:return"default"}}var ms={setup:function(){var e=this;Jr.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),ms.setAspectRatio.call(this),Jr.is.object(window.YT)&&Jr.is.function(window.YT.Player)?ms.ready.call(this):(Jr.loadScript(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){ms.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(Jr.is.function(this.embed.getVideoData)){var n=this.embed.getVideoData().title;if(Jr.is.empty(n))return this.config.title=n,void ts.setTitle.call(this)}var i=this.config.keys.google;if(Jr.is.string(i)&&!Jr.is.empty(i)){var r=Jr.format(this.config.urls.youtube.api,e,i);Jr.fetch(r).then(function(e){Jr.is.object(e)&&(t.config.title=e.items[0].snippet.title,ts.setTitle.call(t))}).catch(function(){})}},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(){var e=this,t=e.media.getAttribute("id");if(Jr.is.empty(t)||!t.startsWith("youtube-")){var n=e.media.getAttribute("src");Jr.is.empty(n)&&(n=e.media.getAttribute(this.config.attributes.embed.id));var i=Jr.parseYouTubeId(n),r=Jr.generateId(e.provider),s=Jr.createElement("div",{id:r});e.media=Jr.replaceElement(s,e.media),e.media.setAttribute("poster",Jr.format(e.config.urls.youtube.poster,i)),e.embed=new window.YT.Player(r,{videoId:i,playerVars:{autoplay:e.config.autoplay?1:0,controls:e.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,widget_referrer:window?window.location.href:null,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language},events:{onError:function(t){if(!Jr.is.object(e.media.error)){var n={code:t.data};switch(t.data){case 2:n.message="The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.";break;case 5:n.message="The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.";break;case 100:n.message="The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.";break;case 101:case 150:n.message="The owner of the requested video does not allow it to be played in embedded players.";break;default:n.message="An unknown error occured"}e.media.error=n,Jr.dispatchEvent.call(e,e.media,"error")}},onPlaybackQualityChange:function(){Jr.dispatchEvent.call(e,e.media,"qualitychange",!1,{quality:e.media.quality})},onPlaybackRateChange:function(t){var n=t.target;e.media.playbackRate=n.getPlaybackRate(),Jr.dispatchEvent.call(e,e.media,"ratechange")},onReady:function(t){var n=t.target;ms.getTitle.call(e,i),e.media.play=function(){n.playVideo()},e.media.pause=function(){n.pauseVideo()},e.media.stop=function(){n.stopVideo()},e.media.duration=n.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(n.getCurrentTime())},set:function(t){var i=e.media.paused;e.media.seeking=!0,Jr.dispatchEvent.call(e,e.media,"seeking"),n.seekTo(t),i&&e.pause()}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return n.getPlaybackRate()},set:function(e){n.setPlaybackRate(e)}}),Object.defineProperty(e.media,"quality",{get:function(){return gs(n.getPlaybackQuality())},set:function(t){var i=t;n.setPlaybackQuality(gs(i)),Jr.dispatchEvent.call(e,e.media,"qualityrequested",!1,{quality:i})}});var r=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return r},set:function(t){r=t,n.setVolume(100*r),Jr.dispatchEvent.call(e,e.media,"volumechange")}});var s=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return s},set:function(t){var i=Jr.is.boolean(t)?t:s;s=i,n[i?"mute":"unMute"](),Jr.dispatchEvent.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return n.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=n.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),Jr.dispatchEvent.call(e,e.media,"timeupdate"),Jr.dispatchEvent.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=n.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&Jr.dispatchEvent.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),Jr.dispatchEvent.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return ts.build.call(e)},50)},onStateChange:function(t){var n,i=t.target;switch(clearInterval(e.timers.playing),t.data){case-1:Jr.dispatchEvent.call(e,e.media,"timeupdate"),e.media.buffered=i.getVideoLoadedFraction(),Jr.dispatchEvent.call(e,e.media,"progress");break;case 0:e.media.paused=!0,e.media.loop?(i.stopVideo(),i.playVideo()):Jr.dispatchEvent.call(e,e.media,"ended");break;case 1:e.media.seeking&&Jr.dispatchEvent.call(e,e.media,"seeked"),e.media.seeking=!1,e.media.paused&&Jr.dispatchEvent.call(e,e.media,"play"),e.media.paused=!1,Jr.dispatchEvent.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){Jr.dispatchEvent.call(e,e.media,"timeupdate")},50),e.media.duration!==i.getDuration()&&(e.media.duration=i.getDuration(),Jr.dispatchEvent.call(e,e.media,"durationchange")),is.setQualityMenu.call(e,(n=i.getAvailableQualityLevels(),Jr.is.empty(n)?n:Jr.dedupe(n.map(function(e){return gs(e)}))));break;case 2:e.media.paused=!0,Jr.dispatchEvent.call(e,e.media,"pause")}Jr.dispatchEvent.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},ys={setup:function(){if(this.media)if(Jr.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),Jr.toggleClass(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&Jr.toggleClass(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=Jr.createElement("div",{class:this.config.classNames.video}),Jr.wrap(this.media,this.elements.wrapper),this.elements.poster=Jr.createElement("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isEmbed)switch(this.provider){case"youtube":ms.setup.call(this);break;case"vimeo":ps.setup.call(this)}else this.isHTML5&&Xr.extend.call(this);else this.debug.warn("No media element found!")}},vs=function(){function e(t){var n=this;Gr(this,e),this.player=t,this.publisherId=t.config.ads.publisherId,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){n.on("loaded",e),n.on("error",t)}),this.load()}return Yr(e,[{key:"load",value:function(){var e=this;this.enabled&&(Jr.is.object(window.google)&&Jr.is.object(window.google.ima)?this.ready():Jr.loadScript(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=Jr.createElement("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var n=new google.ima.AdsRequest;n.adTagUrl=this.tagUrl,n.linearAdSlotWidth=t.offsetWidth,n.linearAdSlotHeight=t.offsetHeight,n.nonLinearAdSlotWidth=t.offsetWidth,n.nonLinearAdSlotHeight=t.offsetHeight,n.forceNonLinearFullSlot=!1,n.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(n)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=Jr.formatTime(Math.max(e.manager.getRemainingTime(),0)),n=Zr("advertisement",e.player.config)+" - "+t;e.elements.container.setAttribute("data-badge-text",n)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this,n=new google.ima.AdsRenderingSettings;n.restoreCustomPlaybackStateOnAdBreakComplete=!0,n.enablePreloading=!0,this.manager=e.getAdsManager(this.player,n),this.cuePoints=this.manager.getCuePoints(),Jr.is.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var n=t.player.elements.progress;if(Jr.is.element(n)){var i=100/t.player.duration*e,r=Jr.createElement("span",{class:t.player.config.classNames.cues});r.style.left=i.toString()+"%",n.appendChild(r)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}},{key:"onAdEvent",value:function(e){var t=this,n=this.player.elements.container,i=e.getAd(),r=function(e){var n="ads"+e.replace(/_/g,"").toLowerCase();Jr.dispatchEvent.call(t.player,t.player.media,n)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),r(e.type),this.pollCountdown(!0),i.isLinear()||(i.width=n.offsetWidth,i.height=n.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:r(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:r(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:r(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:r(e.type)}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e=this,t=this.player.elements.container,n=void 0;this.player.on("ended",function(){e.loader.contentComplete()}),this.player.on("seeking",function(){return n=e.player.currentTime}),this.player.on("seeked",function(){var t=e.player.currentTime;Jr.is.empty(e.cuePoints)||e.cuePoints.forEach(function(i,r){n<i&&i<t&&(e.manager.discardAdBreak(),e.cuePoints.splice(r,1))})}),window.addEventListener("resize",function(){e.manager&&e.manager.resize(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,n=arguments.length,i=Array(n>1?n-1:0),r=1;r<n;r++)i[r-1]=arguments[r];var s=this.events[e];Jr.is.array(s)&&s.forEach(function(e){Jr.is.function(e)&&e.apply(t,i)})}},{key:"on",value:function(e,t){return Jr.is.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var n=this;this.player.debug.log("Safety timer invoked from: "+t),this.safetyTimer=setTimeout(function(){n.cancel(),n.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){Jr.is.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: "+e),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){return this.player.isVideo&&this.player.config.ads.enabled&&!Jr.is.empty(this.publisherId)}},{key:"tagUrl",get:function(){var e={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"https://go.aniview.com/api/adserver6/vast/?"+Jr.buildUrlParams(e)}}]),e}(),bs={insertElements:function(e,t){var n=this;Jr.is.string(t)?Jr.insertElement(e,this.media,{src:t}):Jr.is.array(t)&&t.forEach(function(t){Jr.insertElement(e,n.media,t)})},change:function(e){var t=this;Jr.is.object(e)&&"sources"in e&&e.sources.length?(Xr.cancelRequests.call(this),this.destroy.call(this,function(){switch(t.options.quality=[],Jr.removeElement(t.media),t.media=null,Jr.is.element(t.elements.container)&&t.elements.container.removeAttribute("class"),t.type=e.type,t.provider=Jr.is.empty(e.sources[0].provider)?Wr.html5:e.sources[0].provider,t.supported=$r.check(t.type,t.provider,t.config.playsinline),t.provider+":"+t.type){case"html5:video":t.media=Jr.createElement("video");break;case"html5:audio":t.media=Jr.createElement("audio");break;case"youtube:video":case"vimeo:video":t.media=Jr.createElement("div",{src:e.sources[0].src})}t.elements.container.appendChild(t.media),Jr.is.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),Jr.is.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),ts.addStyleHook.call(t),t.isHTML5&&bs.insertElements.call(t,"source",e.sources),t.config.title=e.title,ys.setup.call(t),t.isHTML5&&("tracks"in e&&bs.insertElements.call(t,"track",e.tracks),t.media.load()),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&ts.build.call(t),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},ws=function(){function e(t){Gr(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return Yr(e,[{key:"get",value:function(t){if(!e.supported)return null;var n=window.localStorage.getItem(this.key);if(Jr.is.empty(n))return null;var i=JSON.parse(n);return Jr.is.string(t)&&t.length?i[t]:i}},{key:"set",value:function(t){if(e.supported&&this.enabled&&Jr.is.object(t)){var n=this.get();Jr.is.empty(n)&&(n={}),Jr.extend(n,t),window.localStorage.setItem(this.key,JSON.stringify(n))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();return function(){function e(t,n){var i=this;if(Gr(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=$r.touch,this.media=t,Jr.is.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||Jr.is.nodeList(this.media)||Jr.is.array(this.media))&&(this.media=this.media[0]),this.config=Jr.extend({},as,n||{},function(){try{return JSON.parse(i.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,buttons:{},display:{},progress:{},inputs:{},settings:{menu:null,panes:{},tabs:{}},captions:null},this.captions={active:null,currentTrack:null},this.fullscreen={active:!1},this.options={speed:[],quality:[],captions:[]},this.debug=new os(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",$r),!Jr.is.nullOrUndefined(this.media)&&Jr.is.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if($r.check().api){var r=this.media.cloneNode(!0);r.autoplay=!1,this.elements.original=r;var s=this.media.tagName.toLowerCase(),o=null,a=null,l=null;switch(s){case"div":if(o=this.media.querySelector("iframe"),Jr.is.element(o)){if(a=o.getAttribute("src"),this.provider=Jr.getProviderByUrl(a),this.elements.container=this.media,this.media=o,this.elements.container.className="",l=Jr.getUrlParams(a),!Jr.is.empty(l)){var c=["1","true"];c.includes(l.autoplay)&&(this.config.autoplay=!0),c.includes(l.loop)&&(this.config.loop.active=!0),this.isYouTube?this.config.playsinline=c.includes(l.playsinline):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(Jr.is.empty(this.provider)||!Object.keys(Wr).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=zr.video;break;case"video":case"audio":this.type=s,this.provider=Wr.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),this.media.hasAttribute("playsinline")&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=$r.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.listeners=new hs(this),this.storage=new ws(this),this.media.plyr=this,Jr.is.element(this.elements.container)||(this.elements.container=Jr.createElement("div"),Jr.wrap(this.media,this.elements.container)),this.elements.container.setAttribute("tabindex",0),ts.addStyleHook.call(this),ys.setup.call(this),this.config.debug&&Jr.on(this.elements.container,this.config.events.join(" "),function(e){i.debug.log("event: "+e.type)}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&ts.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new ds(this),this.ads=new vs(this),this.config.autoplay&&this.play()):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return Yr(e,[{key:"play",value:function(){return Jr.is.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&Jr.is.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(Jr.is.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):Jr.is.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(Jr.is.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(Jr.is.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(Jr.is.number(e)?e:1)}},{key:"decreaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t-(Jr.is.number(e)?e:1)}},{key:"toggleCaptions",value:function(e){if(this.supported.ui){var t=Jr.is.boolean(e)?e:!this.elements.container.classList.contains(this.config.classNames.captions.active);this.captions.active!==t&&(this.captions.active=t,Jr.toggleState(this.elements.buttons.captions,this.captions.active),Jr.toggleClass(this.elements.container,this.config.classNames.captions.active,this.captions.active),Jr.dispatchEvent.call(this,this.media,this.captions.active?"captionsenabled":"captionsdisabled"))}}},{key:"airplay",value:function(){$r.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){var t=this;if(Jr.is.element(this.elements.controls)&&this.supported.ui&&!this.isAudio){var n=0,i=e,r=!1;if(!Jr.is.boolean(e))if(Jr.is.event(e)){r="enterfullscreen"===e.type;i=["touchstart","touchmove","mouseenter","mousemove","focusin"].includes(e.type),["touchmove","touchend","mousemove"].includes(e.type)&&(n=2e3),this.touch||"focusin"!==e.type||(n=3e3,Jr.toggleClass(this.elements.controls,this.config.classNames.noTransition,!0))}else i=Jr.hasClass(this.elements.container,this.config.classNames.hideControls);if(clearTimeout(this.timers.controls),i||this.paused||this.loading){if(Jr.toggleClass(this.elements.container,this.config.classNames.hideControls,!1)&&Jr.dispatchEvent.call(this,this.media,"controlsshown"),this.paused||this.loading)return;this.touch&&(n=3e3)}i&&!this.playing||(this.timers.controls=setTimeout(function(){Jr.is.element(t.elements.controls)&&((!t.elements.controls.pressed&&!t.elements.controls.hover||r)&&(Jr.hasClass(t.elements.container,t.config.classNames.hideControls)||Jr.toggleClass(t.elements.controls,t.config.classNames.noTransition,!1),Jr.toggleClass(t.elements.container,t.config.classNames.hideControls,t.config.hideControls)&&(Jr.dispatchEvent.call(t,t.media,"controlshidden"),t.config.controls.includes("settings")&&!Jr.is.empty(t.config.settings)&&is.toggleMenu.call(t,!1))))},n))}}},{key:"on",value:function(e,t){Jr.on(this.elements.container,e,t)}},{key:"off",value:function(e,t){Jr.off(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var i=function(){document.body.style.overflow="",t.embed=null,n?(Object.keys(t.elements).length&&(Jr.removeElement(t.elements.buttons.play),Jr.removeElement(t.elements.captions),Jr.removeElement(t.elements.controls),Jr.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),Jr.is.function(e)&&e()):(t.listeners.clear(),Jr.replaceElement(t.elements.original,t.elements.container),Jr.dispatchEvent.call(t,t.elements.original,"destroyed",!0),Jr.is.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};switch(this.stop(),this.provider+":"+this.type){case"html5:video":case"html5:audio":clearTimeout(this.timers.loading),ts.toggleNativeControls.call(this,!0),i();break;case"youtube:video":clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&Jr.is.function(this.embed.destroy)&&this.embed.destroy(),i();break;case"vimeo:video":null!==this.embed&&this.embed.unload().then(i),setTimeout(i,200)}}}},{key:"supports",value:function(e){return $r.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===Wr.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===Wr.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===Wr.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===zr.video)}},{key:"isAudio",get:function(){return Boolean(this.type===zr.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){var t=0;Jr.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t,this.debug.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return Jr.is.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=this.media?Number(this.media.duration):0;return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;Jr.is.string(t)&&(t=Number(t)),Jr.is.number(t)||(t=this.storage.get("volume")),Jr.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!Jr.is.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;Jr.is.boolean(t)||(t=this.storage.get("muted")),Jr.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;Jr.is.number(e)&&(t=e),Jr.is.number(t)||(t=this.storage.get("speed")),Jr.is.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed ("+t+")")},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=null;if(Jr.is.empty(e)||(t=Number(e)),Jr.is.number(t)&&0!==t||(t=this.storage.get("quality")),Jr.is.number(t)||(t=this.config.quality.selected),Jr.is.number(t)||(t=this.config.quality.default),this.options.quality.length){if(!this.options.quality.includes(t)){var n=Jr.closest(this.options.quality,t);this.debug.warn("Unsupported quality option: "+t+", using "+n+" instead"),t=n}this.config.quality.selected=t,this.media.quality=t}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=Jr.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){bs.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){this.isVideo?Jr.is.string(e)&&(this.media.setAttribute("poster",e),ts.setPoster.call(this)):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=Jr.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"language",set:function(e){if(Jr.is.string(e))if(Jr.is.empty(e))this.toggleCaptions(!1);else{var t=e.toLowerCase();this.options.captions.includes(t)?(this.toggleCaptions(!0),"enabled"!==t&&this.language!==t&&(this.captions.language=t,rs.setText.call(this,null),rs.setLanguage.call(this),Jr.dispatchEvent.call(this,this.media,"languagechange"))):this.debug.warn("Unsupported language option: "+t)}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t="picture-in-picture",n="inline";if($r.pip){var i=Jr.is.boolean(e)?e:this.pip===n;this.media.webkitSetPresentationMode(i?t:n)}},get:function(){return $r.pip?this.media.webkitPresentationMode:null}}],[{key:"supported",value:function(e,t,n){return $r.check(e,t,n)}},{key:"loadSprite",value:function(e,t){return Jr.loadSprite(e,t)}},{key:"setup",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=null;return Jr.is.string(t)?i=Array.from(document.querySelectorAll(t)):Jr.is.nodeList(t)?i=Array.from(t):Jr.is.array(t)&&(i=t.filter(function(e){return Jr.is.element(e)})),Jr.is.empty(i)?null:i.map(function(t){return new e(t,n)})}}]),e}()}); +"object"==typeof navigator&&function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";!function(){if("undefined"!=typeof window)try{var e=new window.CustomEvent("test",{cancelable:!0});if(e.preventDefault(),!0!==e.defaultPrevented)throw new Error("Could not prevent default")}catch(e){var t=function(e,t){var n,i;return t=t||{bubbles:!1,cancelable:!1,detail:void 0},(n=document.createEvent("CustomEvent")).initCustomEvent(e,t.bubbles,t.cancelable,t.detail),i=n.preventDefault,n.preventDefault=function(){i.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(e){this.defaultPrevented=!0}},n};t.prototype=window.Event.prototype,window.CustomEvent=t}}();var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e,t){return e(t={exports:{}},t.exports),t.exports}!function(e){var t=function(){try{return!!Symbol.iterator}catch(e){return!1}}(),n=function(e){var n={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return t&&(n[Symbol.iterator]=function(){return n}),n},i=function(e){return encodeURIComponent(e).replace(/%20/g,"+")},r=function(e){return decodeURIComponent(e).replace(/\+/g," ")};"URLSearchParams"in e&&"a=1"===new URLSearchParams("?a=1").toString()||function(){var r=function(e){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var t=typeof e;if("undefined"===t);else if("string"===t)""!==e&&this._fromString(e);else if(e instanceof r){var n=this;e.forEach(function(e,t){n.append(t,e)})}else{if(null===e||"object"!==t)throw new TypeError("Unsupported input's type for URLSearchParams");if("[object Array]"===Object.prototype.toString.call(e))for(var i=0;i<e.length;i++){var a=e[i];if("[object Array]"!==Object.prototype.toString.call(a)&&2===a.length)throw new TypeError("Expected [string, any] as entry at index "+i+" of URLSearchParams's input");this.append(a[0],a[1])}else for(var o in e)e.hasOwnProperty(o)&&this.append(o,e[o])}},a=r.prototype;a.append=function(e,t){e in this._entries?this._entries[e].push(String(t)):this._entries[e]=[String(t)]},a.delete=function(e){delete this._entries[e]},a.get=function(e){return e in this._entries?this._entries[e][0]:null},a.getAll=function(e){return e in this._entries?this._entries[e].slice(0):[]},a.has=function(e){return e in this._entries},a.set=function(e,t){this._entries[e]=[String(t)]},a.forEach=function(e,t){var n;for(var i in this._entries)if(this._entries.hasOwnProperty(i)){n=this._entries[i];for(var r=0;r<n.length;r++)e.call(t,n[r],i,this)}},a.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),n(e)},a.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),n(e)},a.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),n(e)},t&&(a[Symbol.iterator]=a.entries),a.toString=function(){var e=[];return this.forEach(function(t,n){e.push(i(n)+"="+i(t))}),e.join("&")},e.URLSearchParams=r}();var a=URLSearchParams.prototype;"function"!=typeof a.sort&&(a.sort=function(){var e=this,t=[];this.forEach(function(n,i){t.push([i,n]),e._entries||e.delete(i)}),t.sort(function(e,t){return e[0]<t[0]?-1:e[0]>t[0]?1:0}),e._entries&&(e._entries={});for(var n=0;n<t.length;n++)this.append(t[n][0],t[n][1])}),"function"!=typeof a._fromString&&Object.defineProperty(a,"_fromString",{enumerable:!1,configurable:!1,writable:!1,value:function(e){if(this._entries)this._entries={};else{var t=[];this.forEach(function(e,n){t.push(n)});for(var n=0;n<t.length;n++)this.delete(t[n])}var i,a=(e=e.replace(/^\?/,"")).split("&");for(n=0;n<a.length;n++)i=a[n].split("="),this.append(r(i[0]),i.length>1?r(i[1]):"")}})}(void 0!==e?e:"undefined"!=typeof window?window:"undefined"!=typeof self?self:e),function(e){if(function(){try{var e=new URL("b","http://a");return e.pathname="c%20d","http://a/c%20d"===e.href&&e.searchParams}catch(e){return!1}}()||function(){var t=e.URL,n=function(t,n){"string"!=typeof t&&(t=String(t));var i,r=document;if(n&&(void 0===e.location||n!==e.location.href)){(i=(r=document.implementation.createHTMLDocument("")).createElement("base")).href=n,r.head.appendChild(i);try{if(0!==i.href.indexOf(n))throw new Error(i.href)}catch(e){throw new Error("URL unable to set base "+n+" due to "+e)}}var a=r.createElement("a");if(a.href=t,i&&(r.body.appendChild(a),a.href=a.href),":"===a.protocol||!/:/.test(a.href))throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:a});var o=new URLSearchParams(this.search),s=!0,l=!0,c=this;["append","delete","set"].forEach(function(e){var t=o[e];o[e]=function(){t.apply(o,arguments),s&&(l=!1,c.search=o.toString(),l=!0)}}),Object.defineProperty(this,"searchParams",{value:o,enumerable:!0});var u=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==u&&(u=this.search,l&&(s=!1,this.searchParams._fromString(this.search),s=!0))}})},i=n.prototype;["hash","host","hostname","port","protocol"].forEach(function(e){!function(e){Object.defineProperty(i,e,{get:function(){return this._anchorElement[e]},set:function(t){this._anchorElement[e]=t},enumerable:!0})}(e)}),Object.defineProperty(i,"search",{get:function(){return this._anchorElement.search},set:function(e){this._anchorElement.search=e,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(i,{toString:{get:function(){var e=this;return function(){return e.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(e){this._anchorElement.href=e,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(e){this._anchorElement.pathname=e},enumerable:!0},origin:{get:function(){var e={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],t=this._anchorElement.port!=e&&""!==this._anchorElement.port;return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(t?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(e){},enumerable:!0},username:{get:function(){return""},set:function(e){},enumerable:!0}}),n.createObjectURL=function(e){return t.createObjectURL.apply(t,arguments)},n.revokeObjectURL=function(e){return t.revokeObjectURL.apply(t,arguments)},e.URL=n}(),void 0!==e.location&&!("origin"in e.location)){var t=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:t,enumerable:!0})}catch(n){setInterval(function(){e.location.origin=t()},100)}}}(void 0!==e?e:"undefined"!=typeof window?window:"undefined"!=typeof self?self:e);var n=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e},i=function(e,t,i){if(n(e),void 0===t)return e;switch(i){case 1:return function(n){return e.call(t,n)};case 2:return function(n,i){return e.call(t,n,i)};case 3:return function(n,i,r){return e.call(t,n,i,r)}}return function(){return e.apply(t,arguments)}},r=t(function(e){var t=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)}),a=t(function(e){var t=e.exports={version:"2.6.3"};"number"==typeof __e&&(__e=t)}),o=(a.version,function(e){return"object"==typeof e?null!==e:"function"==typeof e}),s=function(e){if(!o(e))throw TypeError(e+" is not an object!");return e},l=function(e){try{return!!e()}catch(e){return!0}},c=!l(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}),u=r.document,h=o(u)&&o(u.createElement),d=function(e){return h?u.createElement(e):{}},f=!c&&!l(function(){return 7!=Object.defineProperty(d("div"),"a",{get:function(){return 7}}).a}),p=function(e,t){if(!o(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!o(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!o(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!o(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")},m=Object.defineProperty,g={f:c?Object.defineProperty:function(e,t,n){if(s(e),t=p(t,!0),s(n),f)try{return m(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},v=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}},y=c?function(e,t,n){return g.f(e,t,v(1,n))}:function(e,t,n){return e[t]=n,e},b={}.hasOwnProperty,w=function(e,t){return b.call(e,t)},k=0,T=Math.random(),E=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++k+T).toString(36))},S=t(function(e){var t=E("src"),n=Function.toString,i=(""+n).split("toString");a.inspectSource=function(e){return n.call(e)},(e.exports=function(e,n,a,o){var s="function"==typeof a;s&&(w(a,"name")||y(a,"name",n)),e[n]!==a&&(s&&(w(a,t)||y(a,t,e[n]?""+e[n]:i.join(String(n)))),e===r?e[n]=a:o?e[n]?e[n]=a:y(e,n,a):(delete e[n],y(e,n,a)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[t]||n.call(this)})}),A=function(e,t,n){var o,s,l,c,u=e&A.F,h=e&A.G,d=e&A.S,f=e&A.P,p=e&A.B,m=h?r:d?r[t]||(r[t]={}):(r[t]||{}).prototype,g=h?a:a[t]||(a[t]={}),v=g.prototype||(g.prototype={});for(o in h&&(n=t),n)l=((s=!u&&m&&void 0!==m[o])?m:n)[o],c=p&&s?i(l,r):f&&"function"==typeof l?i(Function.call,l):l,m&&S(m,o,l,e&A.U),g[o]!=l&&y(g,o,c),f&&v[o]!=l&&(v[o]=l)};r.core=a,A.F=1,A.G=2,A.S=4,A.P=8,A.B=16,A.W=32,A.U=64,A.R=128;var _=A,C=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e},P=function(e){return Object(C(e))},x=function(e,t,n,i){try{return i?t(s(n)[0],n[1]):t(n)}catch(t){var r=e.return;throw void 0!==r&&s(r.call(e)),t}},I={},M=t(function(e){var t=r["__core-js_shared__"]||(r["__core-js_shared__"]={});(e.exports=function(e,n){return t[e]||(t[e]=void 0!==n?n:{})})("versions",[]).push({version:a.version,mode:"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})}),N=t(function(e){var t=M("wks"),n=r.Symbol,i="function"==typeof n;(e.exports=function(e){return t[e]||(t[e]=i&&n[e]||(i?n:E)("Symbol."+e))}).store=t}),L=N("iterator"),O=Array.prototype,j=function(e){return void 0!==e&&(I.Array===e||O[L]===e)},R=Math.ceil,F=Math.floor,D=function(e){return isNaN(e=+e)?0:(e>0?F:R)(e)},q=Math.min,H=function(e){return e>0?q(D(e),9007199254740991):0},V=function(e,t,n){t in e?g.f(e,t,v(0,n)):e[t]=n},B={}.toString,U=function(e){return B.call(e).slice(8,-1)},W=N("toStringTag"),z="Arguments"==U(function(){return arguments}()),K=function(e){var t,n,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),W))?n:z?U(t):"Object"==(i=U(t))&&"function"==typeof t.callee?"Arguments":i},Y=N("iterator"),G=a.getIteratorMethod=function(e){if(null!=e)return e[Y]||e["@@iterator"]||I[K(e)]},$=N("iterator"),Q=!1;try{[7][$]().return=function(){Q=!0}}catch(e){}var X=function(e,t){if(!t&&!Q)return!1;var n=!1;try{var i=[7],r=i[$]();r.next=function(){return{done:n=!0}},i[$]=function(){return r},e(i)}catch(e){}return n};_(_.S+_.F*!X(function(e){}),"Array",{from:function(e){var t,n,r,a,o=P(e),s="function"==typeof this?this:Array,l=arguments.length,c=l>1?arguments[1]:void 0,u=void 0!==c,h=0,d=G(o);if(u&&(c=i(c,l>2?arguments[2]:void 0,2)),null==d||s==Array&&j(d))for(n=new s(t=H(o.length));t>h;h++)V(n,h,u?c(o[h],h):o[h]);else for(a=d.call(o),n=new s;!(r=a.next()).done;h++)V(n,h,u?x(a,c,[r.value,h],!0):r.value);return n.length=h,n}});var J=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==U(e)?e.split(""):Object(e)},Z=Array.isArray||function(e){return"Array"==U(e)},ee=N("species"),te=function(e,t){return new(function(e){var t;return Z(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!Z(t.prototype)||(t=void 0),o(t)&&null===(t=t[ee])&&(t=void 0)),void 0===t?Array:t}(e))(t)},ne=function(e,t){var n=1==e,r=2==e,a=3==e,o=4==e,s=6==e,l=5==e||s,c=t||te;return function(t,u,h){for(var d,f,p=P(t),m=J(p),g=i(u,h,3),v=H(m.length),y=0,b=n?c(t,v):r?c(t,0):void 0;v>y;y++)if((l||y in m)&&(f=g(d=m[y],y,p),e))if(n)b[y]=f;else if(f)switch(e){case 3:return!0;case 5:return d;case 6:return y;case 2:b.push(d)}else if(o)return!1;return s?-1:a||o?o:b}},ie=N("unscopables"),re=Array.prototype;null==re[ie]&&y(re,ie,{});var ae=function(e){re[ie][e]=!0},oe=ne(5),se=!0;"find"in[]&&Array(1).find(function(){se=!1}),_(_.P+_.F*se,"Array",{find:function(e){return oe(this,e,arguments.length>1?arguments[1]:void 0)}}),ae("find");var le={f:{}.propertyIsEnumerable},ce=function(e){return J(C(e))},ue=Object.getOwnPropertyDescriptor,he={f:c?ue:function(e,t){if(e=ce(e),t=p(t,!0),f)try{return ue(e,t)}catch(e){}if(w(e,t))return v(!le.f.call(e,t),e[t])}},de=function(e,t){if(s(e),!o(t)&&null!==t)throw TypeError(t+": can't set as prototype!")},fe={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,n){try{(n=i(Function.call,he.f(Object.prototype,"__proto__").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,i){return de(e,i),t?e.__proto__=i:n(e,i),e}}({},!1):void 0),check:de}.set,pe=function(e,t,n){var i,r=t.constructor;return r!==n&&"function"==typeof r&&(i=r.prototype)!==n.prototype&&o(i)&&fe&&fe(e,i),e},me=Math.max,ge=Math.min,ve=function(e){return function(t,n,i){var r,a=ce(t),o=H(a.length),s=function(e,t){return(e=D(e))<0?me(e+t,0):ge(e,t)}(i,o);if(e&&n!=n){for(;o>s;)if((r=a[s++])!=r)return!0}else for(;o>s;s++)if((e||s in a)&&a[s]===n)return e||s||0;return!e&&-1}},ye=M("keys"),be=function(e){return ye[e]||(ye[e]=E(e))},we=ve(!1),ke=be("IE_PROTO"),Te=function(e,t){var n,i=ce(e),r=0,a=[];for(n in i)n!=ke&&w(i,n)&&a.push(n);for(;t.length>r;)w(i,n=t[r++])&&(~we(a,n)||a.push(n));return a},Ee="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),Se=Ee.concat("length","prototype"),Ae={f:Object.getOwnPropertyNames||function(e){return Te(e,Se)}},_e="\t\n\v\f\r \u2028\u2029\ufeff",Ce="["+_e+"]",Pe=RegExp("^"+Ce+Ce+"*"),xe=RegExp(Ce+Ce+"*$"),Ie=function(e,t,n){var i={},r=l(function(){return!!_e[e]()||"
"!="
"[e]()}),a=i[e]=r?t(Me):_e[e];n&&(i[n]=a),_(_.P+_.F*r,"String",i)},Me=Ie.trim=function(e,t){return e=String(C(e)),1&t&&(e=e.replace(Pe,"")),2&t&&(e=e.replace(xe,"")),e},Ne=Ie,Le=Object.keys||function(e){return Te(e,Ee)},Oe=c?Object.defineProperties:function(e,t){s(e);for(var n,i=Le(t),r=i.length,a=0;r>a;)g.f(e,n=i[a++],t[n]);return e},je=r.document,Re=je&&je.documentElement,Fe=be("IE_PROTO"),De=function(){},qe=function(){var e,t=d("iframe"),n=Ee.length;for(t.style.display="none",Re.appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),qe=e.F;n--;)delete qe.prototype[Ee[n]];return qe()},He=Object.create||function(e,t){var n;return null!==e?(De.prototype=s(e),n=new De,De.prototype=null,n[Fe]=e):n=qe(),void 0===t?n:Oe(n,t)},Ve=Ae.f,Be=he.f,Ue=g.f,We=Ne.trim,ze=r.Number,Ke=ze,Ye=ze.prototype,Ge="Number"==U(He(Ye)),$e="trim"in String.prototype,Qe=function(e){var t=p(e,!1);if("string"==typeof t&&t.length>2){var n,i,r,a=(t=$e?t.trim():We(t,3)).charCodeAt(0);if(43===a||45===a){if(88===(n=t.charCodeAt(2))||120===n)return NaN}else if(48===a){switch(t.charCodeAt(1)){case 66:case 98:i=2,r=49;break;case 79:case 111:i=8,r=55;break;default:return+t}for(var o,s=t.slice(2),l=0,c=s.length;l<c;l++)if((o=s.charCodeAt(l))<48||o>r)return NaN;return parseInt(s,i)}}return+t};if(!ze(" 0o1")||!ze("0b1")||ze("+0x1")){ze=function(e){var t=arguments.length<1?0:e,n=this;return n instanceof ze&&(Ge?l(function(){Ye.valueOf.call(n)}):"Number"!=U(n))?pe(new Ke(Qe(t)),n,ze):Qe(t)};for(var Xe,Je=c?Ve(Ke):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),Ze=0;Je.length>Ze;Ze++)w(Ke,Xe=Je[Ze])&&!w(ze,Xe)&&Ue(ze,Xe,Be(Ke,Xe));ze.prototype=Ye,Ye.constructor=ze,S(r,"Number",ze)}!function(e,t){var n=(a.Object||{})[e]||Object[e],i={};i[e]=t(n),_(_.S+_.F*l(function(){n(1)}),"Object",i)}("keys",function(){return function(e){return Le(P(e))}});var et=N("match"),tt=function(e){var t;return o(e)&&(void 0!==(t=e[et])?!!t:"RegExp"==U(e))},nt=function(e,t,n){if(tt(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(C(e))},it=N("match"),rt=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[it]=!1,!"/./"[e](t)}catch(e){}}return!0};_(_.P+_.F*rt("includes"),"String",{includes:function(e){return!!~nt(this,e,"includes").indexOf(e,arguments.length>1?arguments[1]:void 0)}});var at=ve(!0);_(_.P,"Array",{includes:function(e){return at(this,e,arguments.length>1?arguments[1]:void 0)}}),ae("includes");var ot=Object.is||function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t},st=RegExp.prototype.exec,lt=function(e,t){var n=e.exec;if("function"==typeof n){var i=n.call(e,t);if("object"!=typeof i)throw new TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==K(e))throw new TypeError("RegExp#exec called on incompatible receiver");return st.call(e,t)},ct=function(){var e=s(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t},ut=RegExp.prototype.exec,ht=String.prototype.replace,dt=ut,ft=function(){var e=/a/,t=/b*/g;return ut.call(e,"a"),ut.call(t,"a"),0!==e.lastIndex||0!==t.lastIndex}(),pt=void 0!==/()??/.exec("")[1];(ft||pt)&&(dt=function(e){var t,n,i,r,a=this;return pt&&(n=new RegExp("^"+a.source+"$(?!\\s)",ct.call(a))),ft&&(t=a.lastIndex),i=ut.call(a,e),ft&&i&&(a.lastIndex=a.global?i.index+i[0].length:t),pt&&i&&i.length>1&&ht.call(i[0],n,function(){for(r=1;r<arguments.length-2;r++)void 0===arguments[r]&&(i[r]=void 0)}),i});var mt=dt;_({target:"RegExp",proto:!0,forced:mt!==/./.exec},{exec:mt});var gt=N("species"),vt=!l(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$<a>")}),yt=function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2===n.length&&"a"===n[0]&&"b"===n[1]}(),bt=function(e,t,n){var i=N(e),r=!l(function(){var t={};return t[i]=function(){return 7},7!=""[e](t)}),a=r?!l(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===e&&(n.constructor={},n.constructor[gt]=function(){return n}),n[i](""),!t}):void 0;if(!r||!a||"replace"===e&&!vt||"split"===e&&!yt){var o=/./[i],s=n(C,i,""[e],function(e,t,n,i,a){return t.exec===mt?r&&!a?{done:!0,value:o.call(t,n,i)}:{done:!0,value:e.call(n,t,i)}:{done:!1}}),c=s[0],u=s[1];S(String.prototype,e,c),y(RegExp.prototype,i,2==t?function(e,t){return u.call(e,this,t)}:function(e){return u.call(e,this)})}};bt("search",1,function(e,t,n,i){return[function(n){var i=e(this),r=null==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},function(e){var t=i(n,e,this);if(t.done)return t.value;var r=s(e),a=String(this),o=r.lastIndex;ot(o,0)||(r.lastIndex=0);var l=lt(r,a);return ot(r.lastIndex,o)||(r.lastIndex=o),null===l?-1:l.index}]}),c&&"g"!=/./g.flags&&g.f(RegExp.prototype,"flags",{configurable:!0,get:ct});var wt=/./.toString,kt=function(e){S(RegExp.prototype,"toString",e,!0)};l(function(){return"/a/b"!=wt.call({source:"a",flags:"b"})})?kt(function(){var e=s(this);return"/".concat(e.source,"/","flags"in e?e.flags:!c&&e instanceof RegExp?ct.call(e):void 0)}):"toString"!=wt.name&&kt(function(){return wt.call(this)});var Tt=function(e,t){return{value:t,done:!!e}},Et=g.f,St=N("toStringTag"),At=function(e,t,n){e&&!w(e=n?e:e.prototype,St)&&Et(e,St,{configurable:!0,value:t})},_t={};y(_t,N("iterator"),function(){return this});var Ct=function(e,t,n){e.prototype=He(_t,{next:v(1,n)}),At(e,t+" Iterator")},Pt=be("IE_PROTO"),xt=Object.prototype,It=Object.getPrototypeOf||function(e){return e=P(e),w(e,Pt)?e[Pt]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?xt:null},Mt=N("iterator"),Nt=!([].keys&&"next"in[].keys()),Lt=function(){return this},Ot=function(e,t,n,i,r,a,o){Ct(n,t,i);var s,l,c,u=function(e){if(!Nt&&e in p)return p[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},h=t+" Iterator",d="values"==r,f=!1,p=e.prototype,m=p[Mt]||p["@@iterator"]||r&&p[r],g=m||u(r),v=r?d?u("entries"):g:void 0,b="Array"==t&&p.entries||m;if(b&&(c=It(b.call(new e)))!==Object.prototype&&c.next&&(At(c,h,!0),"function"!=typeof c[Mt]&&y(c,Mt,Lt)),d&&m&&"values"!==m.name&&(f=!0,g=function(){return m.call(this)}),(Nt||f||!p[Mt])&&y(p,Mt,g),I[t]=g,I[h]=Lt,r)if(s={values:d?g:u("values"),keys:a?g:u("keys"),entries:v},o)for(l in s)l in p||S(p,l,s[l]);else _(_.P+_.F*(Nt||f),t,s);return s},jt=Ot(Array,"Array",function(e,t){this._t=ce(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,Tt(1)):Tt(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values");I.Arguments=I.Array,ae("keys"),ae("values"),ae("entries");for(var Rt=N("iterator"),Ft=N("toStringTag"),Dt=I.Array,qt={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},Ht=Le(qt),Vt=0;Vt<Ht.length;Vt++){var Bt,Ut=Ht[Vt],Wt=qt[Ut],zt=r[Ut],Kt=zt&&zt.prototype;if(Kt&&(Kt[Rt]||y(Kt,Rt,Dt),Kt[Ft]||y(Kt,Ft,Ut),I[Ut]=Dt,Wt))for(Bt in jt)Kt[Bt]||S(Kt,Bt,jt[Bt],!0)}var Yt=function(e){return function(t,n){var i,r,a=String(C(t)),o=D(n),s=a.length;return o<0||o>=s?e?"":void 0:(i=a.charCodeAt(o))<55296||i>56319||o+1===s||(r=a.charCodeAt(o+1))<56320||r>57343?e?a.charAt(o):i:e?a.slice(o,o+2):r-56320+(i-55296<<10)+65536}},Gt=Yt(!0);Ot(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=Gt(t,n),this._i+=e.length,{value:e,done:!1})});var $t=t(function(e){var t=E("meta"),n=g.f,i=0,r=Object.isExtensible||function(){return!0},a=!l(function(){return r(Object.preventExtensions({}))}),s=function(e){n(e,t,{value:{i:"O"+ ++i,w:{}}})},c=e.exports={KEY:t,NEED:!1,fastKey:function(e,n){if(!o(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!w(e,t)){if(!r(e))return"F";if(!n)return"E";s(e)}return e[t].i},getWeak:function(e,n){if(!w(e,t)){if(!r(e))return!0;if(!n)return!1;s(e)}return e[t].w},onFreeze:function(e){return a&&c.NEED&&r(e)&&!w(e,t)&&s(e),e}}}),Qt=($t.KEY,$t.NEED,$t.fastKey,$t.getWeak,$t.onFreeze,{f:Object.getOwnPropertySymbols}),Xt=Object.assign,Jt=!Xt||l(function(){var e={},t={},n=Symbol(),i="abcdefghijklmnopqrst";return e[n]=7,i.split("").forEach(function(e){t[e]=e}),7!=Xt({},e)[n]||Object.keys(Xt({},t)).join("")!=i})?function(e,t){for(var n=P(e),i=arguments.length,r=1,a=Qt.f,o=le.f;i>r;)for(var s,l=J(arguments[r++]),c=a?Le(l).concat(a(l)):Le(l),u=c.length,h=0;u>h;)o.call(l,s=c[h++])&&(n[s]=l[s]);return n}:Xt,Zt=function(e,t,n){for(var i in t)S(e,i,t[i],n);return e},en=function(e,t,n,i){if(!(e instanceof t)||void 0!==i&&i in e)throw TypeError(n+": incorrect invocation!");return e},tn=t(function(e){var t={},n={},r=e.exports=function(e,r,a,o,l){var c,u,h,d,f=l?function(){return e}:G(e),p=i(a,o,r?2:1),m=0;if("function"!=typeof f)throw TypeError(e+" is not iterable!");if(j(f)){for(c=H(e.length);c>m;m++)if((d=r?p(s(u=e[m])[0],u[1]):p(e[m]))===t||d===n)return d}else for(h=f.call(e);!(u=h.next()).done;)if((d=x(h,p,u.value,r))===t||d===n)return d};r.BREAK=t,r.RETURN=n}),nn=function(e,t){if(!o(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e},rn=$t.getWeak,an=ne(5),on=ne(6),sn=0,ln=function(e){return e._l||(e._l=new cn)},cn=function(){this.a=[]},un=function(e,t){return an(e.a,function(e){return e[0]===t})};cn.prototype={get:function(e){var t=un(this,e);if(t)return t[1]},has:function(e){return!!un(this,e)},set:function(e,t){var n=un(this,e);n?n[1]=t:this.a.push([e,t])},delete:function(e){var t=on(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}};var hn={getConstructor:function(e,t,n,i){var r=e(function(e,a){en(e,r,t,"_i"),e._t=t,e._i=sn++,e._l=void 0,null!=a&&tn(a,n,e[i],e)});return Zt(r.prototype,{delete:function(e){if(!o(e))return!1;var n=rn(e);return!0===n?ln(nn(this,t)).delete(e):n&&w(n,this._i)&&delete n[this._i]},has:function(e){if(!o(e))return!1;var n=rn(e);return!0===n?ln(nn(this,t)).has(e):n&&w(n,this._i)}}),r},def:function(e,t,n){var i=rn(s(t),!0);return!0===i?ln(e).set(t,n):i[e._i]=n,e},ufstore:ln};t(function(e){var t,n=ne(0),i=$t.getWeak,a=Object.isExtensible,s=hn.ufstore,c={},u=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},h={get:function(e){if(o(e)){var t=i(e);return!0===t?s(nn(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return hn.def(nn(this,"WeakMap"),e,t)}},d=e.exports=function(e,t,n,i,a,s){var c=r[e],u=c,h=a?"set":"add",d=u&&u.prototype,f={},p=function(e){var t=d[e];S(d,e,"delete"==e?function(e){return!(s&&!o(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(s&&!o(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return s&&!o(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,n){return t.call(this,0===e?0:e,n),this})};if("function"==typeof u&&(s||d.forEach&&!l(function(){(new u).entries().next()}))){var m=new u,g=m[h](s?{}:-0,1)!=m,v=l(function(){m.has(1)}),y=X(function(e){new u(e)}),b=!s&&l(function(){for(var e=new u,t=5;t--;)e[h](t,t);return!e.has(-0)});y||((u=t(function(t,n){en(t,u,e);var i=pe(new c,t,u);return null!=n&&tn(n,a,i[h],i),i})).prototype=d,d.constructor=u),(v||b)&&(p("delete"),p("has"),a&&p("get")),(b||g)&&p(h),s&&d.clear&&delete d.clear}else u=i.getConstructor(t,e,a,h),Zt(u.prototype,n),$t.NEED=!0;return At(u,e),f[e]=u,_(_.G+_.W+_.F*(u!=c),f),s||i.setStrong(u,e,a),u}("WeakMap",u,h,hn,!0,!0);l(function(){return 7!=(new d).set((Object.freeze||Object)(c),7).get(c)})&&(t=hn.getConstructor(u,"WeakMap"),Jt(t.prototype,h),$t.NEED=!0,n(["delete","has","get","set"],function(e){var n=d.prototype,i=n[e];S(n,e,function(n,r){if(o(n)&&!a(n)){this._f||(this._f=new t);var s=this._f[e](n,r);return"set"==e?this:s}return i.call(this,n,r)})}))});function dn(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function fn(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function pn(e,t,n){return t&&fn(e.prototype,t),n&&fn(e,n),e}function mn(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function gn(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=[],i=!0,r=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(i=(o=s.next()).done)&&(n.push(o.value),!t||n.length!==t);i=!0);}catch(e){r=!0,a=e}finally{try{i||null==s.return||s.return()}finally{if(r)throw a}}return n}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function vn(e){return function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}var yn,bn,wn=[].sort,kn=[1,2,3];_(_.P+_.F*(l(function(){kn.sort(void 0)})||!l(function(){kn.sort(null)})||!((yn=wn)&&l(function(){bn?yn.call(null,function(){},1):yn.call(null)}))),"Array",{sort:function(e){return void 0===e?wn.call(P(this)):wn.call(P(this),n(e))}}),_(_.S+_.F,"Object",{assign:Jt});var Tn=N("species"),En=function(e,t){var i,r=s(e).constructor;return void 0===r||null==(i=s(r)[Tn])?t:n(i)},Sn=Yt(!0),An=function(e,t,n){return t+(n?Sn(e,t).length:1)},_n=Math.min,Cn=[].push,Pn=!l(function(){});bt("split",2,function(e,t,n,i){var r;return r="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(e,t){var i=String(this);if(void 0===e&&0===t)return[];if(!tt(e))return n.call(i,e,t);for(var r,a,o,s=[],l=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),c=0,u=void 0===t?4294967295:t>>>0,h=new RegExp(e.source,l+"g");(r=mt.call(h,i))&&!((a=h.lastIndex)>c&&(s.push(i.slice(c,r.index)),r.length>1&&r.index<i.length&&Cn.apply(s,r.slice(1)),o=r[0].length,c=a,s.length>=u));)h.lastIndex===r.index&&h.lastIndex++;return c===i.length?!o&&h.test("")||s.push(""):s.push(i.slice(c)),s.length>u?s.slice(0,u):s}:"0".split(void 0,0).length?function(e,t){return void 0===e&&0===t?[]:n.call(this,e,t)}:n,[function(n,i){var a=e(this),o=null==n?void 0:n[t];return void 0!==o?o.call(n,a,i):r.call(String(a),n,i)},function(e,t){var a=i(r,e,this,t,r!==n);if(a.done)return a.value;var o=s(e),l=String(this),c=En(o,RegExp),u=o.unicode,h=(o.ignoreCase?"i":"")+(o.multiline?"m":"")+(o.unicode?"u":"")+(Pn?"y":"g"),d=new c(Pn?o:"^(?:"+o.source+")",h),f=void 0===t?4294967295:t>>>0;if(0===f)return[];if(0===l.length)return null===lt(d,l)?[l]:[];for(var p=0,m=0,g=[];m<l.length;){d.lastIndex=Pn?m:0;var v,y=lt(d,Pn?l:l.slice(m));if(null===y||(v=_n(H(d.lastIndex+(Pn?0:m)),l.length))===p)m=An(l,m,u);else{if(g.push(l.slice(p,m)),g.length===f)return g;for(var b=1;b<=y.length-1;b++)if(g.push(y[b]),g.length===f)return g;m=p=v}}return g.push(l.slice(p)),g}]});var xn=le.f,In=function(e){return function(t){for(var n,i=ce(t),r=Le(i),a=r.length,o=0,s=[];a>o;)xn.call(i,n=r[o++])&&s.push(e?[n,i[n]]:i[n]);return s}},Mn=In(!0);_(_.S,"Object",{entries:function(e){return Mn(e)}});var Nn=In(!1);_(_.S,"Object",{values:function(e){return Nn(e)}});var Ln=Math.max,On=Math.min,jn=Math.floor,Rn=/\$([$&`']|\d\d?|<[^>]*>)/g,Fn=/\$([$&`']|\d\d?)/g;bt("replace",2,function(e,t,n,i){return[function(i,r){var a=e(this),o=null==i?void 0:i[t];return void 0!==o?o.call(i,a,r):n.call(String(a),i,r)},function(e,t){var a=i(n,e,this,t);if(a.done)return a.value;var o=s(e),l=String(this),c="function"==typeof t;c||(t=String(t));var u=o.global;if(u){var h=o.unicode;o.lastIndex=0}for(var d=[];;){var f=lt(o,l);if(null===f)break;if(d.push(f),!u)break;""===String(f[0])&&(o.lastIndex=An(l,H(o.lastIndex),h))}for(var p,m="",g=0,v=0;v<d.length;v++){f=d[v];for(var y=String(f[0]),b=Ln(On(D(f.index),l.length),0),w=[],k=1;k<f.length;k++)w.push(void 0===(p=f[k])?p:String(p));var T=f.groups;if(c){var E=[y].concat(w,b,l);void 0!==T&&E.push(T);var S=String(t.apply(void 0,E))}else S=r(y,l,b,w,T,t);b>=g&&(m+=l.slice(g,b)+S,g=b+y.length)}return m+l.slice(g)}];function r(e,t,i,r,a,o){var s=i+e.length,l=r.length,c=Fn;return void 0!==a&&(a=P(a),c=Rn),n.call(o,c,function(n,o){var c;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,i);case"'":return t.slice(s);case"<":c=a[o.slice(1,-1)];break;default:var u=+o;if(0===u)return n;if(u>l){var h=jn(u/10);return 0===h?n:h<=l?void 0===r[h-1]?o.charAt(1):r[h-1]+o.charAt(1):n}c=r[u-1]}return void 0===c?"":c})}});var Dn,qn,Hn,Vn=r.process,Bn=r.setImmediate,Un=r.clearImmediate,Wn=r.MessageChannel,zn=r.Dispatch,Kn=0,Yn={},Gn=function(){var e=+this;if(Yn.hasOwnProperty(e)){var t=Yn[e];delete Yn[e],t()}},$n=function(e){Gn.call(e.data)};Bn&&Un||(Bn=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return Yn[++Kn]=function(){!function(e,t,n){var i=void 0===n;switch(t.length){case 0:return i?e():e.call(n);case 1:return i?e(t[0]):e.call(n,t[0]);case 2:return i?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return i?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return i?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}e.apply(n,t)}("function"==typeof e?e:Function(e),t)},Dn(Kn),Kn},Un=function(e){delete Yn[e]},"process"==U(Vn)?Dn=function(e){Vn.nextTick(i(Gn,e,1))}:zn&&zn.now?Dn=function(e){zn.now(i(Gn,e,1))}:Wn?(Hn=(qn=new Wn).port2,qn.port1.onmessage=$n,Dn=i(Hn.postMessage,Hn,1)):r.addEventListener&&"function"==typeof postMessage&&!r.importScripts?(Dn=function(e){r.postMessage(e+"","*")},r.addEventListener("message",$n,!1)):Dn="onreadystatechange"in d("script")?function(e){Re.appendChild(d("script")).onreadystatechange=function(){Re.removeChild(this),Gn.call(e)}}:function(e){setTimeout(i(Gn,e,1),0)});var Qn={set:Bn,clear:Un},Xn=Qn.set,Jn=r.MutationObserver||r.WebKitMutationObserver,Zn=r.process,ei=r.Promise,ti="process"==U(Zn);function ni(e){var t,i;this.promise=new e(function(e,n){if(void 0!==t||void 0!==i)throw TypeError("Bad Promise constructor");t=e,i=n}),this.resolve=n(t),this.reject=n(i)}var ii,ri,ai,oi,si={f:function(e){return new ni(e)}},li=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}},ci=r.navigator,ui=ci&&ci.userAgent||"",hi=N("species"),di=function(e){var t=r[e];c&&t&&!t[hi]&&g.f(t,hi,{configurable:!0,get:function(){return this}})},fi=Qn.set,pi=function(){var e,t,n,i=function(){var i,r;for(ti&&(i=Zn.domain)&&i.exit();e;){r=e.fn,e=e.next;try{r()}catch(i){throw e?n():t=void 0,i}}t=void 0,i&&i.enter()};if(ti)n=function(){Zn.nextTick(i)};else if(!Jn||r.navigator&&r.navigator.standalone)if(ei&&ei.resolve){var a=ei.resolve(void 0);n=function(){a.then(i)}}else n=function(){Xn.call(r,i)};else{var o=!0,s=document.createTextNode("");new Jn(i).observe(s,{characterData:!0}),n=function(){s.data=o=!o}}return function(i){var r={fn:i,next:void 0};t&&(t.next=r),e||(e=r,n()),t=r}}(),mi=r.TypeError,gi=r.process,vi=gi&&gi.versions,yi=vi&&vi.v8||"",bi=r.Promise,wi="process"==K(gi),ki=function(){},Ti=ri=si.f,Ei=!!function(){try{var e=bi.resolve(1),t=(e.constructor={})[N("species")]=function(e){e(ki,ki)};return(wi||"function"==typeof PromiseRejectionEvent)&&e.then(ki)instanceof t&&0!==yi.indexOf("6.6")&&-1===ui.indexOf("Chrome/66")}catch(e){}}(),Si=function(e){var t;return!(!o(e)||"function"!=typeof(t=e.then))&&t},Ai=function(e,t){if(!e._n){e._n=!0;var n=e._c;pi(function(){for(var i=e._v,r=1==e._s,a=0,o=function(t){var n,a,o,s=r?t.ok:t.fail,l=t.resolve,c=t.reject,u=t.domain;try{s?(r||(2==e._h&&Pi(e),e._h=1),!0===s?n=i:(u&&u.enter(),n=s(i),u&&(u.exit(),o=!0)),n===t.promise?c(mi("Promise-chain cycle")):(a=Si(n))?a.call(n,l,c):l(n)):c(i)}catch(e){u&&!o&&u.exit(),c(e)}};n.length>a;)o(n[a++]);e._c=[],e._n=!1,t&&!e._h&&_i(e)})}},_i=function(e){fi.call(r,function(){var t,n,i,a=e._v,o=Ci(e);if(o&&(t=li(function(){wi?gi.emit("unhandledRejection",a,e):(n=r.onunhandledrejection)?n({promise:e,reason:a}):(i=r.console)&&i.error&&i.error("Unhandled promise rejection",a)}),e._h=wi||Ci(e)?2:1),e._a=void 0,o&&t.e)throw t.v})},Ci=function(e){return 1!==e._h&&0===(e._a||e._c).length},Pi=function(e){fi.call(r,function(){var t;wi?gi.emit("rejectionHandled",e):(t=r.onrejectionhandled)&&t({promise:e,reason:e._v})})},xi=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),Ai(t,!0))},Ii=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw mi("Promise can't be resolved itself");(t=Si(e))?pi(function(){var r={_w:n,_d:!1};try{t.call(e,i(Ii,r,1),i(xi,r,1))}catch(e){xi.call(r,e)}}):(n._v=e,n._s=1,Ai(n,!1))}catch(e){xi.call({_w:n,_d:!1},e)}}};Ei||(bi=function(e){en(this,bi,"Promise","_h"),n(e),ii.call(this);try{e(i(Ii,this,1),i(xi,this,1))}catch(e){xi.call(this,e)}},(ii=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=Zt(bi.prototype,{then:function(e,t){var n=Ti(En(this,bi));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=wi?gi.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&Ai(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),ai=function(){var e=new ii;this.promise=e,this.resolve=i(Ii,e,1),this.reject=i(xi,e,1)},si.f=Ti=function(e){return e===bi||e===oi?new ai(e):ri(e)}),_(_.G+_.W+_.F*!Ei,{Promise:bi}),At(bi,"Promise"),di("Promise"),oi=a.Promise,_(_.S+_.F*!Ei,"Promise",{reject:function(e){var t=Ti(this);return(0,t.reject)(e),t.promise}}),_(_.S+_.F*!Ei,"Promise",{resolve:function(e){return function(e,t){if(s(e),o(t)&&t.constructor===e)return t;var n=si.f(e);return(0,n.resolve)(t),n.promise}(this,e)}}),_(_.S+_.F*!(Ei&&X(function(e){bi.all(e).catch(ki)})),"Promise",{all:function(e){var t=this,n=Ti(t),i=n.resolve,r=n.reject,a=li(function(){var n=[],a=0,o=1;tn(e,!1,function(e){var s=a++,l=!1;n.push(void 0),o++,t.resolve(e).then(function(e){l||(l=!0,n[s]=e,--o||i(n))},r)}),--o||i(n)});return a.e&&r(a.v),n.promise},race:function(e){var t=this,n=Ti(t),i=n.reject,r=li(function(){tn(e,!1,function(e){t.resolve(e).then(n.resolve,i)})});return r.e&&i(r.v),n.promise}});var Mi="".startsWith;_(_.P+_.F*rt("startsWith"),"String",{startsWith:function(e){var t=nt(this,e,"startsWith"),n=H(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),i=String(e);return Mi?Mi.call(t,i,n):t.slice(n,n+i.length)===i}}),_(_.S,"Number",{isNaN:function(e){return e!=e}});var Ni=function(e){return null!=e?e.constructor:null},Li=function(e,t){return Boolean(e&&t&&e instanceof t)},Oi=function(e){return null==e},ji=function(e){return Ni(e)===Object},Ri=function(e){return Ni(e)===String},Fi=function(e){return Array.isArray(e)},Di=function(e){return Li(e,NodeList)},qi=function(e){return Oi(e)||(Ri(e)||Fi(e)||Di(e))&&!e.length||ji(e)&&!Object.keys(e).length},Hi={nullOrUndefined:Oi,object:ji,number:function(e){return Ni(e)===Number&&!Number.isNaN(e)},string:Ri,boolean:function(e){return Ni(e)===Boolean},function:function(e){return Ni(e)===Function},array:Fi,weakMap:function(e){return Li(e,WeakMap)},nodeList:Di,element:function(e){return Li(e,Element)},textNode:function(e){return Ni(e)===Text},event:function(e){return Li(e,Event)},keyboardEvent:function(e){return Li(e,KeyboardEvent)},cue:function(e){return Li(e,window.TextTrackCue)||Li(e,window.VTTCue)},track:function(e){return Li(e,TextTrack)||!Oi(e)&&Ri(e.kind)},url:function(e){if(Li(e,window.URL))return!0;if(!Ri(e))return!1;var t=e;e.startsWith("http://")&&e.startsWith("https://")||(t="http://".concat(e));try{return!qi(new URL(t).hostname)}catch(e){return!1}},empty:qi},Vi=function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(e){}return e}();function Bi(e,t,n){var i=this,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(e&&"addEventListener"in e&&!Hi.empty(t)&&Hi.function(n)){var s=t.split(" "),l=o;Vi&&(l={passive:a,capture:o}),s.forEach(function(t){i&&i.eventListeners&&r&&i.eventListeners.push({element:e,type:t,callback:n,options:l}),e[r?"addEventListener":"removeEventListener"](t,n,l)})}}function Ui(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Bi.call(this,e,t,n,!0,i,r)}function Wi(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Bi.call(this,e,t,n,!1,i,r)}function zi(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];Bi.call(this,e,n,function o(){Wi(e,n,o,r,a);for(var s=arguments.length,l=new Array(s),c=0;c<s;c++)l[c]=arguments[c];i.apply(t,l)},!0,r,a)}function Ki(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(Hi.element(e)&&!Hi.empty(t)){var r=new CustomEvent(t,{bubbles:n,detail:Object.assign({},i,{plyr:this})});e.dispatchEvent(r)}}function Yi(e,t){var n=e.length?e:[e];Array.from(n).reverse().forEach(function(e,n){var i=n>0?t.cloneNode(!0):t,r=e.parentNode,a=e.nextSibling;i.appendChild(e),a?r.insertBefore(i,a):r.appendChild(i)})}function Gi(e,t){Hi.element(e)&&!Hi.empty(t)&&Object.entries(t).filter(function(e){var t=gn(e,2)[1];return!Hi.nullOrUndefined(t)}).forEach(function(t){var n=gn(t,2),i=n[0],r=n[1];return e.setAttribute(i,r)})}function $i(e,t,n){var i=document.createElement(e);return Hi.object(t)&&Gi(i,t),Hi.string(n)&&(i.innerText=n),i}function Qi(e,t,n,i){Hi.element(t)&&t.appendChild($i(e,n,i))}function Xi(e){Hi.nodeList(e)||Hi.array(e)?Array.from(e).forEach(Xi):Hi.element(e)&&Hi.element(e.parentNode)&&e.parentNode.removeChild(e)}function Ji(e){if(Hi.element(e))for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1}function Zi(e,t){return Hi.element(t)&&Hi.element(t.parentNode)&&Hi.element(e)?(t.parentNode.replaceChild(e,t),e):null}function er(e,t){if(!Hi.string(e)||Hi.empty(e))return{};var n={},i=t;return e.split(",").forEach(function(e){var t=e.trim(),r=t.replace(".",""),a=t.replace(/[[\]]/g,"").split("="),o=a[0],s=a.length>1?a[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":Hi.object(i)&&Hi.string(i.class)&&(i.class+=" ".concat(r)),n.class=r;break;case"#":n.id=t.replace("#","");break;case"[":n[o]=s}}),n}function tr(e,t){if(Hi.element(e)){var n=t;Hi.boolean(n)||(n=!e.hidden),n?e.setAttribute("hidden",""):e.removeAttribute("hidden")}}function nr(e,t,n){if(Hi.nodeList(e))return Array.from(e).map(function(e){return nr(e,t,n)});if(Hi.element(e)){var i="toggle";return void 0!==n&&(i=n?"add":"remove"),e.classList[i](t),e.classList.contains(t)}return!1}function ir(e,t){return Hi.element(e)&&e.classList.contains(t)}function rr(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function ar(e){return this.elements.container.querySelectorAll(e)}function or(e){return this.elements.container.querySelector(e)}function sr(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];Hi.element(e)&&(e.focus({preventScroll:!0}),t&&nr(e,this.config.classNames.tabFocus))}var lr,cr,ur,hr=(lr=document.createElement("span"),cr={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},ur=Object.keys(cr).find(function(e){return void 0!==lr.style[e]}),!!Hi.string(ur)&&cr[ur]);function dr(e){setTimeout(function(){try{tr(e,!0),e.offsetHeight,tr(e,!1)}catch(e){}},0)}var fr,pr={isIE:!!document.documentMode,isEdge:window.navigator.userAgent.includes("Edge"),isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)},mr={"audio/ogg":"vorbis","audio/wav":"1","video/webm":"vp8, vorbis","video/mp4":"avc1.42E01E, mp4a.40.2","video/ogg":"theora"},gr={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,n){var i=pr.isIPhone&&n&&gr.playsinline,r=gr[e]||"html5"!==t;return{api:r,ui:r&&gr.rangeInput&&("video"!==e||!pr.isIPhone||i)}},pip:!(pr.isIPhone||!Hi.function($i("video").webkitSetPresentationMode)&&(!document.pictureInPictureEnabled||$i("video").disablePictureInPicture)),airplay:Hi.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){if(Hi.empty(e))return!1;var t=gn(e.split("/"),1)[0],n=e;if(!this.isHTML5||t!==this.type)return!1;Object.keys(mr).includes(n)&&(n+='; codecs="'.concat(mr[e],'"'));try{return Boolean(n&&this.media.canPlayType(n).replace(/no/,""))}catch(e){return!1}},textTracks:"textTracks"in document.createElement("video"),rangeInput:(fr=document.createElement("input"),fr.type="range","range"===fr.type),touch:"ontouchstart"in document.documentElement,transitions:!1!==hr,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},vr={getSources:function(){var e=this;return this.isHTML5?Array.from(this.media.querySelectorAll("source")).filter(function(t){var n=t.getAttribute("type");return!!Hi.empty(n)||gr.mime.call(e,n)}):[]},getQualityOptions:function(){return vr.getSources.call(this).map(function(e){return Number(e.getAttribute("size"))}).filter(Boolean)},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=vr.getSources.call(e).find(function(t){return t.getAttribute("src")===e.source});return t&&Number(t.getAttribute("size"))},set:function(t){var n=vr.getSources.call(e).find(function(e){return Number(e.getAttribute("size"))===t});if(n){var i=e.media,r=i.currentTime,a=i.paused,o=i.preload,s=i.readyState;e.media.src=n.getAttribute("src"),("none"!==o||s)&&(e.once("loadedmetadata",function(){e.currentTime=r,a||e.play()}),e.media.load()),Ki.call(e,e.media,"qualitychange",!1,{quality:t})}}})}},cancelRequests:function(){this.isHTML5&&(Xi(vr.getSources.call(this)),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}};function yr(e){return Hi.array(e)?e.filter(function(t,n){return e.indexOf(t)===n}):e}function br(e,t){return t.split(".").reduce(function(e,t){return e&&e[t]},e)}function wr(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];if(!n.length)return e;var r=n.shift();return Hi.object(r)?(Object.keys(r).forEach(function(t){Hi.object(r[t])?(Object.keys(e).includes(t)||Object.assign(e,mn({},t,{})),wr(e[t],r[t])):Object.assign(e,mn({},t,r[t]))}),wr.apply(void 0,[e].concat(n))):e}var kr=g.f,Tr=Ae.f,Er=r.RegExp,Sr=Er,Ar=Er.prototype,_r=/a/g,Cr=/a/g,Pr=new Er(_r)!==_r;if(c&&(!Pr||l(function(){return Cr[N("match")]=!1,Er(_r)!=_r||Er(Cr)==Cr||"/a/i"!=Er(_r,"i")}))){Er=function(e,t){var n=this instanceof Er,i=tt(e),r=void 0===t;return!n&&i&&e.constructor===Er&&r?e:pe(Pr?new Sr(i&&!r?e.source:e,t):Sr((i=e instanceof Er)?e.source:e,i&&r?ct.call(e):t),n?this:Ar,Er)};for(var xr=function(e){e in Er||kr(Er,e,{configurable:!0,get:function(){return Sr[e]},set:function(t){Sr[e]=t}})},Ir=Tr(Sr),Mr=0;Ir.length>Mr;)xr(Ir[Mr++]);Ar.constructor=Er,Er.prototype=Ar,S(r,"RegExp",Er)}function Nr(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];return Hi.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return n[t].toString()})}function Lr(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"),n.toString())}function Or(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}function jr(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=Lr(e,"-"," "),e=Lr(e,"_"," "),Lr(e=Or(e)," ","")}(e)).charAt(0).toLowerCase()+e.slice(1)}function Rr(e){var t=document.createElement("div");return t.appendChild(e),t.innerHTML}di("RegExp");var Fr={pip:"PIP",airplay:"AirPlay",html5:"HTML5",vimeo:"Vimeo",youtube:"YouTube"},Dr=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(Hi.empty(e)||Hi.empty(t))return"";var n=br(t.i18n,e);if(Hi.empty(n))return Object.keys(Fr).includes(e)?Fr[e]:"";var i={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(i).forEach(function(e){var t=gn(e,2),i=t[0],r=t[1];n=Lr(n,i,r)}),n},qr=function(){function e(t){dn(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return pn(e,[{key:"get",value:function(t){if(!e.supported||!this.enabled)return null;var n=window.localStorage.getItem(this.key);if(Hi.empty(n))return null;var i=JSON.parse(n);return Hi.string(t)&&t.length?i[t]:i}},{key:"set",value:function(t){if(e.supported&&this.enabled&&Hi.object(t)){var n=this.get();Hi.empty(n)&&(n={}),wr(n,t),window.localStorage.setItem(this.key,JSON.stringify(n))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();function Hr(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(n,i){try{var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.addEventListener("load",function(){if("text"===t)try{n(JSON.parse(r.responseText))}catch(e){n(r.responseText)}else n(r.response)}),r.addEventListener("error",function(){throw new Error(r.status)}),r.open("GET",e,!0),r.responseType=t,r.send()}catch(e){i(e)}})}function Vr(e,t){if(Hi.string(e)){var n=Hi.string(t),i=function(){return null!==document.getElementById(t)},r=function(e,t){e.innerHTML=t,n&&i()||document.body.insertAdjacentElement("afterbegin",e)};if(!n||!i()){var a=qr.supported,o=document.createElement("div");if(o.setAttribute("hidden",""),n&&o.setAttribute("id",t),a){var s=window.localStorage.getItem("".concat("cache","-").concat(t));if(null!==s){var l=JSON.parse(s);r(o,l.content)}}Hr(e).then(function(e){Hi.empty(e)||(a&&window.localStorage.setItem("".concat("cache","-").concat(t),JSON.stringify({content:e})),r(o,e))}).catch(function(){})}}}_(_.S,"Math",{trunc:function(e){return(e>0?Math.floor:Math.ceil)(e)}});var Br=function(e){return Math.trunc(e/60/60%60,10)},Ur=function(e){return Math.trunc(e/60%60,10)},Wr=function(e){return Math.trunc(e%60,10)};function zr(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!Hi.number(e))return zr(null,t,n);var i=function(e){return"0".concat(e).slice(-2)},r=Br(e),a=Ur(e),o=Wr(e);return r=t||r>0?"".concat(r,":"):"","".concat(n&&e>0?"-":"").concat(r).concat(i(a),":").concat(i(o))}var Kr={getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||pr.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=or.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:ar.call(this,this.config.selectors.buttons.play),pause:or.call(this,this.config.selectors.buttons.pause),restart:or.call(this,this.config.selectors.buttons.restart),rewind:or.call(this,this.config.selectors.buttons.rewind),fastForward:or.call(this,this.config.selectors.buttons.fastForward),mute:or.call(this,this.config.selectors.buttons.mute),pip:or.call(this,this.config.selectors.buttons.pip),airplay:or.call(this,this.config.selectors.buttons.airplay),settings:or.call(this,this.config.selectors.buttons.settings),captions:or.call(this,this.config.selectors.buttons.captions),fullscreen:or.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=or.call(this,this.config.selectors.progress),this.elements.inputs={seek:or.call(this,this.config.selectors.inputs.seek),volume:or.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:or.call(this,this.config.selectors.display.buffer),currentTime:or.call(this,this.config.selectors.display.currentTime),duration:or.call(this,this.config.selectors.display.duration)},Hi.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip))),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var n=Kr.getIconUrl.call(this),i="".concat(n.cors?"":n.url,"#").concat(this.config.iconPrefix),r=document.createElementNS("http://www.w3.org/2000/svg","svg");Gi(r,wr(t,{role:"presentation",focusable:"false"}));var a=document.createElementNS("http://www.w3.org/2000/svg","use"),o="".concat(i,"-").concat(e);return"href"in a&&a.setAttributeNS("http://www.w3.org/1999/xlink","href",o),a.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),r.appendChild(a),r},createLabel:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Dr(e,this.config);return $i("span",Object.assign({},t,{class:[t.class,this.config.classNames.hidden].filter(Boolean).join(" ")}),n)},createBadge:function(e){if(Hi.empty(e))return null;var t=$i("span",{class:this.config.classNames.menu.value});return t.appendChild($i("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var n=Object.assign({},t),i=jr(e),r={element:"button",toggle:!1,label:null,icon:null,labelPressed:null,iconPressed:null};switch(["element","icon","label"].forEach(function(e){Object.keys(n).includes(e)&&(r[e]=n[e],delete n[e])}),"button"!==r.element||Object.keys(n).includes("type")||(n.type="button"),Object.keys(n).includes("class")?n.class.includes(this.config.classNames.control)||(n.class+=" ".concat(this.config.classNames.control)):n.class=this.config.classNames.control,e){case"play":r.toggle=!0,r.label="play",r.labelPressed="pause",r.icon="play",r.iconPressed="pause";break;case"mute":r.toggle=!0,r.label="mute",r.labelPressed="unmute",r.icon="volume",r.iconPressed="muted";break;case"captions":r.toggle=!0,r.label="enableCaptions",r.labelPressed="disableCaptions",r.icon="captions-off",r.iconPressed="captions-on";break;case"fullscreen":r.toggle=!0,r.label="enterFullscreen",r.labelPressed="exitFullscreen",r.icon="enter-fullscreen",r.iconPressed="exit-fullscreen";break;case"play-large":n.class+=" ".concat(this.config.classNames.control,"--overlaid"),i="play",r.label="play",r.icon="play";break;default:Hi.empty(r.label)&&(r.label=i),Hi.empty(r.icon)&&(r.icon=e)}var a=$i(r.element);return r.toggle?(a.appendChild(Kr.createIcon.call(this,r.iconPressed,{class:"icon--pressed"})),a.appendChild(Kr.createIcon.call(this,r.icon,{class:"icon--not-pressed"})),a.appendChild(Kr.createLabel.call(this,r.labelPressed,{class:"label--pressed"})),a.appendChild(Kr.createLabel.call(this,r.label,{class:"label--not-pressed"}))):(a.appendChild(Kr.createIcon.call(this,r.icon)),a.appendChild(Kr.createLabel.call(this,r.label))),wr(n,er(this.config.selectors.buttons[i],n)),Gi(a,n),"play"===i?(Hi.array(this.elements.buttons[i])||(this.elements.buttons[i]=[]),this.elements.buttons[i].push(a)):this.elements.buttons[i]=a,a},createRange:function(e,t){var n=$i("input",wr(er(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-label":Dr(e,this.config),"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=n,Kr.updateRangeFill.call(this,n),n},createProgress:function(e,t){var n=$i("progress",wr(er(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){n.appendChild($i("span",null,"0"));var i={played:"played",buffer:"buffered"}[e],r=i?Dr(i,this.config):"";n.innerText="% ".concat(r.toLowerCase())}return this.elements.display[e]=n,n},createTime:function(e){var t=er(this.config.selectors.display[e]),n=$i("div",wr(t,{class:"".concat(this.config.classNames.display.time," ").concat(t.class?t.class:"").trim(),"aria-label":Dr(e,this.config)}),"00:00");return this.elements.display[e]=n,n},bindMenuItemShortcuts:function(e,t){var n=this;Ui(e,"keydown keyup",function(i){if([32,38,39,40].includes(i.which)&&(i.preventDefault(),i.stopPropagation(),"keydown"!==i.type)){var r,a=rr(e,'[role="menuitemradio"]');if(!a&&[32,39].includes(i.which))Kr.showMenuPanel.call(n,t,!0);else 32!==i.which&&(40===i.which||a&&39===i.which?(r=e.nextElementSibling,Hi.element(r)||(r=e.parentNode.firstElementChild)):(r=e.previousElementSibling,Hi.element(r)||(r=e.parentNode.lastElementChild)),sr.call(n,r,!0))}},!1),Ui(e,"keyup",function(e){13===e.which&&Kr.focusFirstMenuItem.call(n,null,!0)})},createMenuItem:function(e){var t=this,n=e.value,i=e.list,r=e.type,a=e.title,o=e.badge,s=void 0===o?null:o,l=e.checked,c=void 0!==l&&l,u=er(this.config.selectors.inputs[r]),h=$i("button",wr(u,{type:"button",role:"menuitemradio",class:"".concat(this.config.classNames.control," ").concat(u.class?u.class:"").trim(),"aria-checked":c,value:n})),d=$i("span");d.innerHTML=a,Hi.element(s)&&d.appendChild(s),h.appendChild(d),Object.defineProperty(h,"checked",{enumerable:!0,get:function(){return"true"===h.getAttribute("aria-checked")},set:function(e){e&&Array.from(h.parentNode.children).filter(function(e){return rr(e,'[role="menuitemradio"]')}).forEach(function(e){return e.setAttribute("aria-checked","false")}),h.setAttribute("aria-checked",e?"true":"false")}}),this.listeners.bind(h,"click keyup",function(e){if(!Hi.keyboardEvent(e)||32===e.which){switch(e.preventDefault(),e.stopPropagation(),h.checked=!0,r){case"language":t.currentTrack=Number(n);break;case"quality":t.quality=n;break;case"speed":t.speed=parseFloat(n)}Kr.showMenuPanel.call(t,"home",Hi.keyboardEvent(e))}},r,!1),Kr.bindMenuItemShortcuts.call(this,h,r),i.appendChild(h)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return Hi.number(e)?zr(e,Br(this.duration)>0,t):e},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];Hi.element(e)&&Hi.number(t)&&(e.innerText=Kr.formatTime(t,n))},updateVolume:function(){this.supported.ui&&(Hi.element(this.elements.inputs.volume)&&Kr.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),Hi.element(this.elements.buttons.mute)&&(this.elements.buttons.mute.pressed=this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;Hi.element(e)&&(e.value=t,Kr.updateRangeFill.call(this,e))},updateProgress:function(e){var t=this;if(this.supported.ui&&Hi.event(e)){var n,i,r=0;if(e)switch(e.type){case"timeupdate":case"seeking":case"seeked":n=this.currentTime,i=this.duration,r=0===n||0===i||Number.isNaN(n)||Number.isNaN(i)?0:(n/i*100).toFixed(2),"timeupdate"===e.type&&Kr.setRange.call(this,this.elements.inputs.seek,r);break;case"playing":case"progress":!function(e,n){var i=Hi.number(n)?n:0,r=Hi.element(e)?e:t.elements.display.buffer;if(Hi.element(r)){r.value=i;var a=r.getElementsByTagName("span")[0];Hi.element(a)&&(a.childNodes[0].nodeValue=i)}}(this.elements.display.buffer,100*this.buffered)}}},updateRangeFill:function(e){var t=Hi.event(e)?e.target:e;if(Hi.element(t)&&"range"===t.getAttribute("type")){if(rr(t,this.config.selectors.inputs.seek)){t.setAttribute("aria-valuenow",this.currentTime);var n=Kr.formatTime(this.currentTime),i=Kr.formatTime(this.duration),r=Dr("seekLabel",this.config);t.setAttribute("aria-valuetext",r.replace("{currentTime}",n).replace("{duration}",i))}else if(rr(t,this.config.selectors.inputs.volume)){var a=100*t.value;t.setAttribute("aria-valuenow",a),t.setAttribute("aria-valuetext","".concat(a.toFixed(1),"%"))}else t.setAttribute("aria-valuenow",t.value);pr.isWebkit&&t.style.setProperty("--value","".concat(t.value/t.max*100,"%"))}},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&Hi.element(this.elements.inputs.seek)&&Hi.element(this.elements.display.seekTooltip)&&0!==this.duration){var n=0,i=this.elements.progress.getBoundingClientRect(),r="".concat(this.config.classNames.tooltip,"--visible"),a=function(e){nr(t.elements.display.seekTooltip,r,e)};if(this.touch)a(!1);else{if(Hi.event(e))n=100/i.width*(e.pageX-i.left);else{if(!ir(this.elements.display.seekTooltip,r))return;n=parseFloat(this.elements.display.seekTooltip.style.left,10)}n<0?n=0:n>100&&(n=100),Kr.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*n),this.elements.display.seekTooltip.style.left="".concat(n,"%"),Hi.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&a("mouseenter"===e.type)}}},timeUpdate:function(e){var t=!Hi.element(this.elements.display.duration)&&this.config.invertTime;Kr.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||Kr.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui&&(this.config.invertTime||!this.currentTime)){if(this.duration>=Math.pow(2,32))return tr(this.elements.display.currentTime,!0),void tr(this.elements.progress,!0);Hi.element(this.elements.inputs.seek)&&this.elements.inputs.seek.setAttribute("aria-valuemax",this.duration);var e=Hi.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&Kr.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&Kr.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),Kr.updateSeekTooltip.call(this)}},toggleMenuButton:function(e,t){tr(this.elements.settings.buttons[e],!t)},updateSetting:function(e,t,n){var i=this.elements.settings.panels[e],r=null,a=t;if("captions"===e)r=this.currentTrack;else{if(r=Hi.empty(n)?this[e]:n,Hi.empty(r)&&(r=this.config[e].default),!Hi.empty(this.options[e])&&!this.options[e].includes(r))return void this.debug.warn("Unsupported value of '".concat(r,"' for ").concat(e));if(!this.config[e].options.includes(r))return void this.debug.warn("Disabled value of '".concat(r,"' for ").concat(e))}if(Hi.element(a)||(a=i&&i.querySelector('[role="menu"]')),Hi.element(a)){this.elements.settings.buttons[e].querySelector(".".concat(this.config.classNames.menu.value)).innerHTML=Kr.getLabel.call(this,e,r);var o=a&&a.querySelector('[value="'.concat(r,'"]'));Hi.element(o)&&(o.checked=!0)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?Dr("normal",this.config):"".concat(t,"×");case"quality":if(Hi.number(t)){var n=Dr("qualityLabel.".concat(t),this.config);return n.length?n:"".concat(t,"p")}return Or(t);case"captions":return $r.getLabel.call(this);default:return null}},setQualityMenu:function(e){var t=this;if(Hi.element(this.elements.settings.panels.quality)){var n=this.elements.settings.panels.quality.querySelector('[role="menu"]');Hi.array(e)&&(this.options.quality=yr(e).filter(function(e){return t.config.quality.options.includes(e)}));var i=!Hi.empty(this.options.quality)&&this.options.quality.length>1;if(Kr.toggleMenuButton.call(this,"quality",i),Ji(n),Kr.checkMenu.call(this),i){var r=function(e){var n=Dr("qualityBadge.".concat(e),t.config);return n.length?Kr.createBadge.call(t,n):null};this.options.quality.sort(function(e,n){var i=t.config.quality.options;return i.indexOf(e)>i.indexOf(n)?1:-1}).forEach(function(e){Kr.createMenuItem.call(t,{value:e,list:n,type:"quality",title:Kr.getLabel.call(t,"quality",e),badge:r(e)})}),Kr.updateSetting.call(this,"quality",n)}}},setCaptionsMenu:function(){var e=this;if(Hi.element(this.elements.settings.panels.captions)){var t=this.elements.settings.panels.captions.querySelector('[role="menu"]'),n=$r.getTracks.call(this),i=Boolean(n.length);if(Kr.toggleMenuButton.call(this,"captions",i),Ji(t),Kr.checkMenu.call(this),i){var r=n.map(function(n,i){return{value:i,checked:e.captions.toggled&&e.currentTrack===i,title:$r.getLabel.call(e,n),badge:n.language&&Kr.createBadge.call(e,n.language.toUpperCase()),list:t,type:"language"}});r.unshift({value:-1,checked:!this.captions.toggled,title:Dr("disabled",this.config),list:t,type:"language"}),r.forEach(Kr.createMenuItem.bind(this)),Kr.updateSetting.call(this,"captions",t)}}},setSpeedMenu:function(e){var t=this;if(Hi.element(this.elements.settings.panels.speed)){var n=this.elements.settings.panels.speed.querySelector('[role="menu"]');Hi.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var i=!Hi.empty(this.options.speed)&&this.options.speed.length>1;Kr.toggleMenuButton.call(this,"speed",i),Ji(n),Kr.checkMenu.call(this),i&&(this.options.speed.forEach(function(e){Kr.createMenuItem.call(t,{value:e,list:n,type:"speed",title:Kr.getLabel.call(t,"speed",e)})}),Kr.updateSetting.call(this,"speed",n))}},checkMenu:function(){var e=this.elements.settings.buttons,t=!Hi.empty(e)&&Object.values(e).some(function(e){return!e.hidden});tr(this.elements.settings.menu,!t)},focusFirstMenuItem:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!this.elements.settings.popup.hidden){var n=e;Hi.element(n)||(n=Object.values(this.elements.settings.panels).find(function(e){return!e.hidden}));var i=n.querySelector('[role^="menuitem"]');sr.call(this,i,t)}},toggleMenu:function(e){var t=this.elements.settings.popup,n=this.elements.buttons.settings;if(Hi.element(t)&&Hi.element(n)){var i=t.hidden,r=i;if(Hi.boolean(e))r=e;else if(Hi.keyboardEvent(e)&&27===e.which)r=!1;else if(Hi.event(e)){var a=t.contains(e.target);if(a||!a&&e.target!==n&&r)return}n.setAttribute("aria-expanded",r),tr(t,!r),nr(this.elements.container,this.config.classNames.menu.open,r),r&&Hi.keyboardEvent(e)?Kr.focusFirstMenuItem.call(this,null,!0):r||i||sr.call(this,n,Hi.keyboardEvent(e))}},getMenuSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),e.parentNode.appendChild(t);var n=t.scrollWidth,i=t.scrollHeight;return Xi(t),{width:n,height:i}},showMenuPanel:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=document.getElementById("plyr-settings-".concat(this.id,"-").concat(t));if(Hi.element(i)){var r=i.parentNode,a=Array.from(r.children).find(function(e){return!e.hidden});if(gr.transitions&&!gr.reducedMotion){r.style.width="".concat(a.scrollWidth,"px"),r.style.height="".concat(a.scrollHeight,"px");var o=Kr.getMenuSize.call(this,i);Ui.call(this,r,hr,function t(n){n.target===r&&["width","height"].includes(n.propertyName)&&(r.style.width="",r.style.height="",Wi.call(e,r,hr,t))}),r.style.width="".concat(o.width,"px"),r.style.height="".concat(o.height,"px")}tr(a,!0),tr(i,!1),Kr.focusFirstMenuItem.call(this,i,n)}},setDownloadLink:function(){var e=this.elements.buttons.download;Hi.element(e)&&e.setAttribute("href",this.download)},create:function(e){var t=this,n=$i("div",er(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&n.appendChild(Kr.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&n.appendChild(Kr.createButton.call(this,"rewind")),this.config.controls.includes("play")&&n.appendChild(Kr.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&n.appendChild(Kr.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var i=$i("div",er(this.config.selectors.progress));if(i.appendChild(Kr.createRange.call(this,"seek",{id:"plyr-seek-".concat(e.id)})),i.appendChild(Kr.createProgress.call(this,"buffer")),this.config.tooltips.seek){var r=$i("span",{class:this.config.classNames.tooltip},"00:00");i.appendChild(r),this.elements.display.seekTooltip=r}this.elements.progress=i,n.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&n.appendChild(Kr.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&n.appendChild(Kr.createTime.call(this,"duration")),this.config.controls.includes("mute")||this.config.controls.includes("volume")){var a=$i("div",{class:"plyr__volume"});if(this.config.controls.includes("mute")&&a.appendChild(Kr.createButton.call(this,"mute")),this.config.controls.includes("volume")){var o={max:1,step:.05,value:this.config.volume};a.appendChild(Kr.createRange.call(this,"volume",wr(o,{id:"plyr-volume-".concat(e.id)}))),this.elements.volume=a}n.appendChild(a)}if(this.config.controls.includes("captions")&&n.appendChild(Kr.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!Hi.empty(this.config.settings)){var s=$i("div",{class:"plyr__menu",hidden:""});s.appendChild(Kr.createButton.call(this,"settings",{"aria-haspopup":!0,"aria-controls":"plyr-settings-".concat(e.id),"aria-expanded":!1}));var l=$i("div",{class:"plyr__menu__container",id:"plyr-settings-".concat(e.id),hidden:""}),c=$i("div"),u=$i("div",{id:"plyr-settings-".concat(e.id,"-home")}),h=$i("div",{role:"menu"});u.appendChild(h),c.appendChild(u),this.elements.settings.panels.home=u,this.config.settings.forEach(function(n){var i=$i("button",wr(er(t.config.selectors.buttons.settings),{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--forward"),role:"menuitem","aria-haspopup":!0,hidden:""}));Kr.bindMenuItemShortcuts.call(t,i,n),Ui(i,"click",function(){Kr.showMenuPanel.call(t,n,!1)});var r=$i("span",null,Dr(n,t.config)),a=$i("span",{class:t.config.classNames.menu.value});a.innerHTML=e[n],r.appendChild(a),i.appendChild(r),h.appendChild(i);var o=$i("div",{id:"plyr-settings-".concat(e.id,"-").concat(n),hidden:""}),s=$i("button",{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--back")});s.appendChild($i("span",{"aria-hidden":!0},Dr(n,t.config))),s.appendChild($i("span",{class:t.config.classNames.hidden},Dr("menuBack",t.config))),Ui(o,"keydown",function(e){37===e.which&&(e.preventDefault(),e.stopPropagation(),Kr.showMenuPanel.call(t,"home",!0))},!1),Ui(s,"click",function(){Kr.showMenuPanel.call(t,"home",!1)}),o.appendChild(s),o.appendChild($i("div",{role:"menu"})),c.appendChild(o),t.elements.settings.buttons[n]=i,t.elements.settings.panels[n]=o}),l.appendChild(c),s.appendChild(l),n.appendChild(s),this.elements.settings.popup=l,this.elements.settings.menu=s}if(this.config.controls.includes("pip")&&gr.pip&&n.appendChild(Kr.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&gr.airplay&&n.appendChild(Kr.createButton.call(this,"airplay")),this.config.controls.includes("download")){var d={element:"a",href:this.download,target:"_blank"},f=this.config.urls.download;!Hi.url(f)&&this.isEmbed&&wr(d,{icon:"logo-".concat(this.provider),label:this.provider}),n.appendChild(Kr.createButton.call(this,"download",d))}return this.config.controls.includes("fullscreen")&&n.appendChild(Kr.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(Kr.createButton.call(this,"play-large")),this.elements.controls=n,this.isHTML5&&Kr.setQualityMenu.call(this,vr.getQualityOptions.call(this)),Kr.setSpeedMenu.call(this),n},inject:function(){var e=this;if(this.config.loadSprite){var t=Kr.getIconUrl.call(this);t.cors&&Vr(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var n=null;this.elements.controls=null;var i={id:this.id,seektime:this.config.seekTime,title:this.config.title},r=!0;Hi.function(this.config.controls)&&(this.config.controls=this.config.controls.call(this,i)),this.config.controls||(this.config.controls=[]),Hi.element(this.config.controls)||Hi.string(this.config.controls)?n=this.config.controls:(n=Kr.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:$r.getLabel.call(this)}),r=!1);var a,o=function(e){var t=e;return Object.entries(i).forEach(function(e){var n=gn(e,2),i=n[0],r=n[1];t=Lr(t,"{".concat(i,"}"),r)}),t};if(r&&(Hi.string(this.config.controls)?n=o(n):Hi.element(n)&&(n.innerHTML=o(n.innerHTML))),Hi.string(this.config.selectors.controls.container)&&(a=document.querySelector(this.config.selectors.controls.container)),Hi.element(a)||(a=this.elements.container),a[Hi.element(n)?"insertAdjacentElement":"insertAdjacentHTML"]("afterbegin",n),Hi.element(this.elements.controls)||Kr.findElements.call(this),!Hi.empty(this.elements.buttons)){var s=function(t){var n=e.config.classNames.controlPressed;Object.defineProperty(t,"pressed",{enumerable:!0,get:function(){return ir(t,n)},set:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];nr(t,n,e)}})};Object.values(this.elements.buttons).filter(Boolean).forEach(function(e){Hi.array(e)||Hi.nodeList(e)?Array.from(e).filter(Boolean).forEach(s):s(e)})}if(pr.isEdge&&dr(a),this.config.tooltips.controls){var l=this.config,c=l.classNames,u=l.selectors,h="".concat(u.controls.wrapper," ").concat(u.labels," .").concat(c.hidden),d=ar.call(this,h);Array.from(d).forEach(function(t){nr(t,e.config.classNames.hidden,!1),nr(t,e.config.classNames.tooltip,!0)})}}};function Yr(e){var t=e;if(!(arguments.length>1&&void 0!==arguments[1])||arguments[1]){var n=document.createElement("a");n.href=t,t=n.href}try{return new URL(t)}catch(e){return null}}function Gr(e){var t=new URLSearchParams;return Hi.object(e)&&Object.entries(e).forEach(function(e){var n=gn(e,2),i=n[0],r=n[1];t.set(i,r)}),t}var $r={setup:function(){if(this.supported.ui)if(!this.isVideo||this.isYouTube||this.isHTML5&&!gr.textTracks)Hi.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&Kr.setCaptionsMenu.call(this);else{var e,t;if(Hi.element(this.elements.captions)||(this.elements.captions=$i("div",er(this.config.selectors.captions)),e=this.elements.captions,t=this.elements.wrapper,Hi.element(e)&&Hi.element(t)&&t.parentNode.insertBefore(e,t.nextSibling)),pr.isIE&&window.URL){var n=this.media.querySelectorAll("track");Array.from(n).forEach(function(e){var t=e.getAttribute("src"),n=Yr(t);null!==n&&n.hostname!==window.location.href.hostname&&["http:","https:"].includes(n.protocol)&&Hr(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){Xi(e)})})}var i=yr((navigator.languages||[navigator.language||navigator.userLanguage||"en"]).map(function(e){return e.split("-")[0]})),r=(this.storage.get("language")||this.config.captions.language||"auto").toLowerCase();if("auto"===r)r=gn(i,1)[0];var a=this.storage.get("captions");if(Hi.boolean(a)||(a=this.config.captions.active),Object.assign(this.captions,{toggled:!1,active:a,language:r,languages:i}),this.isHTML5){var o=this.config.captions.update?"addtrack removetrack":"removetrack";Ui.call(this,this.media.textTracks,o,$r.update.bind(this))}setTimeout($r.update.bind(this),0)}},update:function(){var e=this,t=$r.getTracks.call(this,!0),n=this.captions,i=n.active,r=n.language,a=n.meta,o=n.currentTrackNode,s=Boolean(t.find(function(e){return e.language===r}));this.isHTML5&&this.isVideo&&t.filter(function(e){return!a.get(e)}).forEach(function(t){e.debug.log("Track added",t),a.set(t,{default:"showing"===t.mode}),t.mode="hidden",Ui.call(e,t,"cuechange",function(){return $r.updateCues.call(e)})}),(s&&this.language!==r||!t.includes(o))&&($r.setLanguage.call(this,r),$r.toggle.call(this,i&&s)),nr(this.elements.container,this.config.classNames.captions.enabled,!Hi.empty(t)),(this.config.controls||[]).includes("settings")&&this.config.settings.includes("captions")&&Kr.setCaptionsMenu.call(this)},toggle:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.supported.ui){var n=this.captions.toggled,i=this.config.classNames.captions.active,r=Hi.nullOrUndefined(e)?!n:e;if(r!==n){if(t||(this.captions.active=r,this.storage.set({captions:r})),!this.language&&r&&!t){var a=$r.getTracks.call(this),o=$r.findTrack.call(this,[this.captions.language].concat(vn(this.captions.languages)),!0);return this.captions.language=o.language,void $r.set.call(this,a.indexOf(o))}this.elements.buttons.captions&&(this.elements.buttons.captions.pressed=r),nr(this.elements.container,i,r),this.captions.toggled=r,Kr.updateSetting.call(this,"captions"),Ki.call(this,this.media,r?"captionsenabled":"captionsdisabled")}}},set:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=$r.getTracks.call(this);if(-1!==e)if(Hi.number(e))if(e in n){if(this.captions.currentTrack!==e){this.captions.currentTrack=e;var i=n[e],r=(i||{}).language;this.captions.currentTrackNode=i,Kr.updateSetting.call(this,"captions"),t||(this.captions.language=r,this.storage.set({language:r})),this.isVimeo&&this.embed.enableTextTrack(r),Ki.call(this,this.media,"languagechange")}$r.toggle.call(this,!0,t),this.isHTML5&&this.isVideo&&$r.updateCues.call(this)}else this.debug.warn("Track not found",e);else this.debug.warn("Invalid caption argument",e);else $r.toggle.call(this,!1,t)},setLanguage:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(Hi.string(e)){var n=e.toLowerCase();this.captions.language=n;var i=$r.getTracks.call(this),r=$r.findTrack.call(this,[n]);$r.set.call(this,i.indexOf(r),t)}else this.debug.warn("Invalid language argument",e)},getTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Array.from((this.media||{}).textTracks||[]).filter(function(n){return!e.isHTML5||t||e.captions.meta.has(n)}).filter(function(e){return["captions","subtitles"].includes(e.kind)})},findTrack:function(e){var t,n=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=$r.getTracks.call(this),a=function(e){return Number((n.captions.meta.get(e)||{}).default)},o=Array.from(r).sort(function(e,t){return a(t)-a(e)});return e.every(function(e){return!(t=o.find(function(t){return t.language===e}))}),t||(i?o[0]:void 0)},getCurrentTrack:function(){return $r.getTracks.call(this)[this.currentTrack]},getLabel:function(e){var t=e;return!Hi.track(t)&&gr.textTracks&&this.captions.toggled&&(t=$r.getCurrentTrack.call(this)),Hi.track(t)?Hi.empty(t.label)?Hi.empty(t.language)?Dr("enabled",this.config):e.language.toUpperCase():t.label:Dr("disabled",this.config)},updateCues:function(e){if(this.supported.ui)if(Hi.element(this.elements.captions))if(Hi.nullOrUndefined(e)||Array.isArray(e)){var t=e;if(!t){var n=$r.getCurrentTrack.call(this);t=Array.from((n||{}).activeCues||[]).map(function(e){return e.getCueAsHTML()}).map(Rr)}var i=t.map(function(e){return e.trim()}).join("\n");if(i!==this.elements.captions.innerHTML){Ji(this.elements.captions);var r=$i("span",er(this.config.selectors.caption));r.innerHTML=i,this.elements.captions.appendChild(r),Ki.call(this,this.media,"cuechange")}}else this.debug.warn("updateCues: Invalid input",e);else this.debug.warn("No captions element to render to")}},Qr={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,playsinline:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.4.8/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:"auto",update:!1},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",seekLabel:"{currentTime} of {duration}",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",download:"Download",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",menuBack:"Go back to previous menu",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad",qualityBadge:{2160:"4K",1440:"HD",1080:"HD",720:"HD",576:"SD",480:"SD"}},urls:{download:null,vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,download:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","download","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',download:'[data-plyr="download"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress__buffer",loop:".plyr__progress__loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",caption:".plyr__caption",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",posterEnabled:"plyr__poster-enabled",ads:"plyr__ads",control:"plyr__control",controlPressed:"plyr__control--pressed",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",display:{time:"plyr__time"},menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus",previewThumbnails:{thumbContainer:"plyr__preview-thumb",thumbContainerShown:"plyr__preview-thumb--is-shown",imageContainer:"plyr__preview-thumb__image-container",timeContainer:"plyr__preview-thumb__time-container",scrubbingContainer:"plyr__preview-scrubbing",scrubbingContainerShown:"plyr__preview-scrubbing--is-shown"}},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:"",tagUrl:""},previewThumbnails:{enabled:!1,src:""},vimeo:{byline:!1,portrait:!1,title:!1,speed:!0,transparent:!1},youtube:{noCookie:!1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1}},Xr="picture-in-picture",Jr="inline",Zr={html5:"html5",youtube:"youtube",vimeo:"vimeo"},ea={audio:"audio",video:"video"};var ta=function(){},na=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];dn(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return pn(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):ta}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):ta}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):ta}}]),e}();function ia(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;Hi.element(e)&&(e.pressed=this.active),Ki.call(this.player,this.target,this.active?"enterfullscreen":"exitfullscreen",!0),pr.isIos||function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(Hi.element(e)){var n=ar.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=n[0],r=n[n.length-1];Bi.call(this,this.elements.container,"keydown",function(e){if("Tab"===e.key&&9===e.keyCode){var t=document.activeElement;t!==r||e.shiftKey?t===i&&e.shiftKey&&(r.focus(),e.preventDefault()):(i.focus(),e.preventDefault())}},t,!1)}}.call(this.player,this.target,this.active)}}function ra(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(t?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=t?"hidden":"",nr(this.target,this.player.config.classNames.fullscreen.fallback,t),pr.isIos){var n=document.head.querySelector('meta[name="viewport"]'),i="viewport-fit=cover";n||(n=document.createElement("meta")).setAttribute("name","viewport");var r=Hi.string(n.content)&&n.content.includes(i);t?(this.cleanupViewport=!r,r||(n.content+=",".concat(i))):this.cleanupViewport&&(n.content=n.content.split(",").filter(function(e){return e.trim()!==i}).join(",")),setTimeout(function(){return dr(e.target)},100)}ia.call(this)}var aa=function(){function e(t){var n=this;dn(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},this.forceFallback="force"===t.config.fullscreen.fallback,Ui.call(this.player,document,"ms"===this.prefix?"MSFullscreenChange":"".concat(this.prefix,"fullscreenchange"),function(){ia.call(n)}),Ui.call(this.player,this.player.elements.container,"dblclick",function(e){Hi.element(n.player.elements.controls)&&n.player.elements.controls.contains(e.target)||n.toggle()}),this.update()}return pn(e,[{key:"update",value:function(){var t;this.enabled?(t=this.forceFallback?"Fallback (forced)":e.native?"Native":"Fallback",this.player.debug.log("".concat(t," fullscreen enabled"))):this.player.debug.log("Fullscreen not supported and fallback disabled");nr(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(pr.isIos&&this.player.config.fullscreen.iosNative?this.target.webkitEnterFullscreen():!e.native||this.forceFallback?ra.call(this,!0):this.prefix?Hi.empty(this.prefix)||this.target["".concat(this.prefix,"Request").concat(this.property)]():this.target.requestFullscreen())}},{key:"exit",value:function(){if(this.enabled)if(pr.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(!e.native||this.forceFallback)ra.call(this,!1);else if(this.prefix){if(!Hi.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document["".concat(this.prefix).concat(t).concat(this.property)]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"usingNative",get:function(){return e.native&&!this.forceFallback}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(!e.native||this.forceFallback?ir(this.target,this.player.config.classNames.fullscreen.fallback):(this.prefix?document["".concat(this.prefix).concat(this.property,"Element")]:document.fullscreenElement)===this.target)}},{key:"target",get:function(){return pr.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(Hi.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!Hi.function(document["".concat(t,"ExitFullscreen")])&&!Hi.function(document["".concat(t,"CancelFullScreen")]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}(),oa=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1};function sa(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return new Promise(function(n,i){var r=new Image,a=function(){delete r.onload,delete r.onerror,(r.naturalWidth>=t?n:i)(r)};Object.assign(r,{onload:a,onerror:a,src:e})})}_(_.S,"Math",{sign:oa});var la={addStyleHook:function(){nr(this.elements.container,this.config.selectors.container.replace(".",""),!0),nr(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for ".concat(this.provider," ").concat(this.type)),void la.toggleNativeControls.call(this,!0);Hi.element(this.elements.controls)||(Kr.inject.call(this),this.listeners.controls()),la.toggleNativeControls.call(this),this.isHTML5&&$r.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,Kr.updateVolume.call(this),Kr.timeUpdate.call(this),la.checkPlaying.call(this),nr(this.elements.container,this.config.classNames.pip.supported,gr.pip&&this.isHTML5&&this.isVideo),nr(this.elements.container,this.config.classNames.airplay.supported,gr.airplay&&this.isHTML5),nr(this.elements.container,this.config.classNames.isIos,pr.isIos),nr(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){Ki.call(e,e.media,"ready")},0),la.setTitle.call(this),this.poster&&la.setPoster.call(this,this.poster,!1).catch(function(){}),this.config.duration&&Kr.durationUpdate.call(this)},setTitle:function(){var e=Dr("play",this.config);if(Hi.string(this.config.title)&&!Hi.empty(this.config.title)&&(e+=", ".concat(this.config.title)),Array.from(this.elements.buttons.play||[]).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=or.call(this,"iframe");if(!Hi.element(t))return;var n=Hi.empty(this.config.title)?"video":this.config.title,i=Dr("frameTitle",this.config);t.setAttribute("title",i.replace("{title}",n))}},togglePoster:function(e){nr(this.elements.container,this.config.classNames.posterEnabled,e)},setPoster:function(e){var t=this;return arguments.length>1&&void 0!==arguments[1]&&!arguments[1]||!this.poster?(this.media.setAttribute("poster",e),function(){var e=this;return new Promise(function(t){return e.ready?setTimeout(t,0):Ui.call(e,e.elements.container,"ready",t)}).then(function(){})}.call(this).then(function(){return sa(e)}).catch(function(n){throw e===t.poster&&la.togglePoster.call(t,!1),n}).then(function(){if(e!==t.poster)throw new Error("setPoster cancelled by later call to setPoster")}).then(function(){return Object.assign(t.elements.poster.style,{backgroundImage:"url('".concat(e,"')"),backgroundSize:""}),la.togglePoster.call(t,!0),e})):Promise.reject(new Error("Poster already set"))},checkPlaying:function(e){var t=this;nr(this.elements.container,this.config.classNames.playing,this.playing),nr(this.elements.container,this.config.classNames.paused,this.paused),nr(this.elements.container,this.config.classNames.stopped,this.stopped),Array.from(this.elements.buttons.play||[]).forEach(function(e){e.pressed=t.playing}),Hi.event(e)&&"timeupdate"===e.type||la.toggleControls.call(this)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){nr(t.elements.container,t.config.classNames.loading,t.loading),la.toggleControls.call(t)},this.loading?250:0)},toggleControls:function(e){var t=this.elements.controls;if(t&&this.config.hideControls){var n=this.touch&&this.lastSeekTime+2e3>Date.now();this.toggleControls(Boolean(e||this.loading||this.paused||t.pressed||t.hover||n))}}};function ca(e){var t=e;Hi.string(t)||Hi.nullOrUndefined(this.embed)||(t=this.embed.ratio),Hi.string(t)||(t=this.config.ratio);var n=gn(t.split(":").map(Number),2),i=100/n[0]*n[1];if(this.elements.wrapper.style.paddingBottom="".concat(i,"%"),this.isVimeo&&this.supported.ui){var r=(240-i)/4.8;this.media.style.transform="translateY(-".concat(r,"%)")}return{padding:i,ratio:t}}var ua=function(){function e(t){dn(this,e),this.player=t,this.lastKey=null,this.focusTimer=null,this.lastKeyDown=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.setTabFocus=this.setTabFocus.bind(this),this.firstTouch=this.firstTouch.bind(this)}return pn(e,[{key:"handleKey",value:function(e){var t=this.player,n=t.elements,i=e.keyCode?e.keyCode:e.which,r="keydown"===e.type,a=r&&i===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&Hi.number(i)){if(r){var o=document.activeElement;if(Hi.element(o)){var s=t.config.selectors.editable;if(o!==n.inputs.seek&&rr(o,s))return;if(32===e.which&&rr(o,'button, [role^="menuitem"]'))return}switch([32,37,38,39,40,48,49,50,51,52,53,54,56,57,67,70,73,75,76,77,79].includes(i)&&(e.preventDefault(),e.stopPropagation()),i){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:a||(t.currentTime=t.duration/10*(i-48));break;case 32:case 75:a||t.togglePlay();break;case 38:t.increaseVolume(.1);break;case 40:t.decreaseVolume(.1);break;case 77:a||(t.muted=!t.muted);break;case 39:t.forward();break;case 37:t.rewind();break;case 70:t.fullscreen.toggle();break;case 67:a||t.toggleCaptions();break;case 76:t.loop=!t.loop}27===i&&!t.fullscreen.usingNative&&t.fullscreen.active&&t.fullscreen.toggle(),this.lastKey=i}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){Kr.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){var e=this.player,t=e.elements;e.touch=!0,nr(t.container,e.config.classNames.isTouch,!0)}},{key:"setTabFocus",value:function(e){var t=this.player,n=t.elements;if(clearTimeout(this.focusTimer),"keydown"!==e.type||9===e.which){"keydown"===e.type&&(this.lastKeyDown=e.timeStamp);var i,r=e.timeStamp-this.lastKeyDown<=20;if("focus"!==e.type||r)i=t.config.classNames.tabFocus,nr(ar.call(t,".".concat(i)),i,!1),this.focusTimer=setTimeout(function(){var e=document.activeElement;n.container.contains(e)&&nr(document.activeElement,t.config.classNames.tabFocus,!0)},10)}}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.player;t.config.keyboard.global&&Bi.call(t,window,"keydown keyup",this.handleKey,e,!1),Bi.call(t,document.body,"click",this.toggleMenu,e),zi.call(t,document.body,"touchstart",this.firstTouch),Bi.call(t,document.body,"keydown focus blur",this.setTabFocus,e,!1,!0)}},{key:"container",value:function(){var e=this.player,t=e.config,n=e.elements,i=e.timers;!t.keyboard.global&&t.keyboard.focused&&Ui.call(e,n.container,"keydown keyup",this.handleKey,!1),Ui.call(e,n.container,"mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",function(t){var r=n.controls;r&&"enterfullscreen"===t.type&&(r.pressed=!1,r.hover=!1);var a=0;["touchstart","touchmove","mousemove"].includes(t.type)&&(la.toggleControls.call(e,!0),a=e.touch?3e3:2e3),clearTimeout(i.controls),i.controls=setTimeout(function(){return la.toggleControls.call(e,!1)},a)});var r=function(t){if(!t)return ca.call(e);var i=n.container.getBoundingClientRect(),r=i.width,a=i.height;return ca.call(e,"".concat(r,":").concat(a))},a=function(){window.clearTimeout(i.resized),i.resized=window.setTimeout(r,50)};Ui.call(e,n.container,"enterfullscreen exitfullscreen",function(t){var i=e.fullscreen,o=i.target,s=i.usingNative;if(e.isEmbed&&o===n.container){var l="enterfullscreen"===t.type,c=r(l);c.padding;!function(t,n,i){if(e.isVimeo){var r=e.elements.wrapper.firstChild,a=gn(t.split(":").map(Number),2)[1],o=gn(e.embed.ratio.split(":").map(Number),2),s=o[0],l=o[1];r.style.maxWidth=i?"".concat(a/l*s,"px"):null,r.style.margin=i?"0 auto":null}}(c.ratio,0,l),s||(l?Ui.call(e,window,"resize",a):Wi.call(e,window,"resize",a))}})}},{key:"media",value:function(){var e=this,t=this.player,n=t.elements;if(Ui.call(t,t.media,"timeupdate seeking seeked",function(e){return Kr.timeUpdate.call(t,e)}),Ui.call(t,t.media,"durationchange loadeddata loadedmetadata",function(e){return Kr.durationUpdate.call(t,e)}),Ui.call(t,t.media,"canplay loadeddata",function(){tr(n.volume,!t.hasAudio),tr(n.buttons.mute,!t.hasAudio)}),Ui.call(t,t.media,"ended",function(){t.isHTML5&&t.isVideo&&t.config.resetOnEnd&&t.restart()}),Ui.call(t,t.media,"progress playing seeking seeked",function(e){return Kr.updateProgress.call(t,e)}),Ui.call(t,t.media,"volumechange",function(e){return Kr.updateVolume.call(t,e)}),Ui.call(t,t.media,"playing play pause ended emptied timeupdate",function(e){return la.checkPlaying.call(t,e)}),Ui.call(t,t.media,"waiting canplay seeked playing",function(e){return la.checkLoading.call(t,e)}),Ui.call(t,t.media,"playing",function(){t.ads&&t.ads.enabled&&!t.ads.initialized&&t.ads.managerPromise.then(function(){return t.ads.play()}).catch(function(){return t.play()})}),t.supported.ui&&t.config.clickToPlay&&!t.isAudio){var i=or.call(t,".".concat(t.config.classNames.video));if(!Hi.element(i))return;Ui.call(t,n.container,"click",function(r){([n.container,i].includes(r.target)||i.contains(r.target))&&(t.touch&&t.config.hideControls||(t.ended?(e.proxy(r,t.restart,"restart"),e.proxy(r,t.play,"play")):e.proxy(r,t.togglePlay,"play")))})}t.supported.ui&&t.config.disableContextMenu&&Ui.call(t,n.wrapper,"contextmenu",function(e){e.preventDefault()},!1),Ui.call(t,t.media,"volumechange",function(){t.storage.set({volume:t.volume,muted:t.muted})}),Ui.call(t,t.media,"ratechange",function(){Kr.updateSetting.call(t,"speed"),t.storage.set({speed:t.speed})}),Ui.call(t,t.media,"qualitychange",function(e){Kr.updateSetting.call(t,"quality",null,e.detail.quality)}),Ui.call(t,t.media,"ready qualitychange",function(){Kr.setDownloadLink.call(t)});var r=t.config.events.concat(["keyup","keydown"]).join(" ");Ui.call(t,t.media,r,function(e){var i=e.detail,r=void 0===i?{}:i;"error"===e.type&&(r=t.media.error),Ki.call(t,n.container,e.type,!0,r)})}},{key:"proxy",value:function(e,t,n){var i=this.player,r=i.config.listeners[n],a=!0;Hi.function(r)&&(a=r.call(i,e)),a&&Hi.function(t)&&t.call(i,e)}},{key:"bind",value:function(e,t,n,i){var r=this,a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=this.player,s=o.config.listeners[i],l=Hi.function(s);Ui.call(o,e,t,function(e){return r.proxy(e,n,i)},a&&!l)}},{key:"controls",value:function(){var e=this,t=this.player,n=t.elements,i=pr.isIE?"change":"input";if(n.buttons.play&&Array.from(n.buttons.play).forEach(function(n){e.bind(n,"click",t.togglePlay,"play")}),this.bind(n.buttons.restart,"click",t.restart,"restart"),this.bind(n.buttons.rewind,"click",t.rewind,"rewind"),this.bind(n.buttons.fastForward,"click",t.forward,"fastForward"),this.bind(n.buttons.mute,"click",function(){t.muted=!t.muted},"mute"),this.bind(n.buttons.captions,"click",function(){return t.toggleCaptions()}),this.bind(n.buttons.download,"click",function(){Ki.call(t,t.media,"download")},"download"),this.bind(n.buttons.fullscreen,"click",function(){t.fullscreen.toggle()},"fullscreen"),this.bind(n.buttons.pip,"click",function(){t.pip="toggle"},"pip"),this.bind(n.buttons.airplay,"click",t.airplay,"airplay"),this.bind(n.buttons.settings,"click",function(e){e.stopPropagation(),Kr.toggleMenu.call(t,e)}),this.bind(n.buttons.settings,"keyup",function(e){var n=e.which;[13,32].includes(n)&&(13!==n?(e.preventDefault(),e.stopPropagation(),Kr.toggleMenu.call(t,e)):Kr.focusFirstMenuItem.call(t,null,!0))},null,!1),this.bind(n.settings.menu,"keydown",function(e){27===e.which&&Kr.toggleMenu.call(t,e)}),this.bind(n.inputs.seek,"mousedown mousemove",function(e){var t=n.progress.getBoundingClientRect(),i=100/t.width*(e.pageX-t.left);e.currentTarget.setAttribute("seek-value",i)}),this.bind(n.inputs.seek,"mousedown mouseup keydown keyup touchstart touchend",function(e){var n=e.currentTarget,i=e.keyCode?e.keyCode:e.which;if(!Hi.keyboardEvent(e)||39===i||37===i){t.lastSeekTime=Date.now();var r=n.hasAttribute("play-on-seeked"),a=["mouseup","touchend","keyup"].includes(e.type);r&&a?(n.removeAttribute("play-on-seeked"),t.play()):!a&&t.playing&&(n.setAttribute("play-on-seeked",""),t.pause())}}),pr.isIos){var r=ar.call(t,'input[type="range"]');Array.from(r).forEach(function(t){return e.bind(t,i,function(e){return dr(e.target)})})}this.bind(n.inputs.seek,i,function(e){var n=e.currentTarget,i=n.getAttribute("seek-value");Hi.empty(i)&&(i=n.value),n.removeAttribute("seek-value"),t.currentTime=i/n.max*t.duration},"seek"),this.bind(n.progress,"mouseenter mouseleave mousemove",function(e){return Kr.updateSeekTooltip.call(t,e)}),this.bind(n.progress,"mousemove touchmove",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startMove(e)}),this.bind(n.progress,"mouseleave click",function(){var e=t.previewThumbnails;e&&e.loaded&&e.endMove(!1,!0)}),this.bind(n.progress,"mousedown touchstart",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startScrubbing(e)}),this.bind(n.progress,"mouseup touchend",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.endScrubbing(e)}),pr.isWebkit&&Array.from(ar.call(t,'input[type="range"]')).forEach(function(n){e.bind(n,"input",function(e){return Kr.updateRangeFill.call(t,e.target)})}),t.config.toggleInvert&&!Hi.element(n.display.duration)&&this.bind(n.display.currentTime,"click",function(){0!==t.currentTime&&(t.config.invertTime=!t.config.invertTime,Kr.timeUpdate.call(t))}),this.bind(n.inputs.volume,i,function(e){t.volume=e.target.value},"volume"),this.bind(n.controls,"mouseenter mouseleave",function(e){n.controls.hover=!t.touch&&"mouseenter"===e.type}),this.bind(n.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){n.controls.pressed=["mousedown","touchstart"].includes(e.type)}),this.bind(n.controls,"focusin",function(){var n=t.config,i=t.elements,r=t.timers;nr(i.controls,n.classNames.noTransition,!0),la.toggleControls.call(t,!0),setTimeout(function(){nr(i.controls,n.classNames.noTransition,!1)},0);var a=e.touch?3e3:4e3;clearTimeout(r.controls),r.controls=setTimeout(function(){return la.toggleControls.call(t,!1)},a)}),this.bind(n.inputs.volume,"wheel",function(e){var n=e.webkitDirectionInvertedFromDevice,i=gn([e.deltaX,-e.deltaY].map(function(e){return n?-e:e}),2),r=i[0],a=i[1],o=Math.sign(Math.abs(r)>Math.abs(a)?r:a);t.increaseVolume(o/50);var s=t.media.volume;(1===o&&s<1||-1===o&&s>0)&&e.preventDefault()},"volume",!1)}}]),e}(),ha=g.f,da=Function.prototype,fa=/^\s*function ([^ (]*)/;"name"in da||c&&ha(da,"name",{configurable:!0,get:function(){try{return(""+this).match(fa)[1]}catch(e){return""}}}),bt("match",1,function(e,t,n,i){return[function(n){var i=e(this),r=null==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},function(e){var t=i(n,e,this);if(t.done)return t.value;var r=s(e),a=String(this);if(!r.global)return lt(r,a);var o=r.unicode;r.lastIndex=0;for(var l,c=[],u=0;null!==(l=lt(r,a));){var h=String(l[0]);c[u]=h,""===h&&(r.lastIndex=An(a,H(r.lastIndex),o)),u++}return 0===u?null:c}]});var pa=t(function(e,t){e.exports=function(){var e=function(){},t={},n={},i={};function r(e,t){if(e){var r=i[e];if(n[e]=t,r)for(;r.length;)r[0](e,t),r.splice(0,1)}}function a(t,n){t.call&&(t={success:t}),n.length?(t.error||e)(n):(t.success||e)(t)}function o(t,n,i,r){var a,s,l=document,c=i.async,u=(i.numRetries||0)+1,h=i.before||e,d=t.replace(/^(css|img)!/,"");r=r||0,/(^css!|\.css$)/.test(t)?(a=!0,(s=l.createElement("link")).rel="stylesheet",s.href=d):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(s=l.createElement("img")).src=d:((s=l.createElement("script")).src=t,s.async=void 0===c||c),s.onload=s.onerror=s.onbeforeload=function(e){var l=e.type[0];if(a&&"hideFocus"in s)try{s.sheet.cssText.length||(l="e")}catch(e){18!=e.code&&(l="e")}if("e"==l&&(r+=1)<u)return o(t,n,i,r);n(t,l,e.defaultPrevented)},!1!==h(t,s)&&l.head.appendChild(s)}function s(e,n,i){var s,l;if(n&&n.trim&&(s=n),l=(s?i:n)||{},s){if(s in t)throw"LoadJS";t[s]=!0}!function(e,t,n){var i,r,a=(e=e.push?e:[e]).length,s=a,l=[];for(i=function(e,n,i){if("e"==n&&l.push(e),"b"==n){if(!i)return;l.push(e)}--a||t(l)},r=0;r<s;r++)o(e[r],i,n)}(e,function(e){a(l,e),r(s,e)},l)}return s.ready=function(e,t){return function(e,t){e=e.push?e:[e];var r,a,o,s=[],l=e.length,c=l;for(r=function(e,n){n.length&&s.push(e),--c||t(s)};l--;)a=e[l],(o=n[a])?r(a,o):(i[a]=i[a]||[]).push(r)}(e,function(e){a(t,e)}),s},s.done=function(e){r(e,[])},s.reset=function(){t={},n={},i={}},s.isDefined=function(e){return e in t},s}()});function ma(e){return new Promise(function(t,n){pa(e,{success:t,error:n})})}function ga(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,Ki.call(this,this.media,e?"play":"pause"))}var va={setup:function(){var e=this;nr(this.elements.wrapper,this.config.classNames.embed,!0),ca.call(this),Hi.object(window.Vimeo)?va.ready.call(this):ma(this.config.urls.vimeo.sdk).then(function(){va.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},ready:function(){var e=this,t=this,n=t.config.vimeo,i=Gr(wr({},{loop:t.config.loop.active,autoplay:t.autoplay,muted:t.muted,gesture:"media",playsinline:!this.config.fullscreen.iosNative},n)),r=t.media.getAttribute("src");Hi.empty(r)&&(r=t.media.getAttribute(t.config.attributes.embed.id));var a,o=(a=r,Hi.empty(a)?null:Hi.number(Number(a))?a:a.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:a),s=$i("iframe"),l=Nr(t.config.urls.vimeo.iframe,o,i);s.setAttribute("src",l),s.setAttribute("allowfullscreen",""),s.setAttribute("allowtransparency",""),s.setAttribute("allow","autoplay");var c=$i("div",{poster:t.poster,class:t.config.classNames.embedContainer});c.appendChild(s),t.media=Zi(c,t.media),Hr(Nr(t.config.urls.vimeo.api,o),"json").then(function(e){if(!Hi.empty(e)){var n=new URL(e[0].thumbnail_large);n.pathname="".concat(n.pathname.split("_")[0],".jpg"),la.setPoster.call(t,n.href).catch(function(){})}}),t.embed=new window.Vimeo.Player(s,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){return ga.call(t,!0),t.embed.play()},t.media.pause=function(){return ga.call(t,!1),t.embed.pause()},t.media.stop=function(){t.pause(),t.currentTime=0};var u=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return u},set:function(e){var n=t.embed,i=t.media,r=t.paused,a=t.volume,o=r&&!n.hasPlayed;i.seeking=!0,Ki.call(t,i,"seeking"),Promise.resolve(o&&n.setVolume(0)).then(function(){return n.setCurrentTime(e)}).then(function(){return o&&n.pause()}).then(function(){return o&&n.setVolume(a)}).catch(function(){})}});var h=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return h},set:function(e){t.embed.setPlaybackRate(e).then(function(){h=e,Ki.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&Kr.setSpeedMenu.call(t,[])})}});var d=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return d},set:function(e){t.embed.setVolume(e).then(function(){d=e,Ki.call(t,t.media,"volumechange")})}});var f=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return f},set:function(e){var n=!!Hi.boolean(e)&&e;t.embed.setVolume(n?0:t.config.volume).then(function(){f=n,Ki.call(t,t.media,"volumechange")})}});var p,m=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return m},set:function(e){var n=Hi.boolean(e)?e:t.config.loop.active;t.embed.setLoop(n).then(function(){m=n})}}),t.embed.getVideoUrl().then(function(e){p=e,Kr.setDownloadLink.call(t)}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return p}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(n){var i=gn(n,2),r=i[0],a=i[1];t.embed.ratio="".concat(r,":").concat(a),ca.call(e,t.embed.ratio)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(n){t.config.title=n,la.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){u=e,Ki.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,Ki.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,$r.setup.call(t)}),t.embed.on("cuechange",function(e){var n=e.cues,i=(void 0===n?[]:n).map(function(e){return t=e.text,n=document.createDocumentFragment(),i=document.createElement("div"),n.appendChild(i),i.innerHTML=t,n.firstChild.innerText;var t,n,i});$r.updateCues.call(t,i)}),t.embed.on("loaded",function(){(t.embed.getPaused().then(function(e){ga.call(t,!e),e||Ki.call(t,t.media,"playing")}),Hi.element(t.embed.element)&&t.supported.ui)&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){ga.call(t,!0),Ki.call(t,t.media,"playing")}),t.embed.on("pause",function(){ga.call(t,!1)}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,u=e.seconds,Ki.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,Ki.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&Ki.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,Ki.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,Ki.call(t,t.media,"seeked")}),t.embed.on("ended",function(){t.media.paused=!0,Ki.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,Ki.call(t,t.media,"error")}),setTimeout(function(){return la.build.call(t)},0)}};function ya(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,Ki.call(this,this.media,e?"play":"pause"))}var ba={setup:function(){var e=this;nr(this.elements.wrapper,this.config.classNames.embed,!0),ca.call(this),Hi.object(window.YT)&&Hi.function(window.YT.Player)?ba.ready.call(this):(ma(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){ba.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(Hi.function(this.embed.getVideoData)){var n=this.embed.getVideoData().title;if(Hi.empty(n))return this.config.title=n,void la.setTitle.call(this)}var i=this.config.keys.google;Hi.string(i)&&!Hi.empty(i)&&Hr(Nr(this.config.urls.youtube.api,e,i)).then(function(e){Hi.object(e)&&(t.config.title=e.items[0].snippet.title,la.setTitle.call(t))}).catch(function(){})},ready:function(){var e=this,t=e.media.getAttribute("id");if(Hi.empty(t)||!t.startsWith("youtube-")){var n=e.media.getAttribute("src");Hi.empty(n)&&(n=e.media.getAttribute(this.config.attributes.embed.id));var i,r,a=(i=n,Hi.empty(i)?null:i.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:i),o=(r=e.provider,"".concat(r,"-").concat(Math.floor(1e4*Math.random()))),s=$i("div",{id:o,poster:e.poster});e.media=Zi(s,e.media);var l=function(e){return"https://img.youtube.com/vi/".concat(a,"/").concat(e,"default.jpg")};sa(l("maxres"),121).catch(function(){return sa(l("sd"),121)}).catch(function(){return sa(l("hq"))}).then(function(t){return la.setPoster.call(e,t.src)}).then(function(t){t.includes("maxres")||(e.elements.poster.style.backgroundSize="cover")}).catch(function(){});var c=e.config.youtube;e.embed=new window.YT.Player(o,{videoId:a,host:c.noCookie?"https://www.youtube-nocookie.com":void 0,playerVars:wr({},{autoplay:e.config.autoplay?1:0,hl:e.config.hl,controls:e.supported.ui?0:1,disablekb:1,playsinline:e.config.fullscreen.iosNative?0:1,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language,widget_referrer:window?window.location.href:null},c),events:{onError:function(t){if(!e.media.error){var n=t.data,i={2:"The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.",5:"The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",100:"The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.",101:"The owner of the requested video does not allow it to be played in embedded players.",150:"The owner of the requested video does not allow it to be played in embedded players."}[n]||"An unknown error occured";e.media.error={code:n,message:i},Ki.call(e,e.media,"error")}},onPlaybackRateChange:function(t){var n=t.target;e.media.playbackRate=n.getPlaybackRate(),Ki.call(e,e.media,"ratechange")},onReady:function(t){if(!Hi.function(e.media.play)){var n=t.target;ba.getTitle.call(e,a),e.media.play=function(){ya.call(e,!0),n.playVideo()},e.media.pause=function(){ya.call(e,!1),n.pauseVideo()},e.media.stop=function(){n.stopVideo()},e.media.duration=n.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(n.getCurrentTime())},set:function(t){e.paused&&!e.embed.hasPlayed&&e.embed.mute(),e.media.seeking=!0,Ki.call(e,e.media,"seeking"),n.seekTo(t)}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return n.getPlaybackRate()},set:function(e){n.setPlaybackRate(e)}});var i=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return i},set:function(t){i=t,n.setVolume(100*i),Ki.call(e,e.media,"volumechange")}});var r=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return r},set:function(t){var i=Hi.boolean(t)?t:r;r=i,n[i?"mute":"unMute"](),Ki.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return n.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=n.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),Ki.call(e,e.media,"timeupdate"),Ki.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=n.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&Ki.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),Ki.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return la.build.call(e)},50)}},onStateChange:function(t){var n=t.target;switch(clearInterval(e.timers.playing),e.media.seeking&&[1,2].includes(t.data)&&(e.media.seeking=!1,Ki.call(e,e.media,"seeked")),t.data){case-1:Ki.call(e,e.media,"timeupdate"),e.media.buffered=n.getVideoLoadedFraction(),Ki.call(e,e.media,"progress");break;case 0:ya.call(e,!1),e.media.loop?(n.stopVideo(),n.playVideo()):Ki.call(e,e.media,"ended");break;case 1:e.media.paused&&!e.embed.hasPlayed?e.media.pause():(ya.call(e,!0),Ki.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){Ki.call(e,e.media,"timeupdate")},50),e.media.duration!==n.getDuration()&&(e.media.duration=n.getDuration(),Ki.call(e,e.media,"durationchange")));break;case 2:e.muted||e.embed.unMute(),ya.call(e,!1)}Ki.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},wa={setup:function(){this.media?(nr(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),nr(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&nr(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=$i("div",{class:this.config.classNames.video}),Yi(this.media,this.elements.wrapper),this.elements.poster=$i("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isHTML5?vr.extend.call(this):this.isYouTube?ba.setup.call(this):this.isVimeo&&va.setup.call(this)):this.debug.warn("No media element found!")}},ka=function(){function e(t){var n=this;dn(this,e),this.player=t,this.config=t.config.ads,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){n.on("loaded",e),n.on("error",t)}),this.load()}return pn(e,[{key:"load",value:function(){var e=this;this.enabled&&(Hi.object(window.google)&&Hi.object(window.google.ima)?this.ready():ma(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=$i("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var n=new google.ima.AdsRequest;n.adTagUrl=this.tagUrl,n.linearAdSlotWidth=t.offsetWidth,n.linearAdSlotHeight=t.offsetHeight,n.nonLinearAdSlotWidth=t.offsetWidth,n.nonLinearAdSlotHeight=t.offsetHeight,n.forceNonLinearFullSlot=!1,n.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(n)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=zr(Math.max(e.manager.getRemainingTime(),0)),n="".concat(Dr("advertisement",e.player.config)," - ").concat(t);e.elements.container.setAttribute("data-badge-text",n)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this;if(this.enabled){var n=new google.ima.AdsRenderingSettings;n.restoreCustomPlaybackStateOnAdBreakComplete=!0,n.enablePreloading=!0,this.manager=e.getAdsManager(this.player,n),this.cuePoints=this.manager.getCuePoints(),Hi.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var n=t.player.elements.progress;if(Hi.element(n)){var i=100/t.player.duration*e,r=$i("span",{class:t.player.config.classNames.cues});r.style.left="".concat(i.toString(),"%"),n.appendChild(r)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}}},{key:"onAdEvent",value:function(e){var t=this,n=this.player.elements.container,i=e.getAd(),r=e.getAdData(),a=function(e){var n="ads".concat(e.replace(/_/g,"").toLowerCase());Ki.call(t.player,t.player.media,n)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),a(e.type),this.pollCountdown(!0),i.isLinear()||(i.width=n.offsetWidth,i.height=n.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:a(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:a(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:a(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:a(e.type);break;case google.ima.AdEvent.Type.LOG:r.adError&&this.player.debug.warn("Non-fatal ad error: ".concat(r.adError.getMessage()))}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e,t=this,n=this.player.elements.container;this.player.on("ended",function(){t.loader.contentComplete()}),this.player.on("timeupdate",function(){e=t.player.currentTime}),this.player.on("seeked",function(){var n=t.player.currentTime;Hi.empty(t.cuePoints)||t.cuePoints.forEach(function(i,r){e<i&&i<n&&(t.manager.discardAdBreak(),t.cuePoints.splice(r,1))})}),window.addEventListener("resize",function(){t.manager&&t.manager.resize(n.offsetWidth,n.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,n=arguments.length,i=new Array(n>1?n-1:0),r=1;r<n;r++)i[r-1]=arguments[r];var a=this.events[e];Hi.array(a)&&a.forEach(function(e){Hi.function(e)&&e.apply(t,i)})}},{key:"on",value:function(e,t){return Hi.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var n=this;this.player.debug.log("Safety timer invoked from: ".concat(t)),this.safetyTimer=setTimeout(function(){n.cancel(),n.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){Hi.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: ".concat(e)),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){var e=this.config;return this.player.isHTML5&&this.player.isVideo&&e.enabled&&(!Hi.empty(e.publisherId)||Hi.url(e.tagUrl))}},{key:"tagUrl",get:function(){var e=this.config;if(Hi.url(e.tagUrl))return e.tagUrl;var t={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:window.location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"".concat("https://go.aniview.com/api/adserver6/vast/","?").concat(Gr(t))}}]),e}(),Ta=ne(6),Ea=!0;"findIndex"in[]&&Array(1).findIndex(function(){Ea=!1}),_(_.P+_.F*Ea,"Array",{findIndex:function(e){return Ta(this,e,arguments.length>1?arguments[1]:void 0)}}),ae("findIndex");var Sa,Aa=function(){function e(t){dn(this,e),this.player=t,this.thumbnails=[],this.loaded=!1,this.lastMouseMoveTime=Date.now(),this.mouseDown=!1,this.loadedImages=[],this.elements={thumb:{},scrubbing:{}},this.load()}return pn(e,[{key:"load",value:function(){var e=this;this.player.elements.display.seekTooltip&&(this.player.elements.display.seekTooltip.hidden=this.enabled),this.enabled&&this.getThumbnails().then(function(){e.render(),e.determineContainerAutoSizing(),e.loaded=!0})}},{key:"getThumbnails",value:function(){var e=this;return new Promise(function(t){var n=e.player.config.previewThumbnails.src;if(Hi.empty(n))throw new Error("Missing previewThumbnails.src config attribute");var i=(Hi.string(n)?[n]:n).map(function(t){return e.getThumbnail(t)});Promise.all(i).then(function(){e.thumbnails.sort(function(e,t){return e.height-t.height}),e.player.debug.log("Preview thumbnails",e.thumbnails),t()})})}},{key:"getThumbnail",value:function(e){var t=this;return new Promise(function(n){Hr(e).then(function(i){var r,a,o={frames:(r=i,a=[],r.split(/\r\n\r\n|\n\n|\r\r/).forEach(function(e){var t={};e.split(/\r\n|\n|\r/).forEach(function(e){if(Hi.number(t.startTime)){if(!Hi.empty(e.trim())&&Hi.empty(t.text)){var n=e.trim().split("#xywh="),i=gn(n,1);if(t.text=i[0],n[1]){var r=gn(n[1].split(","),4);t.x=r[0],t.y=r[1],t.w=r[2],t.h=r[3]}}}else{var a=e.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);a&&(t.startTime=60*Number(a[1])*60+60*Number(a[2])+Number(a[3])+Number("0.".concat(a[4])),t.endTime=60*Number(a[6])*60+60*Number(a[7])+Number(a[8])+Number("0.".concat(a[9])))}}),t.text&&a.push(t)}),a),height:null,urlPrefix:""};o.frames[0].text.startsWith("/")||(o.urlPrefix=e.substring(0,e.lastIndexOf("/")+1));var s=new Image;s.onload=function(){o.height=s.naturalHeight,o.width=s.naturalWidth,t.thumbnails.push(o),n()},s.src=o.urlPrefix+o.frames[0].text})})}},{key:"startMove",value:function(e){if(this.loaded&&Hi.event(e)&&["touchmove","mousemove"].includes(e.type)&&this.player.media.duration){if("touchmove"===e.type)this.seekTime=this.player.media.duration*(this.player.elements.inputs.seek.value/100);else{var t=this.player.elements.progress.getBoundingClientRect(),n=100/t.width*(e.pageX-t.left);this.seekTime=this.player.media.duration*(n/100),this.seekTime<0&&(this.seekTime=0),this.seekTime>this.player.media.duration-1&&(this.seekTime=this.player.media.duration-1),this.mousePosX=e.pageX,this.elements.thumb.time.innerText=zr(this.seekTime)}this.showImageAtCurrentTime()}}},{key:"endMove",value:function(){this.toggleThumbContainer(!1,!0)}},{key:"startScrubbing",value:function(e){!1!==e.button&&0!==e.button||(this.mouseDown=!0,this.player.media.duration&&(this.toggleScrubbingContainer(!0),this.toggleThumbContainer(!1,!0),this.showImageAtCurrentTime()))}},{key:"finishScrubbing",value:function(){var e=this;this.mouseDown=!1,Math.ceil(this.lastTime)===Math.ceil(this.player.media.currentTime)?this.toggleScrubbingContainer(!1):zi.call(this.player,this.player.media,"timeupdate",function(){e.mouseDown||e.toggleScrubbingContainer(!1)})}},{key:"listeners",value:function(){var e=this;this.player.on("play",function(){e.toggleThumbContainer(!1,!0)}),this.player.on("seeked",function(){e.toggleThumbContainer(!1)}),this.player.on("timeupdate",function(){e.lastTime=e.player.media.currentTime})}},{key:"render",value:function(){this.elements.thumb.container=$i("div",{class:this.player.config.classNames.previewThumbnails.thumbContainer}),this.elements.thumb.imageContainer=$i("div",{class:this.player.config.classNames.previewThumbnails.imageContainer}),this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);var e=$i("div",{class:this.player.config.classNames.previewThumbnails.timeContainer});this.elements.thumb.time=$i("span",{},"00:00"),e.appendChild(this.elements.thumb.time),this.elements.thumb.container.appendChild(e),this.player.elements.progress.appendChild(this.elements.thumb.container),this.elements.scrubbing.container=$i("div",{class:this.player.config.classNames.previewThumbnails.scrubbingContainer}),this.player.elements.wrapper.appendChild(this.elements.scrubbing.container)}},{key:"showImageAtCurrentTime",value:function(){var e=this;this.mouseDown?this.setScrubbingContainerSize():(this.toggleThumbContainer(!0),this.setThumbContainerSizeAndPos());var t=this.thumbnails[0].frames.findIndex(function(t){return e.seekTime>=t.startTime&&e.seekTime<=t.endTime}),n=t>=0,i=0;this.toggleThumbContainer(n),n&&(this.thumbnails.forEach(function(n,r){e.loadedImages.includes(n.frames[t].text)&&(i=r)}),t!==this.showingThumb&&(this.showingThumb=t,this.loadImage(i)))}},{key:"loadImage",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=this.showingThumb,i=this.thumbnails[t],r=i.urlPrefix,a=i.frames[n],o=i.frames[n].text,s=r+o;if(this.currentImageElement&&this.currentImageElement.dataset.filename===o)this.showImage(this.currentImageElement,a,t,n,o,!1),this.currentImageElement.dataset.index=n,this.removeOldImages(this.currentImageElement);else{this.loadingImage&&this.usingSprites&&(this.loadingImage.onload=null);var l=new Image;l.src=s,l.dataset.index=n,l.dataset.filename=o,this.showingThumbFilename=o,this.player.debug.log("Loading image: ".concat(s)),l.onload=function(){return e.showImage(l,a,t,n,o,!0)},this.loadingImage=l,this.removeOldImages(l)}}},{key:"showImage",value:function(e,t,n,i,r){var a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];this.player.debug.log("Showing thumb: ".concat(r,". num: ").concat(i,". qual: ").concat(n,". newimg: ").concat(a)),this.setImageSizeAndOffset(e,t),a&&(this.currentImageContainer.appendChild(e),this.currentImageElement=e,this.loadedImages.includes(r)||this.loadedImages.push(r)),this.preloadNearby(i,!0).then(this.preloadNearby(i,!1)).then(this.getHigherQuality(n,e,t,r))}},{key:"removeOldImages",value:function(e){var t=this;Array.from(this.currentImageContainer.children).forEach(function(n){if("img"===n.tagName.toLowerCase()){var i=t.usingSprites?500:1e3;if(n.dataset.index!==e.dataset.index&&!n.dataset.deleting){n.dataset.deleting=!0;var r=t.currentImageContainer;setTimeout(function(){r.removeChild(n),t.player.debug.log("Removing thumb: ".concat(n.dataset.filename))},i)}}})}},{key:"preloadNearby",value:function(e){var t=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return new Promise(function(i){setTimeout(function(){var r=t.thumbnails[0].frames[e].text;if(t.showingThumbFilename===r){var a;a=n?t.thumbnails[0].frames.slice(e):t.thumbnails[0].frames.slice(0,e).reverse();var o=!1;a.forEach(function(e){var n=e.text;if(n!==r&&!t.loadedImages.includes(n)){o=!0,t.player.debug.log("Preloading thumb filename: ".concat(n));var a=t.thumbnails[0].urlPrefix+n,s=new Image;s.src=a,s.onload=function(){t.player.debug.log("Preloaded thumb filename: ".concat(n)),t.loadedImages.includes(n)||t.loadedImages.push(n),i()}}}),o||i()}},300)})}},{key:"getHigherQuality",value:function(e,t,n,i){var r=this;if(e<this.thumbnails.length-1){var a=t.naturalHeight;this.usingSprites&&(a=n.h),a<this.thumbContainerHeight&&setTimeout(function(){r.showingThumbFilename===i&&(r.player.debug.log("Showing higher quality thumb for: ".concat(i)),r.loadImage(e+1))},300)}}},{key:"toggleThumbContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.player.config.classNames.previewThumbnails.thumbContainerShown;this.elements.thumb.container.classList.toggle(n,e),!e&&t&&(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"toggleScrubbingContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.player.config.classNames.previewThumbnails.scrubbingContainerShown;this.elements.scrubbing.container.classList.toggle(t,e),e||(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"determineContainerAutoSizing",value:function(){this.elements.thumb.imageContainer.clientHeight>20&&(this.sizeSpecifiedInCSS=!0)}},{key:"setThumbContainerSizeAndPos",value:function(){if(!this.sizeSpecifiedInCSS){var e=Math.floor(this.thumbContainerHeight*this.thumbAspectRatio);this.elements.thumb.imageContainer.style.height="".concat(this.thumbContainerHeight,"px"),this.elements.thumb.imageContainer.style.width="".concat(e,"px")}this.setThumbContainerPos()}},{key:"setThumbContainerPos",value:function(){var e=this.player.elements.progress.getBoundingClientRect(),t=this.player.elements.container.getBoundingClientRect(),n=this.elements.thumb.container,i=t.left-e.left+10,r=t.right-e.left-n.clientWidth-10,a=this.mousePosX-e.left-n.clientWidth/2;a<i&&(a=i),a>r&&(a=r),n.style.left="".concat(a,"px")}},{key:"setScrubbingContainerSize",value:function(){this.elements.scrubbing.container.style.width="".concat(this.player.media.clientWidth,"px"),this.elements.scrubbing.container.style.height="".concat(this.player.media.clientWidth/this.thumbAspectRatio,"px")}},{key:"setImageSizeAndOffset",value:function(e,t){if(this.usingSprites){var n=this.thumbContainerHeight/t.h;e.style.height="".concat(Math.floor(e.naturalHeight*n),"px"),e.style.width="".concat(Math.floor(e.naturalWidth*n),"px"),e.style.left="-".concat(t.x*n,"px"),e.style.top="-".concat(t.y*n,"px")}}},{key:"enabled",get:function(){return this.player.isHTML5&&this.player.isVideo&&this.player.config.previewThumbnails.enabled}},{key:"currentImageContainer",get:function(){return this.mouseDown?this.elements.scrubbing.container:this.elements.thumb.imageContainer}},{key:"usingSprites",get:function(){return Object.keys(this.thumbnails[0].frames[0]).includes("w")}},{key:"thumbAspectRatio",get:function(){return this.usingSprites?this.thumbnails[0].frames[0].w/this.thumbnails[0].frames[0].h:this.thumbnails[0].width/this.thumbnails[0].height}},{key:"thumbContainerHeight",get:function(){return this.mouseDown?Math.floor(this.player.media.clientWidth/this.thumbAspectRatio):Math.floor(this.player.media.clientWidth/this.thumbAspectRatio/4)}},{key:"currentImageElement",get:function(){return this.mouseDown?this.currentScrubbingImageElement:this.currentThumbnailImageElement},set:function(e){this.mouseDown?this.currentScrubbingImageElement=e:this.currentThumbnailImageElement=e}}]),e}(),_a={insertElements:function(e,t){var n=this;Hi.string(t)?Qi(e,this.media,{src:t}):Hi.array(t)&&t.forEach(function(t){Qi(e,n.media,t)})},change:function(e){var t=this;br(e,"sources.length")?(vr.cancelRequests.call(this),this.destroy.call(this,function(){t.options.quality=[],Xi(t.media),t.media=null,Hi.element(t.elements.container)&&t.elements.container.removeAttribute("class");var n=e.sources,i=e.type,r=gn(n,1)[0],a=r.provider,o=void 0===a?Zr.html5:a,s=r.src,l="html5"===o?i:"div",c="html5"===o?{}:{src:s};Object.assign(t,{provider:o,type:i,supported:gr.check(i,o,t.config.playsinline),media:$i(l,c)}),t.elements.container.appendChild(t.media),Hi.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),Hi.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),la.addStyleHook.call(t),t.isHTML5&&_a.insertElements.call(t,"source",n),t.config.title=e.title,wa.setup.call(t),t.isHTML5&&Object.keys(e).includes("tracks")&&_a.insertElements.call(t,"track",e.tracks),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&la.build.call(t),t.isHTML5&&t.media.load(),t.previewThumbnails&&t.previewThumbnails.load(),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},Ca=function(){function e(t,n){var i=this;if(dn(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=gr.touch,this.media=t,Hi.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||Hi.nodeList(this.media)||Hi.array(this.media))&&(this.media=this.media[0]),this.config=wr({},Qr,e.defaults,n||{},function(){try{return JSON.parse(i.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,captions:null,buttons:{},display:{},progress:{},inputs:{},settings:{popup:null,menu:null,panels:{},buttons:{}}},this.captions={active:null,currentTrack:-1,meta:new WeakMap},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new na(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",gr),!Hi.nullOrUndefined(this.media)&&Hi.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(gr.check().api){var r=this.media.cloneNode(!0);r.autoplay=!1,this.elements.original=r;var a=this.media.tagName.toLowerCase(),o=null,s=null;switch(a){case"div":if(o=this.media.querySelector("iframe"),Hi.element(o)){if(s=Yr(o.getAttribute("src")),this.provider=function(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e)?Zr.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?Zr.vimeo:null}(s.toString()),this.elements.container=this.media,this.media=o,this.elements.container.className="",s.search.length){var l=["1","true"];l.includes(s.searchParams.get("autoplay"))&&(this.config.autoplay=!0),l.includes(s.searchParams.get("loop"))&&(this.config.loop.active=!0),this.isYouTube?(this.config.playsinline=l.includes(s.searchParams.get("playsinline")),this.config.youtube.hl=s.searchParams.get("hl")):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(Hi.empty(this.provider)||!Object.keys(Zr).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=ea.video;break;case"video":case"audio":this.type=a,this.provider=Zr.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),(this.media.hasAttribute("playsinline")||this.media.hasAttribute("webkit-playsinline"))&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=gr.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.eventListeners=[],this.listeners=new ua(this),this.storage=new qr(this),this.media.plyr=this,Hi.element(this.elements.container)||(this.elements.container=$i("div",{tabindex:0}),Yi(this.media,this.elements.container)),la.addStyleHook.call(this),wa.setup.call(this),this.config.debug&&Ui.call(this,this.elements.container,this.config.events.join(" "),function(e){i.debug.log("event: ".concat(e.type))}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&la.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new aa(this),this.config.ads.enabled&&(this.ads=new ka(this)),this.config.autoplay&&this.play(),this.lastSeekTime=0,this.config.previewThumbnails.enabled&&(this.previewThumbnails=new Aa(this))):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return pn(e,[{key:"play",value:function(){return Hi.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&Hi.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(Hi.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):Hi.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(Hi.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(Hi.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(Hi.number(e)?e:0)}},{key:"decreaseVolume",value:function(e){this.increaseVolume(-e)}},{key:"toggleCaptions",value:function(e){$r.toggle.call(this,e,!1)}},{key:"airplay",value:function(){gr.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){if(this.supported.ui&&!this.isAudio){var t=ir(this.elements.container,this.config.classNames.hideControls),n=void 0===e?void 0:!e,i=nr(this.elements.container,this.config.classNames.hideControls,n);if(i&&this.config.controls.includes("settings")&&!Hi.empty(this.config.settings)&&Kr.toggleMenu.call(this,!1),i!==t){var r=i?"controlshidden":"controlsshown";Ki.call(this,this.media,r)}return!i}return!1}},{key:"on",value:function(e,t){Ui.call(this,this.elements.container,e,t)}},{key:"once",value:function(e,t){zi.call(this,this.elements.container,e,t)}},{key:"off",value:function(e,t){Wi(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var i=function(){document.body.style.overflow="",t.embed=null,n?(Object.keys(t.elements).length&&(Xi(t.elements.buttons.play),Xi(t.elements.captions),Xi(t.elements.controls),Xi(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),Hi.function(e)&&e()):(function(){this&&this.eventListeners&&(this.eventListeners.forEach(function(e){var t=e.element,n=e.type,i=e.callback,r=e.options;t.removeEventListener(n,i,r)}),this.eventListeners=[])}.call(t),Zi(t.elements.original,t.elements.container),Ki.call(t,t.elements.original,"destroyed",!0),Hi.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};this.stop(),this.isHTML5?(clearTimeout(this.timers.loading),la.toggleNativeControls.call(this,!0),i()):this.isYouTube?(clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&Hi.function(this.embed.destroy)&&this.embed.destroy(),i()):this.isVimeo&&(null!==this.embed&&this.embed.unload().then(i),setTimeout(i,200))}}},{key:"supports",value:function(e){return gr.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===Zr.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===Zr.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===Zr.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===ea.video)}},{key:"isAudio",get:function(){return Boolean(this.type===ea.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){if(this.duration){var t=Hi.number(e)&&e>0;this.media.currentTime=t?Math.min(e,this.duration):0,this.debug.log("Seeking to ".concat(this.currentTime," seconds"))}},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return Hi.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=(this.media||{}).duration,n=Hi.number(t)&&t!==1/0?t:0;return e||n}},{key:"volume",set:function(e){var t=e;Hi.string(t)&&(t=Number(t)),Hi.number(t)||(t=this.storage.get("volume")),Hi.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!Hi.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;Hi.boolean(t)||(t=this.storage.get("muted")),Hi.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;Hi.number(e)&&(t=e),Hi.number(t)||(t=this.storage.get("speed")),Hi.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed (".concat(t,")"))},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=this.config.quality,n=this.options.quality;if(n.length){var i=[!Hi.empty(e)&&Number(e),this.storage.get("quality"),t.selected,t.default].find(Hi.number),r=!0;if(!n.includes(i)){var a=function(e,t){return Hi.array(e)&&e.length?e.reduce(function(e,n){return Math.abs(n-t)<Math.abs(e-t)?n:e}):null}(n,i);this.debug.warn("Unsupported quality option: ".concat(i,", using ").concat(a," instead")),i=a,r=!1}t.selected=i,this.media.quality=i,r&&this.storage.set({quality:i})}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=Hi.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){_a.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"download",get:function(){var e=this.config.urls.download;return Hi.url(e)?e:this.source}},{key:"poster",set:function(e){this.isVideo?la.setPoster.call(this,e,!1).catch(function(){}):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=Hi.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"currentTrack",set:function(e){$r.set.call(this,e,!1)},get:function(){var e=this.captions,t=e.toggled,n=e.currentTrack;return t?n:-1}},{key:"language",set:function(e){$r.setLanguage.call(this,e,!1)},get:function(){return($r.getCurrentTrack.call(this)||{}).language}},{key:"pip",set:function(e){if(gr.pip){var t=Hi.boolean(e)?e:!this.pip;Hi.function(this.media.webkitSetPresentationMode)&&this.media.webkitSetPresentationMode(t?Xr:Jr),Hi.function(this.media.requestPictureInPicture)&&(!this.pip&&t?this.media.requestPictureInPicture():this.pip&&!t&&document.exitPictureInPicture())}},get:function(){return gr.pip?Hi.empty(this.media.webkitPresentationMode)?this.media===document.pictureInPictureElement:this.media.webkitPresentationMode===Xr:null}}],[{key:"supported",value:function(e,t,n){return gr.check(e,t,n)}},{key:"loadSprite",value:function(e,t){return Vr(e,t)}},{key:"setup",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=null;return Hi.string(t)?i=Array.from(document.querySelectorAll(t)):Hi.nodeList(t)?i=Array.from(t):Hi.array(t)&&(i=t.filter(Hi.element)),Hi.empty(i)?null:i.map(function(t){return new e(t,n)})}}]),e}();return Ca.defaults=(Sa=Qr,JSON.parse(JSON.stringify(Sa))),Ca}); //# sourceMappingURL=plyr.polyfilled.min.js.map diff --git a/dist/plyr.polyfilled.min.js.map b/dist/plyr.polyfilled.min.js.map index 29fd774e..5a363ff0 100644 --- a/dist/plyr.polyfilled.min.js.map +++ b/dist/plyr.polyfilled.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../node_modules/core-js/modules/_global.js","../../node_modules/core-js/modules/_core.js","../../node_modules/core-js/modules/_is-object.js","../../node_modules/core-js/modules/_an-object.js","../../node_modules/core-js/modules/_fails.js","../../node_modules/core-js/modules/_descriptors.js","../../node_modules/core-js/modules/_dom-create.js","../../node_modules/core-js/modules/_ie8-dom-define.js","../../node_modules/core-js/modules/_to-primitive.js","../../node_modules/core-js/modules/_object-dp.js","../../node_modules/core-js/modules/_property-desc.js","../../node_modules/core-js/modules/_hide.js","../../node_modules/core-js/modules/_has.js","../../node_modules/core-js/modules/_uid.js","../../node_modules/core-js/modules/_redefine.js","../../node_modules/core-js/modules/_a-function.js","../../node_modules/core-js/modules/_ctx.js","../../node_modules/core-js/modules/_export.js","../../node_modules/core-js/modules/_typed.js","../../node_modules/core-js/modules/_redefine-all.js","../../node_modules/core-js/modules/_an-instance.js","../../node_modules/core-js/modules/_to-integer.js","../../node_modules/core-js/modules/_to-length.js","../../node_modules/core-js/modules/_to-index.js","../../node_modules/core-js/modules/_cof.js","../../node_modules/core-js/modules/_iobject.js","../../node_modules/core-js/modules/_defined.js","../../node_modules/core-js/modules/_to-iobject.js","../../node_modules/core-js/modules/_to-absolute-index.js","../../node_modules/core-js/modules/_array-includes.js","../../node_modules/core-js/modules/_shared.js","../../node_modules/core-js/modules/_shared-key.js","../../node_modules/core-js/modules/_object-keys-internal.js","../../node_modules/core-js/modules/_enum-bug-keys.js","../../node_modules/core-js/modules/_object-gopn.js","../../node_modules/core-js/modules/_to-object.js","../../node_modules/core-js/modules/_array-fill.js","../../node_modules/core-js/modules/_wks.js","../../node_modules/core-js/modules/_set-to-string-tag.js","../../node_modules/core-js/modules/_typed-buffer.js","../../node_modules/core-js/modules/_species-constructor.js","../../node_modules/core-js/modules/_set-species.js","../../node_modules/core-js/modules/es6.typed.array-buffer.js","../../node_modules/core-js/modules/_classof.js","../../node_modules/core-js/modules/_iterators.js","../../node_modules/core-js/modules/_is-array-iter.js","../../node_modules/core-js/modules/_object-keys.js","../../node_modules/core-js/modules/_object-dps.js","../../node_modules/core-js/modules/_html.js","../../node_modules/core-js/modules/_object-create.js","../../node_modules/core-js/modules/_object-gpo.js","../../node_modules/core-js/modules/core.get-iterator-method.js","../../node_modules/core-js/modules/_is-array.js","../../node_modules/core-js/modules/_array-species-constructor.js","../../node_modules/core-js/modules/_array-species-create.js","../../node_modules/core-js/modules/_array-methods.js","../../node_modules/core-js/modules/_add-to-unscopables.js","../../node_modules/core-js/modules/_iter-step.js","../../node_modules/core-js/modules/_iter-create.js","../../node_modules/core-js/modules/_iter-define.js","../../node_modules/core-js/modules/es6.array.iterator.js","../../node_modules/core-js/modules/_iter-detect.js","../../node_modules/core-js/modules/_array-copy-within.js","../../node_modules/core-js/modules/_object-pie.js","../../node_modules/core-js/modules/_object-gopd.js","../../node_modules/core-js/modules/_typed-array.js","../../node_modules/core-js/modules/es6.typed.int8-array.js","../../node_modules/core-js/modules/es6.typed.uint8-array.js","../../node_modules/core-js/modules/es6.typed.uint8-clamped-array.js","../../node_modules/core-js/modules/es6.typed.int16-array.js","../../node_modules/core-js/modules/es6.typed.uint16-array.js","../../node_modules/core-js/modules/es6.typed.int32-array.js","../../node_modules/core-js/modules/es6.typed.uint32-array.js","../../node_modules/core-js/modules/es6.typed.float32-array.js","../../node_modules/core-js/modules/es6.typed.float64-array.js","../../node_modules/core-js/modules/_iter-call.js","../../node_modules/core-js/modules/_for-of.js","../../node_modules/core-js/modules/_meta.js","../../node_modules/core-js/modules/_validate-collection.js","../../node_modules/core-js/modules/_collection-strong.js","../../node_modules/core-js/modules/_set-proto.js","../../node_modules/core-js/modules/_inherit-if-required.js","../../node_modules/core-js/modules/_collection.js","../../node_modules/core-js/modules/es6.map.js","../../node_modules/core-js/modules/es6.set.js","../../node_modules/core-js/modules/_object-gops.js","../../node_modules/core-js/modules/_object-assign.js","../../node_modules/core-js/modules/_collection-weak.js","../../node_modules/core-js/modules/es6.weak-map.js","../../node_modules/core-js/modules/es6.weak-set.js","../../node_modules/core-js/modules/es6.reflect.apply.js","../../node_modules/core-js/modules/_invoke.js","../../node_modules/core-js/modules/_bind.js","../../node_modules/core-js/modules/es6.reflect.construct.js","../../node_modules/core-js/modules/es6.reflect.define-property.js","../../node_modules/core-js/modules/es6.reflect.delete-property.js","../../node_modules/core-js/modules/es6.reflect.get.js","../../node_modules/core-js/modules/es6.reflect.get-own-property-descriptor.js","../../node_modules/core-js/modules/es6.reflect.get-prototype-of.js","../../node_modules/core-js/modules/es6.reflect.has.js","../../node_modules/core-js/modules/es6.reflect.is-extensible.js","../../node_modules/core-js/modules/_own-keys.js","../../node_modules/core-js/modules/es6.reflect.own-keys.js","../../node_modules/core-js/modules/es6.reflect.prevent-extensions.js","../../node_modules/core-js/modules/es6.reflect.set.js","../../node_modules/core-js/modules/es6.reflect.set-prototype-of.js","../../node_modules/core-js/modules/_task.js","../../node_modules/core-js/modules/_microtask.js","../../node_modules/core-js/modules/_new-promise-capability.js","../../node_modules/core-js/modules/es6.promise.js","../../node_modules/core-js/modules/_perform.js","../../node_modules/core-js/modules/_promise-resolve.js","../../node_modules/core-js/modules/_wks-ext.js","../../node_modules/core-js/modules/_wks-define.js","../../node_modules/core-js/modules/_object-gopn-ext.js","../../node_modules/core-js/modules/es6.symbol.js","../../node_modules/core-js/modules/_enum-keys.js","../../node_modules/core-js/modules/_object-sap.js","../../node_modules/core-js/modules/es6.object.freeze.js","../../node_modules/core-js/modules/es6.object.seal.js","../../node_modules/core-js/modules/es6.object.prevent-extensions.js","../../node_modules/core-js/modules/es6.object.is-frozen.js","../../node_modules/core-js/modules/es6.object.is-sealed.js","../../node_modules/core-js/modules/es6.object.is-extensible.js","../../node_modules/core-js/modules/es6.object.get-own-property-descriptor.js","../../node_modules/core-js/modules/es6.object.get-prototype-of.js","../../node_modules/core-js/modules/es6.object.keys.js","../../node_modules/core-js/modules/es6.object.get-own-property-names.js","../../node_modules/core-js/modules/es6.object.assign.js","../../node_modules/core-js/modules/_same-value.js","../../node_modules/core-js/modules/es6.object.is.js","../../node_modules/core-js/modules/es6.function.name.js","../../node_modules/core-js/modules/es6.string.raw.js","../../node_modules/core-js/modules/es6.string.from-code-point.js","../../node_modules/core-js/modules/_string-at.js","../../node_modules/core-js/modules/es6.string.code-point-at.js","../../node_modules/core-js/modules/_string-repeat.js","../../node_modules/core-js/modules/es6.string.repeat.js","../../node_modules/core-js/modules/_is-regexp.js","../../node_modules/core-js/modules/_string-context.js","../../node_modules/core-js/modules/_fails-is-regexp.js","../../node_modules/core-js/modules/es6.string.starts-with.js","../../node_modules/core-js/modules/es6.string.ends-with.js","../../node_modules/core-js/modules/es6.string.includes.js","../../node_modules/core-js/modules/es6.regexp.flags.js","../../node_modules/core-js/modules/_flags.js","../../node_modules/core-js/modules/_fix-re-wks.js","../../node_modules/core-js/modules/es6.regexp.match.js","../../node_modules/core-js/modules/es6.regexp.replace.js","../../node_modules/core-js/modules/es6.regexp.split.js","../../node_modules/core-js/modules/es6.regexp.search.js","../../node_modules/core-js/modules/_create-property.js","../../node_modules/core-js/modules/es6.array.from.js","../../node_modules/core-js/modules/es6.array.of.js","../../node_modules/core-js/modules/es6.array.copy-within.js","../../node_modules/core-js/modules/es6.array.find.js","../../node_modules/core-js/modules/es6.array.find-index.js","../../node_modules/core-js/modules/es6.array.fill.js","../../node_modules/core-js/modules/es6.number.is-finite.js","../../node_modules/core-js/modules/_is-integer.js","../../node_modules/core-js/modules/es6.number.is-integer.js","../../node_modules/core-js/modules/es6.number.is-safe-integer.js","../../node_modules/core-js/modules/es6.number.is-nan.js","../../node_modules/core-js/modules/es6.number.epsilon.js","../../node_modules/core-js/modules/es6.number.min-safe-integer.js","../../node_modules/core-js/modules/es6.number.max-safe-integer.js","../../node_modules/core-js/modules/_math-log1p.js","../../node_modules/core-js/modules/es6.math.acosh.js","../../node_modules/core-js/modules/es6.math.asinh.js","../../node_modules/core-js/modules/es6.math.atanh.js","../../node_modules/core-js/modules/_math-sign.js","../../node_modules/core-js/modules/es6.math.cbrt.js","../../node_modules/core-js/modules/es6.math.clz32.js","../../node_modules/core-js/modules/es6.math.cosh.js","../../node_modules/core-js/modules/_math-expm1.js","../../node_modules/core-js/modules/es6.math.expm1.js","../../node_modules/core-js/modules/_math-fround.js","../../node_modules/core-js/modules/es6.math.fround.js","../../node_modules/core-js/modules/es6.math.hypot.js","../../node_modules/core-js/modules/es6.math.imul.js","../../node_modules/core-js/modules/es6.math.log1p.js","../../node_modules/core-js/modules/es6.math.log10.js","../../node_modules/core-js/modules/es6.math.log2.js","../../node_modules/core-js/modules/es6.math.sign.js","../../node_modules/core-js/modules/es6.math.sinh.js","../../node_modules/core-js/modules/es6.math.tanh.js","../../node_modules/core-js/modules/es6.math.trunc.js","../../node_modules/core-js/modules/es7.array.includes.js","../../node_modules/core-js/modules/_object-to-array.js","../../node_modules/core-js/modules/es7.object.values.js","../../node_modules/core-js/modules/es7.object.entries.js","../../node_modules/core-js/modules/es7.object.get-own-property-descriptors.js","../../node_modules/core-js/modules/_string-pad.js","../../node_modules/core-js/modules/_user-agent.js","../../node_modules/core-js/modules/es7.string.pad-start.js","../../node_modules/core-js/modules/es7.string.pad-end.js","../../node_modules/core-js/modules/web.timers.js","../../node_modules/core-js/modules/web.immediate.js","../../node_modules/core-js/modules/web.dom.iterable.js","../../node_modules/regenerator-runtime/runtime.js","../../node_modules/custom-event-polyfill/custom-event-polyfill.js","support.js","../../node_modules/loadjs/dist/loadjs.umd.js","types.js","utils.js","html5.js","i18n.js","ui.js","controls.js","captions.js","console.js","defaults.js","fullscreen.js","listeners.js","plugins/vimeo.js","plugins/youtube.js","media.js","plugins/ads.js","source.js","storage.js","plyr.js"],"names":["global","module","exports","window","Math","self","Function","__g","core","version","__e","_isObject","it","_anObject","isObject","TypeError","_fails","exec","e","_descriptors","require$$0","Object","defineProperty","get","a","document","is","createElement","_domCreate","_ie8DomDefine","require$$1","require$$2","_toPrimitive","S","fn","val","toString","call","valueOf","dP","O","P","Attributes","anObject","toPrimitive","IE8_DOM_DEFINE","value","_propertyDesc","bitmap","enumerable","configurable","writable","_hide","object","key","f","createDesc","hasOwnProperty","_has","id","px","random","_uid","concat","undefined","SRC","$toString","TPL","split","inspectSource","safe","isFunction","has","hide","join","String","prototype","this","_aFunction","_ctx","that","length","aFunction","b","c","apply","arguments","$export","type","name","source","own","out","exp","IS_FORCED","F","IS_GLOBAL","G","IS_STATIC","IS_PROTO","IS_BIND","B","target","expProto","ctx","redefine","U","W","R","Typed","_export","TYPED","uid","VIEW","ABV","ArrayBuffer","DataView","CONSTR","i","TypedArrayConstructors","_typed","_redefineAll","src","_anInstance","Constructor","forbiddenField","ceil","floor","_toInteger","isNaN","min","_toLength","toInteger","_toIndex","number","toLength","RangeError","_cof","slice","_iobject","propertyIsEnumerable","cof","_defined","_toIobject","IObject","defined","max","_toAbsoluteIndex","index","_arrayIncludes","IS_INCLUDES","$this","el","fromIndex","toIObject","toAbsoluteIndex","store","_shared","shared","_sharedKey","arrayIndexOf","IE_PROTO","_objectKeysInternal","names","result","push","_enumBugKeys","hiddenKeys","getOwnPropertyNames","$keys","_toObject","_arrayFill","toObject","aLen","end","endPos","Symbol","USE_SYMBOL","def","TAG","_setToStringTag","tag","stat","gOPN","PROTOTYPE","WRONG_INDEX","$ArrayBuffer","$DataView","Infinity","BaseBuffer","abs","pow","log","LN2","$BUFFER","DESCRIPTORS","$LENGTH","$OFFSET","packIEEE754","mLen","nBytes","m","buffer","Array","eLen","eMax","eBias","rt","s","unpackIEEE754","nBits","NaN","unpackI32","bytes","packI8","packI16","packI32","packF64","packF32","addGetter","C","internal","view","isLittleEndian","intIndex","toIndex","_b","start","pack","reverse","set","conversion","$typed","fails","ArrayBufferProto","anInstance","keys","j","constructor","$setInt8","setInt8","getInt8","redefineAll","byteOffset","setUint8","byteLength","arrayFill","bufferLength","offset","getUint8","getInt16","getUint16","getInt32","getUint32","getFloat32","getFloat64","setInt16","setUint16","setInt32","setUint32","setFloat32","setFloat64","setToStringTag","SPECIES","_speciesConstructor","D","_setSpecies","KEY","$isView","isView","$slice","len","first","final","speciesConstructor","viewS","viewT","ARG","_classof","T","tryGet","callee","_iterators","ITERATOR","ArrayProto","_isArrayIter","Iterators","_objectKeys","enumBugKeys","_objectDps","defineProperties","Properties","getKeys","_html","documentElement","Empty","createDict","iframeDocument","iframe","style","display","appendChild","contentWindow","open","write","lt","close","_objectCreate","create","dPs","ObjectProto","_objectGpo","getPrototypeOf","core_getIteratorMethod","getIteratorMethod","classof","_isArray","isArray","arg","_arraySpeciesCreate","original","_arrayMethods","TYPE","$create","IS_MAP","IS_FILTER","IS_SOME","IS_EVERY","IS_FIND_INDEX","NO_HOLES","asc","callbackfn","res","UNSCOPABLES","_addToUnscopables","_iterStep","done","IteratorPrototype","_iterCreate","NAME","next","descriptor","BUGGY","returnThis","_iterDefine","Base","DEFAULT","IS_SET","FORCED","$iterCreate","methods","getMethod","kind","proto","DEF_VALUES","VALUES_BUG","$native","$default","$entries","$anyNative","entries","values","es6_array_iterator","iterated","_t","_i","_k","step","Arguments","addToUnscopables","SAFE_CLOSING","_iterDetect","skipClosing","arr","iter","_arrayCopyWithin","copyWithin","to","from","count","inc","gOPD","getOwnPropertyDescriptor","pIE","require$$3","require$$4","require$$5","$buffer","require$$6","require$$7","require$$8","propertyDesc","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","isArrayIter","require$$21","require$$22","require$$23","require$$24","getIterFn","require$$25","require$$26","wks","require$$27","createArrayMethod","require$$28","createArrayIncludes","require$$29","require$$30","ArrayIterators","require$$31","require$$32","$iterDetect","require$$33","setSpecies","require$$34","require$$35","arrayCopyWithin","require$$36","$DP","require$$37","$GOPD","require$$38","Uint8Array","arrayForEach","arrayFilter","arraySome","arrayEvery","arrayFind","arrayFindIndex","arrayIncludes","arrayValues","arrayKeys","arrayEntries","arrayLastIndexOf","lastIndexOf","arrayReduce","reduce","arrayReduceRight","reduceRight","arrayJoin","arraySort","sort","arraySlice","arrayToString","arrayToLocaleString","toLocaleString","TYPED_CONSTRUCTOR","DEF_CONSTRUCTOR","ALL_CONSTRUCTORS","TYPED_ARRAY","$map","allocate","LITTLE_ENDIAN","Uint16Array","FORCED_SET","toOffset","BYTES","validate","speciesFromList","list","fromList","_d","$from","iterator","mapfn","mapping","iterFn","$of","TO_LOCALE_BUG","$toLocaleString","every","fill","filter","find","predicate","findIndex","forEach","indexOf","searchElement","includes","separator","map","middle","some","comparefn","subarray","begin","$begin","BYTES_PER_ELEMENT","$set","arrayLike","$iterators","isTAIndex","$getDesc","$setDesc","desc","$TypedArrayPrototype$","wrapper","CLAMPED","GETTER","SETTER","TypedArray","TAC","TypedArrayPrototype","addElement","data","v","o","getter","round","setter","$offset","$length","klass","$len","l","$nativeIterator","CORRECT_ITER_NAME","$iterator","of","init","_iterCall","ret","BREAK","RETURN","iterable","META","setDesc","isExtensible","FREEZE","preventExtensions","setMeta","w","meta","NEED","fastKey","getWeak","onFreeze","_validateCollection","SIZE","getEntry","entry","_f","n","k","_collectionStrong","getConstructor","ADDER","_l","forOf","clear","r","p","delete","prev","setStrong","$iterDefine","check","_setProto","setPrototypeOf","test","buggy","__proto__","_collection","common","IS_WEAK","fixMethod","instance","HASNT_CHAINING","THROWS_ON_PRIMITIVES","ACCEPT_ITERABLES","BUGGY_ZERO","$instance","inheritIfRequired","strong","add","getOwnPropertySymbols","$assign","assign","_objectAssign","A","K","getSymbols","gOPS","isEnum","uncaughtFrozenStore","UncaughtFrozenStore","findUncaughtFrozen","splice","_collectionWeak","$has","ufstore","InternalMap","each","weak","tmp","$WeakMap","freeze","method","rApply","Reflect","fApply","thisArgument","argumentsList","L","_invoke","args","un","factories","_bind","bind","partArgs","bound","construct","invoke","rConstruct","NEW_TARGET_BUG","ARGS_BUG","Target","newTarget","$args","propertyKey","attributes","deleteProperty","receiver","getProto","$isExtensible","_ownKeys","ownKeys","$preventExtensions","V","existingDescriptor","ownDesc","setProto","defer","channel","port","process","setTask","setImmediate","clearTask","clearImmediate","MessageChannel","Dispatch","counter","queue","run","listener","event","nextTick","now","port2","port1","onmessage","postMessage","addEventListener","importScripts","cel","html","removeChild","setTimeout","_task","macrotask","Observer","MutationObserver","WebKitMutationObserver","Promise","isNode","Internal","newGenericPromiseCapability","OwnPromiseCapability","Wrapper","resolve","reject","promise","$$resolve","$$reject","_perform","task","microtask","head","last","notify","flush","parent","domain","exit","enter","navigator","standalone","then","toggle","node","createTextNode","observe","characterData","$Promise","empty","newPromiseCapability","newPromiseCapabilityModule","USE_NATIVE","FakePromise","PromiseRejectionEvent","isThenable","isReject","_n","chain","_c","_v","ok","_s","reaction","handler","fail","_h","onHandleUnhandled","onUnhandled","console","unhandled","isUnhandled","perform","emit","onunhandledrejection","reason","error","_a","onrejectionhandled","$reject","_w","$resolve","executor","err","onFulfilled","onRejected","catch","capability","x","promiseCapability","promiseResolve","all","remaining","$index","alreadyCalled","race","_wksDefine","$Symbol","charAt","wksExt","windowNames","getWindowNames","gOPNExt","$JSON","JSON","_stringify","stringify","HIDDEN","TO_PRIMITIVE","SymbolRegistry","AllSymbols","OPSymbols","QObject","findChild","setSymbolDesc","$fails","_create","protoDesc","wrap","sym","isSymbol","$defineProperty","$defineProperties","symbols","enumKeys","$propertyIsEnumerable","E","$getOwnPropertyDescriptor","$getOwnPropertyNames","$getOwnPropertySymbols","IS_OP","es6Symbols","wellKnownSymbols","wksDefine","for","keyFor","useSetter","useSimple","replacer","$replacer","_objectSap","$freeze","$seal","$isFrozen","$isSealed","$getPrototypeOf","_sameValue","y","FProto","nameRE","match","raw","callSite","tpl","fromCharCode","$fromCodePoint","fromCodePoint","code","TO_STRING","$at","pos","charCodeAt","codePointAt","_stringRepeat","str","repeat","MATCH","_isRegexp","isRegExp","_stringContext","searchString","_failsIsRegexp","re","$startsWith","startsWith","context","search","$endsWith","endsWith","endPosition","flags","RegExp","ignoreCase","multiline","unicode","sticky","_fixReWks","SYMBOL","fns","strfn","rxfn","string","$match","regexp","REPLACE","$replace","searchValue","replaceValue","SPLIT","$split","_split","$push","NPCG","limit","separator2","lastIndex","lastLength","output","lastLastIndex","splitLimit","separatorCopy","replace","SEARCH","$search","_createProperty","createProperty","$find","forced","_isFinite","isFinite","_isInteger","isInteger","isSafeInteger","EPSILON","MIN_SAFE_INTEGER","MAX_SAFE_INTEGER","_mathLog1p","log1p","sqrt","$acosh","acosh","Number","MAX_VALUE","$asinh","asinh","$atanh","atanh","_mathSign","sign","cbrt","clz32","LOG2E","cosh","$expm1","expm1","_mathExpm1","EPSILON32","MAX32","MIN32","_mathFround","fround","$abs","$sign","hypot","value1","value2","div","sum","larg","$imul","imul","xn","yn","xl","yl","log10","LOG10E","log2","sinh","tanh","trunc","$includes","_objectToArray","isEntries","$values","getOwnPropertyDescriptors","getDesc","_stringPad","maxLength","fillString","left","stringLength","fillStr","intMaxLength","fillLen","stringFiller","_userAgent","userAgent","padStart","$pad","padEnd","MSIE","time","boundArgs","setInterval","$task","TO_STRING_TAG","ArrayValues","DOMIterables","CSSRuleList","CSSStyleDeclaration","CSSValueList","ClientRectList","DOMRectList","DOMStringList","DOMTokenList","DataTransferItemList","FileList","HTMLAllCollection","HTMLCollection","HTMLFormElement","HTMLSelectElement","MediaList","MimeTypeArray","NamedNodeMap","NodeList","PaintRequestList","Plugin","PluginArray","SVGLengthList","SVGNumberList","SVGPathSegList","SVGPointList","SVGStringList","SVGTransformList","SourceBufferList","StyleSheetList","TextTrackCueList","TextTrackList","TouchList","collections","explicit","Collection","Op","hasOwn","iteratorSymbol","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","toStringTag","runtime","regeneratorRuntime","GenStateSuspendedStart","GenStateSuspendedYield","GenStateExecuting","GenStateCompleted","ContinueSentinel","NativeIteratorPrototype","Gp","GeneratorFunctionPrototype","Generator","GeneratorFunction","displayName","isGeneratorFunction","genFun","ctor","mark","awrap","__await","defineIteratorMethods","AsyncIterator","async","innerFn","outerFn","tryLocsList","pop","Context","reset","skipTempReset","sent","_sent","delegate","tryEntries","resetTryEntry","stop","rootRecord","completion","rval","dispatchException","exception","handle","loc","caught","record","tryLoc","hasCatch","hasFinally","catchLoc","finallyLoc","Error","abrupt","finallyEntry","complete","afterLoc","finish","thrown","delegateYield","resultName","nextLoc","protoGenerator","generator","state","doneResult","delegateResult","maybeInvokeDelegate","tryCatch","makeInvokeMethod","obj","unwrapped","previousPromise","callInvokeWithMethodAndArg","return","info","pushTryEntry","locs","iteratorMethod","ce","CustomEvent","preventDefault","defaultPrevented","params","evt","origPrevent","bubbles","cancelable","detail","createEvent","initCustomEvent","Event","range","factory","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","q","executeCallbacks","depsNotFound","success","loadFile","path","callbackFn","numTries","isCss","doc","maxTries","numRetries","beforeCallbackFn","before","pathStripped","rel","href","onload","onerror","onbeforeload","ev","sheet","cssText","loadjs","paths","arg1","arg2","trim","numWaiting","loadFiles","ready","deps","bundleIds","subscribe","isDefined","providers","types","utils","input","instanceof","Plyr","Boolean","nullOrUndefined","WeakMap","Element","Text","TextTrackCue","VTTCue","TextTrack","array","nodeList","documentMode","platform","url","responseType","request","XMLHttpRequest","parse","responseText","response","statusText","send","hasId","exists","querySelectorAll","container","toggleHidden","setAttribute","support","storage","cached","localStorage","getItem","content","fetch","setItem","injectSprite","innerHTML","body","insertBefore","childNodes","prefix","elements","targets","element","child","cloneNode","parentNode","sibling","nextSibling","text","setAttributes","textContent","removeElement","lastChild","newChild","oldChild","replaceChild","_ref","_ref2","sel","existingAttributes","existing","selector","className","parts","class","hidden","boolean","hasAttribute","removeAttribute","contains","classList","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","querySelector","focused","activeElement","focusable","getElements","trap","keyCode","getFocusElement","shiftKey","focus","on","off","callback","passive","capture","function","Node","toggleListener","events","options","passiveListeners","plyr","dispatchEvent","toggleState","pressed","getAttribute","_len","_key","current","toFixed","parseInt","displayHours","inverted","formatTime","format","hours","getHours","mins","getMinutes","secs","getSeconds","toUpperCase","substr","toLowerCase","replaceAll","toTitleCase","toPascalCase","sources","_len2","_key2","shift","defineProperty$1","extend","toConsumableArray","item","curr","youtube","vimeo","$2","parser","parseUrl","hash","_hash$split2","decodeURIComponent","encodeURIComponent","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","h","offsetHeight","provider","playsinline","api","ui","browser","getBrowser","canPlayInline","isIPhone","video","rangeInput","audio","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","isHTML5","canPlayType","isVideo","isAudio","supported","transitionEndEvent","matchMedia","html5","getSources","sizes","dedupe","player","mime","currentTime","playing","load","play","config","blankVideo","debug","i18n","seekTime","title","toggleClass","selectors","classNames","uiSupported","listeners","warn","toggleNativeControls","controls","inject","setup","volume","muted","speed","loop","quality","updateVolume","timeUpdate","checkPlaying","pip","airplay","isIos","isTouch","touch","_this","setTitle","setPoster","label","buttons","button","isEmbed","getElement","poster","posters","backgroundImage","paused","stopped","toggleControls","loading","timers","_this2","failed","networkState","_this3","inputs","setRange","mute","updateRangeFill","progress","getElementsByTagName","nodeValue","getPercentage","duration","seek","setProgress","buffered","forceHours","invert","invertTime","updateTimeDisplay","seeking","updateProgress","hasDuration","displayDuration","updateSeekTooltip","isWebkit","setProperty","cors","URL","iconUrl","location","host","isIE","svg4everybody","pause","restart","rewind","fastForward","settings","captions","fullscreen","seekTooltip","tooltip","getIconUrl","iconPath","iconPrefix","icon","createElementNS","use","setAttributeNS","attr","badge","menu","buttonType","toCamelCase","labelPressed","iconPressed","control","createIcon","createLabel","getAttributesFromSelector","suffix","checked","radio","faux","insertAdjacentHTML","tooltips","percent","clientRect","getBoundingClientRect","visible","_toggle","pageX","hasClass","parseFloat","setting","tabs","panes","toggleTab","checkMenu","emptyElement","sorting","getLabel","createMenuItem","createBadge","getBadge","updateSetting","pane","active","lang","language","default","getTracks","tracks","track","unshift","isVimeo","_this4","tab","form","show","isMenuItem","isButton","stopPropagation","clone","position","opacity","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setQualityMenu","getQualityOptions","setSpeedMenu","loadSprite","props","update","findElements","repaint","labels","_this6","stored","isYouTube","textTracks","setCaptionsMenu","insertAfter","enabled","hostname","protocol","blob","createObjectURL","setLanguage","setCue","mode","currentTrack","getCurrentTrack","activeCues","embed","enableTextTrack","cue","setText","getCueAsHTML","caption","noop","Console","defaults","userLanguage","onChange","trapFocus","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","overflow","fallback","Fullscreen","property","native","iosNative","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","exitFullscreen","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","Listeners","lastKey","handleKey","toggleMenu","firstTouch","which","altKey","ctrlKey","metaKey","editable","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","keyboard","tabFocus","hideControls","durationUpdate","hasAudio","resetOnEnd","checkLoading","ads","initialized","managerPromise","clickToPlay","ended","disableContextMenu","inputEvent","proxy","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","showHomeTab","showTab","toggleInvert","hover","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","setAspectRatio","Vimeo","loadScript","urls","sdk","padding","paddingBottom","transform","autoplay","buildUrlParams","parseVimeoId","embedContainer","replaceElement","thumbnail_large","pathname","Player","autopause","disableTextTrack","setCurrentTime","selected","setPlaybackRate","setVolume","setLoop","currentSrc","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","getAspectRatio","setAutopause","getVideoTitle","getCurrentTime","getDuration","getTextTracks","cues","stripHTML","seconds","build","mapQualityUnit","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","videoId","getVideoData","google","items","snippet","currentId","parseYouTubeId","generateId","message","playbackRate","getPlaybackRate","getTitle","playVideo","pauseVideo","stopVideo","seekTo","getPlaybackQuality","setPlaybackQuality","getAvailablePlaybackRates","buffering","getVideoLoadedFraction","lastBuffered","levels","getAvailableQualityLevels","level","Ads","publisherId","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","googleIMA","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","displayContainer","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","tagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","_this7","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","cancel","contentComplete","_this8","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","_this9","adError","zIndex","_this10","destroy","handlers","_this11","Date","base","insertElement","attribute","cancelRequests","crossorigin","addStyleHook","insertElements","Storage","json","removeItem","jQuery","tagName","getProviderByUrl","getUrlParams","truthy","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","noTransition","soft","unload","targetTime","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","closest","change","states","webkitPresentationMode","inline","t"],"mappings":"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H,aACC,YACF,UACA,YACE,iBACG,mBACD,wBACM,uBAMN,gDACG,6CACH,wDAGA,yCACA,+GACG,gHAGH,uEAMH,UACA,WACC,aACE,YACD,iBACK,UACP,YACE,cACE,gBACE,SACP,aACI,WACF,aACE,UACH,cACI,sBAQV,WACA,UACA,UACA,UACA,UACA,iBACA,YACA,aACA,iBACA,aACA,eACA,OACA,QACA,QACA,UACA,SACA,UACA,aACA,8BAIA,iBACA,kBACA,mBACA,iBACA,iBACA,gBACA,sBAIA,gBACA,+BAIA,kBACA,mBACA,YACA,cACA,cACA,iBACA,gBACA,gCAMU,uDACC,4BAEI,aACF,0BAEL,4BAEE,2BACC,8BACE,+BACD,mCACK,kCACP,8BACI,oCACE,+BACP,4BACI,iCACC,8BACJ,mCAGA,4BACE,6BACD,+BACG,iCACD,8CAGI,gCACH,+BACF,iCACA,+BACF,+BACE,mCAEF,2BACA,gCAEG,mDAMP,qBACI,kBACH,4BACA,mCACS,sCACR,mBACH,oBACI,wBACA,uBACD,uBACC,wBACA,sBACF,wBACA,sBACE,qBACH,oBACE,6BACM,4BACP,uBACE,6BACI,6BACC,kCAEH,0BACA,mBACD,qCAGG,gCACD,6CAGC,oCACC,4CAGC,6BACH,uCAGG,iCACH,iCAEF,+CAMI,wBACN,oCAMA,oBAMC,cACI,KChYfysC,GAAU/J,GAAMgK,aAEtB,SAASuO,QACAx6C,KAAKm5C,aAKJtJ,EAAS7vC,KAAKqtC,OAAOvI,SAAS8K,QAAQoD,WACxC/Q,GAAMplC,GAAGmoC,QAAQ6K,OACXrH,YAAYqH,EAAQ7vC,KAAKg2C,WAI7BzN,cAAcvoC,KAAKyB,OAAQzB,KAAKg2C,OAAS,kBAAoB,kBAAkB,GAGhFhK,GAAQqD,UACHoL,UAAUj9C,KAAKwC,KAAKqtC,OAAQrtC,KAAKyB,OAAQzB,KAAKg2C,SAI5D,SAAS0E,SAAezzB,EAAgBxmB,UAAAL,OAAA,QAAAjB,IAAAsB,UAAA,IAAAA,UAAA,GAEhCwmB,OACK0zB,kBACEr/C,OAAOs/C,SAAW,IAClBt/C,OAAOu/C,SAAW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","file":"plyr.polyfilled.min.js","sourcesContent":["// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var core = module.exports = { version: '2.5.3' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar TO_STRING = 'toString';\nvar $toString = Function[TO_STRING];\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar uid = require('./_uid');\nvar TYPED = uid('typed_array');\nvar VIEW = uid('view');\nvar ABV = !!(global.ArrayBuffer && global.DataView);\nvar CONSTR = ABV;\nvar i = 0;\nvar l = 9;\nvar Typed;\n\nvar TypedArrayConstructors = (\n 'Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array'\n).split(',');\n\nwhile (i < l) {\n if (Typed = global[TypedArrayConstructors[i++]]) {\n hide(Typed.prototype, TYPED, true);\n hide(Typed.prototype, VIEW, true);\n } else CONSTR = false;\n}\n\nmodule.exports = {\n ABV: ABV,\n CONSTR: CONSTR,\n TYPED: TYPED,\n VIEW: VIEW\n};\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","// https://tc39.github.io/ecma262/#sec-toindex\nvar toInteger = require('./_to-integer');\nvar toLength = require('./_to-length');\nmodule.exports = function (it) {\n if (it === undefined) return 0;\n var number = toInteger(it);\n var length = toLength(number);\n if (number !== length) throw RangeError('Wrong length!');\n return length;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","var global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\nmodule.exports = function (key) {\n return store[key] || (store[key] = {});\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)\nvar $keys = require('./_object-keys-internal');\nvar hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype');\n\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {\n return $keys(O, hiddenKeys);\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)\n'use strict';\nvar toObject = require('./_to-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\nmodule.exports = function fill(value /* , start = 0, end = @length */) {\n var O = toObject(this);\n var length = toLength(O.length);\n var aLen = arguments.length;\n var index = toAbsoluteIndex(aLen > 1 ? arguments[1] : undefined, length);\n var end = aLen > 2 ? arguments[2] : undefined;\n var endPos = end === undefined ? length : toAbsoluteIndex(end, length);\n while (endPos > index) O[index++] = value;\n return O;\n};\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","'use strict';\nvar global = require('./_global');\nvar DESCRIPTORS = require('./_descriptors');\nvar LIBRARY = require('./_library');\nvar $typed = require('./_typed');\nvar hide = require('./_hide');\nvar redefineAll = require('./_redefine-all');\nvar fails = require('./_fails');\nvar anInstance = require('./_an-instance');\nvar toInteger = require('./_to-integer');\nvar toLength = require('./_to-length');\nvar toIndex = require('./_to-index');\nvar gOPN = require('./_object-gopn').f;\nvar dP = require('./_object-dp').f;\nvar arrayFill = require('./_array-fill');\nvar setToStringTag = require('./_set-to-string-tag');\nvar ARRAY_BUFFER = 'ArrayBuffer';\nvar DATA_VIEW = 'DataView';\nvar PROTOTYPE = 'prototype';\nvar WRONG_LENGTH = 'Wrong length!';\nvar WRONG_INDEX = 'Wrong index!';\nvar $ArrayBuffer = global[ARRAY_BUFFER];\nvar $DataView = global[DATA_VIEW];\nvar Math = global.Math;\nvar RangeError = global.RangeError;\n// eslint-disable-next-line no-shadow-restricted-names\nvar Infinity = global.Infinity;\nvar BaseBuffer = $ArrayBuffer;\nvar abs = Math.abs;\nvar pow = Math.pow;\nvar floor = Math.floor;\nvar log = Math.log;\nvar LN2 = Math.LN2;\nvar BUFFER = 'buffer';\nvar BYTE_LENGTH = 'byteLength';\nvar BYTE_OFFSET = 'byteOffset';\nvar $BUFFER = DESCRIPTORS ? '_b' : BUFFER;\nvar $LENGTH = DESCRIPTORS ? '_l' : BYTE_LENGTH;\nvar $OFFSET = DESCRIPTORS ? '_o' : BYTE_OFFSET;\n\n// IEEE754 conversions based on https://github.com/feross/ieee754\nfunction packIEEE754(value, mLen, nBytes) {\n var buffer = new Array(nBytes);\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var rt = mLen === 23 ? pow(2, -24) - pow(2, -77) : 0;\n var i = 0;\n var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;\n var e, m, c;\n value = abs(value);\n // eslint-disable-next-line no-self-compare\n if (value != value || value === Infinity) {\n // eslint-disable-next-line no-self-compare\n m = value != value ? 1 : 0;\n e = eMax;\n } else {\n e = floor(log(value) / LN2);\n if (value * (c = pow(2, -e)) < 1) {\n e--;\n c *= 2;\n }\n if (e + eBias >= 1) {\n value += rt / c;\n } else {\n value += rt * pow(2, 1 - eBias);\n }\n if (value * c >= 2) {\n e++;\n c /= 2;\n }\n if (e + eBias >= eMax) {\n m = 0;\n e = eMax;\n } else if (e + eBias >= 1) {\n m = (value * c - 1) * pow(2, mLen);\n e = e + eBias;\n } else {\n m = value * pow(2, eBias - 1) * pow(2, mLen);\n e = 0;\n }\n }\n for (; mLen >= 8; buffer[i++] = m & 255, m /= 256, mLen -= 8);\n e = e << mLen | m;\n eLen += mLen;\n for (; eLen > 0; buffer[i++] = e & 255, e /= 256, eLen -= 8);\n buffer[--i] |= s * 128;\n return buffer;\n}\nfunction unpackIEEE754(buffer, mLen, nBytes) {\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var nBits = eLen - 7;\n var i = nBytes - 1;\n var s = buffer[i--];\n var e = s & 127;\n var m;\n s >>= 7;\n for (; nBits > 0; e = e * 256 + buffer[i], i--, nBits -= 8);\n m = e & (1 << -nBits) - 1;\n e >>= -nBits;\n nBits += mLen;\n for (; nBits > 0; m = m * 256 + buffer[i], i--, nBits -= 8);\n if (e === 0) {\n e = 1 - eBias;\n } else if (e === eMax) {\n return m ? NaN : s ? -Infinity : Infinity;\n } else {\n m = m + pow(2, mLen);\n e = e - eBias;\n } return (s ? -1 : 1) * m * pow(2, e - mLen);\n}\n\nfunction unpackI32(bytes) {\n return bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];\n}\nfunction packI8(it) {\n return [it & 0xff];\n}\nfunction packI16(it) {\n return [it & 0xff, it >> 8 & 0xff];\n}\nfunction packI32(it) {\n return [it & 0xff, it >> 8 & 0xff, it >> 16 & 0xff, it >> 24 & 0xff];\n}\nfunction packF64(it) {\n return packIEEE754(it, 52, 8);\n}\nfunction packF32(it) {\n return packIEEE754(it, 23, 4);\n}\n\nfunction addGetter(C, key, internal) {\n dP(C[PROTOTYPE], key, { get: function () { return this[internal]; } });\n}\n\nfunction get(view, bytes, index, isLittleEndian) {\n var numIndex = +index;\n var intIndex = toIndex(numIndex);\n if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX);\n var store = view[$BUFFER]._b;\n var start = intIndex + view[$OFFSET];\n var pack = store.slice(start, start + bytes);\n return isLittleEndian ? pack : pack.reverse();\n}\nfunction set(view, bytes, index, conversion, value, isLittleEndian) {\n var numIndex = +index;\n var intIndex = toIndex(numIndex);\n if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX);\n var store = view[$BUFFER]._b;\n var start = intIndex + view[$OFFSET];\n var pack = conversion(+value);\n for (var i = 0; i < bytes; i++) store[start + i] = pack[isLittleEndian ? i : bytes - i - 1];\n}\n\nif (!$typed.ABV) {\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, $ArrayBuffer, ARRAY_BUFFER);\n var byteLength = toIndex(length);\n this._b = arrayFill.call(new Array(byteLength), 0);\n this[$LENGTH] = byteLength;\n };\n\n $DataView = function DataView(buffer, byteOffset, byteLength) {\n anInstance(this, $DataView, DATA_VIEW);\n anInstance(buffer, $ArrayBuffer, DATA_VIEW);\n var bufferLength = buffer[$LENGTH];\n var offset = toInteger(byteOffset);\n if (offset < 0 || offset > bufferLength) throw RangeError('Wrong offset!');\n byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);\n if (offset + byteLength > bufferLength) throw RangeError(WRONG_LENGTH);\n this[$BUFFER] = buffer;\n this[$OFFSET] = offset;\n this[$LENGTH] = byteLength;\n };\n\n if (DESCRIPTORS) {\n addGetter($ArrayBuffer, BYTE_LENGTH, '_l');\n addGetter($DataView, BUFFER, '_b');\n addGetter($DataView, BYTE_LENGTH, '_l');\n addGetter($DataView, BYTE_OFFSET, '_o');\n }\n\n redefineAll($DataView[PROTOTYPE], {\n getInt8: function getInt8(byteOffset) {\n return get(this, 1, byteOffset)[0] << 24 >> 24;\n },\n getUint8: function getUint8(byteOffset) {\n return get(this, 1, byteOffset)[0];\n },\n getInt16: function getInt16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments[1]);\n return (bytes[1] << 8 | bytes[0]) << 16 >> 16;\n },\n getUint16: function getUint16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments[1]);\n return bytes[1] << 8 | bytes[0];\n },\n getInt32: function getInt32(byteOffset /* , littleEndian */) {\n return unpackI32(get(this, 4, byteOffset, arguments[1]));\n },\n getUint32: function getUint32(byteOffset /* , littleEndian */) {\n return unpackI32(get(this, 4, byteOffset, arguments[1])) >>> 0;\n },\n getFloat32: function getFloat32(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 4, byteOffset, arguments[1]), 23, 4);\n },\n getFloat64: function getFloat64(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 8, byteOffset, arguments[1]), 52, 8);\n },\n setInt8: function setInt8(byteOffset, value) {\n set(this, 1, byteOffset, packI8, value);\n },\n setUint8: function setUint8(byteOffset, value) {\n set(this, 1, byteOffset, packI8, value);\n },\n setInt16: function setInt16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packI16, value, arguments[2]);\n },\n setUint16: function setUint16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packI16, value, arguments[2]);\n },\n setInt32: function setInt32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packI32, value, arguments[2]);\n },\n setUint32: function setUint32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packI32, value, arguments[2]);\n },\n setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packF32, value, arguments[2]);\n },\n setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {\n set(this, 8, byteOffset, packF64, value, arguments[2]);\n }\n });\n} else {\n if (!fails(function () {\n $ArrayBuffer(1);\n }) || !fails(function () {\n new $ArrayBuffer(-1); // eslint-disable-line no-new\n }) || fails(function () {\n new $ArrayBuffer(); // eslint-disable-line no-new\n new $ArrayBuffer(1.5); // eslint-disable-line no-new\n new $ArrayBuffer(NaN); // eslint-disable-line no-new\n return $ArrayBuffer.name != ARRAY_BUFFER;\n })) {\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, $ArrayBuffer);\n return new BaseBuffer(toIndex(length));\n };\n var ArrayBufferProto = $ArrayBuffer[PROTOTYPE] = BaseBuffer[PROTOTYPE];\n for (var keys = gOPN(BaseBuffer), j = 0, key; keys.length > j;) {\n if (!((key = keys[j++]) in $ArrayBuffer)) hide($ArrayBuffer, key, BaseBuffer[key]);\n }\n if (!LIBRARY) ArrayBufferProto.constructor = $ArrayBuffer;\n }\n // iOS Safari 7.x bug\n var view = new $DataView(new $ArrayBuffer(2));\n var $setInt8 = $DataView[PROTOTYPE].setInt8;\n view.setInt8(0, 2147483648);\n view.setInt8(1, 2147483649);\n if (view.getInt8(0) || !view.getInt8(1)) redefineAll($DataView[PROTOTYPE], {\n setInt8: function setInt8(byteOffset, value) {\n $setInt8.call(this, byteOffset, value << 24 >> 24);\n },\n setUint8: function setUint8(byteOffset, value) {\n $setInt8.call(this, byteOffset, value << 24 >> 24);\n }\n }, true);\n}\nsetToStringTag($ArrayBuffer, ARRAY_BUFFER);\nsetToStringTag($DataView, DATA_VIEW);\nhide($DataView[PROTOTYPE], $typed.VIEW, true);\nexports[ARRAY_BUFFER] = $ArrayBuffer;\nexports[DATA_VIEW] = $DataView;\n","// 7.3.20 SpeciesConstructor(O, defaultConstructor)\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar SPECIES = require('./_wks')('species');\nmodule.exports = function (O, D) {\n var C = anObject(O).constructor;\n var S;\n return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);\n};\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","'use strict';\nvar $export = require('./_export');\nvar $typed = require('./_typed');\nvar buffer = require('./_typed-buffer');\nvar anObject = require('./_an-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\nvar isObject = require('./_is-object');\nvar ArrayBuffer = require('./_global').ArrayBuffer;\nvar speciesConstructor = require('./_species-constructor');\nvar $ArrayBuffer = buffer.ArrayBuffer;\nvar $DataView = buffer.DataView;\nvar $isView = $typed.ABV && ArrayBuffer.isView;\nvar $slice = $ArrayBuffer.prototype.slice;\nvar VIEW = $typed.VIEW;\nvar ARRAY_BUFFER = 'ArrayBuffer';\n\n$export($export.G + $export.W + $export.F * (ArrayBuffer !== $ArrayBuffer), { ArrayBuffer: $ArrayBuffer });\n\n$export($export.S + $export.F * !$typed.CONSTR, ARRAY_BUFFER, {\n // 24.1.3.1 ArrayBuffer.isView(arg)\n isView: function isView(it) {\n return $isView && $isView(it) || isObject(it) && VIEW in it;\n }\n});\n\n$export($export.P + $export.U + $export.F * require('./_fails')(function () {\n return !new $ArrayBuffer(2).slice(1, undefined).byteLength;\n}), ARRAY_BUFFER, {\n // 24.1.4.3 ArrayBuffer.prototype.slice(start, end)\n slice: function slice(start, end) {\n if ($slice !== undefined && end === undefined) return $slice.call(anObject(this), start); // FF fix\n var len = anObject(this).byteLength;\n var first = toAbsoluteIndex(start, len);\n var final = toAbsoluteIndex(end === undefined ? len : end, len);\n var result = new (speciesConstructor(this, $ArrayBuffer))(toLength(final - first));\n var viewS = new $DataView(this);\n var viewT = new $DataView(result);\n var index = 0;\n while (first < final) {\n viewT.setUint8(index++, viewS.getUint8(first++));\n } return result;\n }\n});\n\nrequire('./_set-species')(ARRAY_BUFFER);\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","module.exports = {};\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","// 22.1.3.31 Array.prototype[@@unscopables]\nvar UNSCOPABLES = require('./_wks')('unscopables');\nvar ArrayProto = Array.prototype;\nif (ArrayProto[UNSCOPABLES] == undefined) require('./_hide')(ArrayProto, UNSCOPABLES, {});\nmodule.exports = function (key) {\n ArrayProto[UNSCOPABLES][key] = true;\n};\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = (!BUGGY && $native) || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","'use strict';\nvar addToUnscopables = require('./_add-to-unscopables');\nvar step = require('./_iter-step');\nvar Iterators = require('./_iterators');\nvar toIObject = require('./_to-iobject');\n\n// 22.1.3.4 Array.prototype.entries()\n// 22.1.3.13 Array.prototype.keys()\n// 22.1.3.29 Array.prototype.values()\n// 22.1.3.30 Array.prototype[@@iterator]()\nmodule.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) {\n this._t = toIObject(iterated); // target\n this._i = 0; // next index\n this._k = kind; // kind\n// 22.1.5.2.1 %ArrayIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var kind = this._k;\n var index = this._i++;\n if (!O || index >= O.length) {\n this._t = undefined;\n return step(1);\n }\n if (kind == 'keys') return step(0, index);\n if (kind == 'values') return step(0, O[index]);\n return step(0, [index, O[index]]);\n}, 'values');\n\n// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)\nIterators.Arguments = Iterators.Array;\n\naddToUnscopables('keys');\naddToUnscopables('values');\naddToUnscopables('entries');\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)\n'use strict';\nvar toObject = require('./_to-object');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar toLength = require('./_to-length');\n\nmodule.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {\n var O = toObject(this);\n var len = toLength(O.length);\n var to = toAbsoluteIndex(target, len);\n var from = toAbsoluteIndex(start, len);\n var end = arguments.length > 2 ? arguments[2] : undefined;\n var count = Math.min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);\n var inc = 1;\n if (from < to && to < from + count) {\n inc = -1;\n from += count - 1;\n to += count - 1;\n }\n while (count-- > 0) {\n if (from in O) O[to] = O[from];\n else delete O[to];\n to += inc;\n from += inc;\n } return O;\n};\n","exports.f = {}.propertyIsEnumerable;\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","'use strict';\nif (require('./_descriptors')) {\n var LIBRARY = require('./_library');\n var global = require('./_global');\n var fails = require('./_fails');\n var $export = require('./_export');\n var $typed = require('./_typed');\n var $buffer = require('./_typed-buffer');\n var ctx = require('./_ctx');\n var anInstance = require('./_an-instance');\n var propertyDesc = require('./_property-desc');\n var hide = require('./_hide');\n var redefineAll = require('./_redefine-all');\n var toInteger = require('./_to-integer');\n var toLength = require('./_to-length');\n var toIndex = require('./_to-index');\n var toAbsoluteIndex = require('./_to-absolute-index');\n var toPrimitive = require('./_to-primitive');\n var has = require('./_has');\n var classof = require('./_classof');\n var isObject = require('./_is-object');\n var toObject = require('./_to-object');\n var isArrayIter = require('./_is-array-iter');\n var create = require('./_object-create');\n var getPrototypeOf = require('./_object-gpo');\n var gOPN = require('./_object-gopn').f;\n var getIterFn = require('./core.get-iterator-method');\n var uid = require('./_uid');\n var wks = require('./_wks');\n var createArrayMethod = require('./_array-methods');\n var createArrayIncludes = require('./_array-includes');\n var speciesConstructor = require('./_species-constructor');\n var ArrayIterators = require('./es6.array.iterator');\n var Iterators = require('./_iterators');\n var $iterDetect = require('./_iter-detect');\n var setSpecies = require('./_set-species');\n var arrayFill = require('./_array-fill');\n var arrayCopyWithin = require('./_array-copy-within');\n var $DP = require('./_object-dp');\n var $GOPD = require('./_object-gopd');\n var dP = $DP.f;\n var gOPD = $GOPD.f;\n var RangeError = global.RangeError;\n var TypeError = global.TypeError;\n var Uint8Array = global.Uint8Array;\n var ARRAY_BUFFER = 'ArrayBuffer';\n var SHARED_BUFFER = 'Shared' + ARRAY_BUFFER;\n var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';\n var PROTOTYPE = 'prototype';\n var ArrayProto = Array[PROTOTYPE];\n var $ArrayBuffer = $buffer.ArrayBuffer;\n var $DataView = $buffer.DataView;\n var arrayForEach = createArrayMethod(0);\n var arrayFilter = createArrayMethod(2);\n var arraySome = createArrayMethod(3);\n var arrayEvery = createArrayMethod(4);\n var arrayFind = createArrayMethod(5);\n var arrayFindIndex = createArrayMethod(6);\n var arrayIncludes = createArrayIncludes(true);\n var arrayIndexOf = createArrayIncludes(false);\n var arrayValues = ArrayIterators.values;\n var arrayKeys = ArrayIterators.keys;\n var arrayEntries = ArrayIterators.entries;\n var arrayLastIndexOf = ArrayProto.lastIndexOf;\n var arrayReduce = ArrayProto.reduce;\n var arrayReduceRight = ArrayProto.reduceRight;\n var arrayJoin = ArrayProto.join;\n var arraySort = ArrayProto.sort;\n var arraySlice = ArrayProto.slice;\n var arrayToString = ArrayProto.toString;\n var arrayToLocaleString = ArrayProto.toLocaleString;\n var ITERATOR = wks('iterator');\n var TAG = wks('toStringTag');\n var TYPED_CONSTRUCTOR = uid('typed_constructor');\n var DEF_CONSTRUCTOR = uid('def_constructor');\n var ALL_CONSTRUCTORS = $typed.CONSTR;\n var TYPED_ARRAY = $typed.TYPED;\n var VIEW = $typed.VIEW;\n var WRONG_LENGTH = 'Wrong length!';\n\n var $map = createArrayMethod(1, function (O, length) {\n return allocate(speciesConstructor(O, O[DEF_CONSTRUCTOR]), length);\n });\n\n var LITTLE_ENDIAN = fails(function () {\n // eslint-disable-next-line no-undef\n return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\n });\n\n var FORCED_SET = !!Uint8Array && !!Uint8Array[PROTOTYPE].set && fails(function () {\n new Uint8Array(1).set({});\n });\n\n var toOffset = function (it, BYTES) {\n var offset = toInteger(it);\n if (offset < 0 || offset % BYTES) throw RangeError('Wrong offset!');\n return offset;\n };\n\n var validate = function (it) {\n if (isObject(it) && TYPED_ARRAY in it) return it;\n throw TypeError(it + ' is not a typed array!');\n };\n\n var allocate = function (C, length) {\n if (!(isObject(C) && TYPED_CONSTRUCTOR in C)) {\n throw TypeError('It is not a typed array constructor!');\n } return new C(length);\n };\n\n var speciesFromList = function (O, list) {\n return fromList(speciesConstructor(O, O[DEF_CONSTRUCTOR]), list);\n };\n\n var fromList = function (C, list) {\n var index = 0;\n var length = list.length;\n var result = allocate(C, length);\n while (length > index) result[index] = list[index++];\n return result;\n };\n\n var addGetter = function (it, key, internal) {\n dP(it, key, { get: function () { return this._d[internal]; } });\n };\n\n var $from = function from(source /* , mapfn, thisArg */) {\n var O = toObject(source);\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var iterFn = getIterFn(O);\n var i, length, values, result, step, iterator;\n if (iterFn != undefined && !isArrayIter(iterFn)) {\n for (iterator = iterFn.call(O), values = [], i = 0; !(step = iterator.next()).done; i++) {\n values.push(step.value);\n } O = values;\n }\n if (mapping && aLen > 2) mapfn = ctx(mapfn, arguments[2], 2);\n for (i = 0, length = toLength(O.length), result = allocate(this, length); length > i; i++) {\n result[i] = mapping ? mapfn(O[i], i) : O[i];\n }\n return result;\n };\n\n var $of = function of(/* ...items */) {\n var index = 0;\n var length = arguments.length;\n var result = allocate(this, length);\n while (length > index) result[index] = arguments[index++];\n return result;\n };\n\n // iOS Safari 6.x fails here\n var TO_LOCALE_BUG = !!Uint8Array && fails(function () { arrayToLocaleString.call(new Uint8Array(1)); });\n\n var $toLocaleString = function toLocaleString() {\n return arrayToLocaleString.apply(TO_LOCALE_BUG ? arraySlice.call(validate(this)) : validate(this), arguments);\n };\n\n var proto = {\n copyWithin: function copyWithin(target, start /* , end */) {\n return arrayCopyWithin.call(validate(this), target, start, arguments.length > 2 ? arguments[2] : undefined);\n },\n every: function every(callbackfn /* , thisArg */) {\n return arrayEvery(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n fill: function fill(value /* , start, end */) { // eslint-disable-line no-unused-vars\n return arrayFill.apply(validate(this), arguments);\n },\n filter: function filter(callbackfn /* , thisArg */) {\n return speciesFromList(this, arrayFilter(validate(this), callbackfn,\n arguments.length > 1 ? arguments[1] : undefined));\n },\n find: function find(predicate /* , thisArg */) {\n return arrayFind(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined);\n },\n findIndex: function findIndex(predicate /* , thisArg */) {\n return arrayFindIndex(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined);\n },\n forEach: function forEach(callbackfn /* , thisArg */) {\n arrayForEach(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n indexOf: function indexOf(searchElement /* , fromIndex */) {\n return arrayIndexOf(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);\n },\n includes: function includes(searchElement /* , fromIndex */) {\n return arrayIncludes(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);\n },\n join: function join(separator) { // eslint-disable-line no-unused-vars\n return arrayJoin.apply(validate(this), arguments);\n },\n lastIndexOf: function lastIndexOf(searchElement /* , fromIndex */) { // eslint-disable-line no-unused-vars\n return arrayLastIndexOf.apply(validate(this), arguments);\n },\n map: function map(mapfn /* , thisArg */) {\n return $map(validate(this), mapfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n reduce: function reduce(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars\n return arrayReduce.apply(validate(this), arguments);\n },\n reduceRight: function reduceRight(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars\n return arrayReduceRight.apply(validate(this), arguments);\n },\n reverse: function reverse() {\n var that = this;\n var length = validate(that).length;\n var middle = Math.floor(length / 2);\n var index = 0;\n var value;\n while (index < middle) {\n value = that[index];\n that[index++] = that[--length];\n that[length] = value;\n } return that;\n },\n some: function some(callbackfn /* , thisArg */) {\n return arraySome(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n },\n sort: function sort(comparefn) {\n return arraySort.call(validate(this), comparefn);\n },\n subarray: function subarray(begin, end) {\n var O = validate(this);\n var length = O.length;\n var $begin = toAbsoluteIndex(begin, length);\n return new (speciesConstructor(O, O[DEF_CONSTRUCTOR]))(\n O.buffer,\n O.byteOffset + $begin * O.BYTES_PER_ELEMENT,\n toLength((end === undefined ? length : toAbsoluteIndex(end, length)) - $begin)\n );\n }\n };\n\n var $slice = function slice(start, end) {\n return speciesFromList(this, arraySlice.call(validate(this), start, end));\n };\n\n var $set = function set(arrayLike /* , offset */) {\n validate(this);\n var offset = toOffset(arguments[1], 1);\n var length = this.length;\n var src = toObject(arrayLike);\n var len = toLength(src.length);\n var index = 0;\n if (len + offset > length) throw RangeError(WRONG_LENGTH);\n while (index < len) this[offset + index] = src[index++];\n };\n\n var $iterators = {\n entries: function entries() {\n return arrayEntries.call(validate(this));\n },\n keys: function keys() {\n return arrayKeys.call(validate(this));\n },\n values: function values() {\n return arrayValues.call(validate(this));\n }\n };\n\n var isTAIndex = function (target, key) {\n return isObject(target)\n && target[TYPED_ARRAY]\n && typeof key != 'symbol'\n && key in target\n && String(+key) == String(key);\n };\n var $getDesc = function getOwnPropertyDescriptor(target, key) {\n return isTAIndex(target, key = toPrimitive(key, true))\n ? propertyDesc(2, target[key])\n : gOPD(target, key);\n };\n var $setDesc = function defineProperty(target, key, desc) {\n if (isTAIndex(target, key = toPrimitive(key, true))\n && isObject(desc)\n && has(desc, 'value')\n && !has(desc, 'get')\n && !has(desc, 'set')\n // TODO: add validation descriptor w/o calling accessors\n && !desc.configurable\n && (!has(desc, 'writable') || desc.writable)\n && (!has(desc, 'enumerable') || desc.enumerable)\n ) {\n target[key] = desc.value;\n return target;\n } return dP(target, key, desc);\n };\n\n if (!ALL_CONSTRUCTORS) {\n $GOPD.f = $getDesc;\n $DP.f = $setDesc;\n }\n\n $export($export.S + $export.F * !ALL_CONSTRUCTORS, 'Object', {\n getOwnPropertyDescriptor: $getDesc,\n defineProperty: $setDesc\n });\n\n if (fails(function () { arrayToString.call({}); })) {\n arrayToString = arrayToLocaleString = function toString() {\n return arrayJoin.call(this);\n };\n }\n\n var $TypedArrayPrototype$ = redefineAll({}, proto);\n redefineAll($TypedArrayPrototype$, $iterators);\n hide($TypedArrayPrototype$, ITERATOR, $iterators.values);\n redefineAll($TypedArrayPrototype$, {\n slice: $slice,\n set: $set,\n constructor: function () { /* noop */ },\n toString: arrayToString,\n toLocaleString: $toLocaleString\n });\n addGetter($TypedArrayPrototype$, 'buffer', 'b');\n addGetter($TypedArrayPrototype$, 'byteOffset', 'o');\n addGetter($TypedArrayPrototype$, 'byteLength', 'l');\n addGetter($TypedArrayPrototype$, 'length', 'e');\n dP($TypedArrayPrototype$, TAG, {\n get: function () { return this[TYPED_ARRAY]; }\n });\n\n // eslint-disable-next-line max-statements\n module.exports = function (KEY, BYTES, wrapper, CLAMPED) {\n CLAMPED = !!CLAMPED;\n var NAME = KEY + (CLAMPED ? 'Clamped' : '') + 'Array';\n var GETTER = 'get' + KEY;\n var SETTER = 'set' + KEY;\n var TypedArray = global[NAME];\n var Base = TypedArray || {};\n var TAC = TypedArray && getPrototypeOf(TypedArray);\n var FORCED = !TypedArray || !$typed.ABV;\n var O = {};\n var TypedArrayPrototype = TypedArray && TypedArray[PROTOTYPE];\n var getter = function (that, index) {\n var data = that._d;\n return data.v[GETTER](index * BYTES + data.o, LITTLE_ENDIAN);\n };\n var setter = function (that, index, value) {\n var data = that._d;\n if (CLAMPED) value = (value = Math.round(value)) < 0 ? 0 : value > 0xff ? 0xff : value & 0xff;\n data.v[SETTER](index * BYTES + data.o, value, LITTLE_ENDIAN);\n };\n var addElement = function (that, index) {\n dP(that, index, {\n get: function () {\n return getter(this, index);\n },\n set: function (value) {\n return setter(this, index, value);\n },\n enumerable: true\n });\n };\n if (FORCED) {\n TypedArray = wrapper(function (that, data, $offset, $length) {\n anInstance(that, TypedArray, NAME, '_d');\n var index = 0;\n var offset = 0;\n var buffer, byteLength, length, klass;\n if (!isObject(data)) {\n length = toIndex(data);\n byteLength = length * BYTES;\n buffer = new $ArrayBuffer(byteLength);\n } else if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) {\n buffer = data;\n offset = toOffset($offset, BYTES);\n var $len = data.byteLength;\n if ($length === undefined) {\n if ($len % BYTES) throw RangeError(WRONG_LENGTH);\n byteLength = $len - offset;\n if (byteLength < 0) throw RangeError(WRONG_LENGTH);\n } else {\n byteLength = toLength($length) * BYTES;\n if (byteLength + offset > $len) throw RangeError(WRONG_LENGTH);\n }\n length = byteLength / BYTES;\n } else if (TYPED_ARRAY in data) {\n return fromList(TypedArray, data);\n } else {\n return $from.call(TypedArray, data);\n }\n hide(that, '_d', {\n b: buffer,\n o: offset,\n l: byteLength,\n e: length,\n v: new $DataView(buffer)\n });\n while (index < length) addElement(that, index++);\n });\n TypedArrayPrototype = TypedArray[PROTOTYPE] = create($TypedArrayPrototype$);\n hide(TypedArrayPrototype, 'constructor', TypedArray);\n } else if (!fails(function () {\n TypedArray(1);\n }) || !fails(function () {\n new TypedArray(-1); // eslint-disable-line no-new\n }) || !$iterDetect(function (iter) {\n new TypedArray(); // eslint-disable-line no-new\n new TypedArray(null); // eslint-disable-line no-new\n new TypedArray(1.5); // eslint-disable-line no-new\n new TypedArray(iter); // eslint-disable-line no-new\n }, true)) {\n TypedArray = wrapper(function (that, data, $offset, $length) {\n anInstance(that, TypedArray, NAME);\n var klass;\n // `ws` module bug, temporarily remove validation length for Uint8Array\n // https://github.com/websockets/ws/pull/645\n if (!isObject(data)) return new Base(toIndex(data));\n if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) {\n return $length !== undefined\n ? new Base(data, toOffset($offset, BYTES), $length)\n : $offset !== undefined\n ? new Base(data, toOffset($offset, BYTES))\n : new Base(data);\n }\n if (TYPED_ARRAY in data) return fromList(TypedArray, data);\n return $from.call(TypedArray, data);\n });\n arrayForEach(TAC !== Function.prototype ? gOPN(Base).concat(gOPN(TAC)) : gOPN(Base), function (key) {\n if (!(key in TypedArray)) hide(TypedArray, key, Base[key]);\n });\n TypedArray[PROTOTYPE] = TypedArrayPrototype;\n if (!LIBRARY) TypedArrayPrototype.constructor = TypedArray;\n }\n var $nativeIterator = TypedArrayPrototype[ITERATOR];\n var CORRECT_ITER_NAME = !!$nativeIterator\n && ($nativeIterator.name == 'values' || $nativeIterator.name == undefined);\n var $iterator = $iterators.values;\n hide(TypedArray, TYPED_CONSTRUCTOR, true);\n hide(TypedArrayPrototype, TYPED_ARRAY, NAME);\n hide(TypedArrayPrototype, VIEW, true);\n hide(TypedArrayPrototype, DEF_CONSTRUCTOR, TypedArray);\n\n if (CLAMPED ? new TypedArray(1)[TAG] != NAME : !(TAG in TypedArrayPrototype)) {\n dP(TypedArrayPrototype, TAG, {\n get: function () { return NAME; }\n });\n }\n\n O[NAME] = TypedArray;\n\n $export($export.G + $export.W + $export.F * (TypedArray != Base), O);\n\n $export($export.S, NAME, {\n BYTES_PER_ELEMENT: BYTES\n });\n\n $export($export.S + $export.F * fails(function () { Base.of.call(TypedArray, 1); }), NAME, {\n from: $from,\n of: $of\n });\n\n if (!(BYTES_PER_ELEMENT in TypedArrayPrototype)) hide(TypedArrayPrototype, BYTES_PER_ELEMENT, BYTES);\n\n $export($export.P, NAME, proto);\n\n setSpecies(NAME);\n\n $export($export.P + $export.F * FORCED_SET, NAME, { set: $set });\n\n $export($export.P + $export.F * !CORRECT_ITER_NAME, NAME, $iterators);\n\n if (!LIBRARY && TypedArrayPrototype.toString != arrayToString) TypedArrayPrototype.toString = arrayToString;\n\n $export($export.P + $export.F * fails(function () {\n new TypedArray(1).slice();\n }), NAME, { slice: $slice });\n\n $export($export.P + $export.F * (fails(function () {\n return [1, 2].toLocaleString() != new TypedArray([1, 2]).toLocaleString();\n }) || !fails(function () {\n TypedArrayPrototype.toLocaleString.call([1, 2]);\n })), NAME, { toLocaleString: $toLocaleString });\n\n Iterators[NAME] = CORRECT_ITER_NAME ? $nativeIterator : $iterator;\n if (!LIBRARY && !CORRECT_ITER_NAME) hide(TypedArrayPrototype, ITERATOR, $iterator);\n };\n} else module.exports = function () { /* empty */ };\n","require('./_typed-array')('Int8', 1, function (init) {\n return function Int8Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint8', 1, function (init) {\n return function Uint8Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint8', 1, function (init) {\n return function Uint8ClampedArray(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n}, true);\n","require('./_typed-array')('Int16', 2, function (init) {\n return function Int16Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint16', 2, function (init) {\n return function Uint16Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Int32', 4, function (init) {\n return function Int32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Uint32', 4, function (init) {\n return function Uint32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Float32', 4, function (init) {\n return function Float32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","require('./_typed-array')('Float64', 8, function (init) {\n return function Float64Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","'use strict';\nvar dP = require('./_object-dp').f;\nvar create = require('./_object-create');\nvar redefineAll = require('./_redefine-all');\nvar ctx = require('./_ctx');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar $iterDefine = require('./_iter-define');\nvar step = require('./_iter-step');\nvar setSpecies = require('./_set-species');\nvar DESCRIPTORS = require('./_descriptors');\nvar fastKey = require('./_meta').fastKey;\nvar validate = require('./_validate-collection');\nvar SIZE = DESCRIPTORS ? '_s' : 'size';\n\nvar getEntry = function (that, key) {\n // fast case\n var index = fastKey(key);\n var entry;\n if (index !== 'F') return that._i[index];\n // frozen object case\n for (entry = that._f; entry; entry = entry.n) {\n if (entry.k == key) return entry;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = create(null); // index\n that._f = undefined; // first entry\n that._l = undefined; // last entry\n that[SIZE] = 0; // size\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.1.3.1 Map.prototype.clear()\n // 23.2.3.2 Set.prototype.clear()\n clear: function clear() {\n for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {\n entry.r = true;\n if (entry.p) entry.p = entry.p.n = undefined;\n delete data[entry.i];\n }\n that._f = that._l = undefined;\n that[SIZE] = 0;\n },\n // 23.1.3.3 Map.prototype.delete(key)\n // 23.2.3.4 Set.prototype.delete(value)\n 'delete': function (key) {\n var that = validate(this, NAME);\n var entry = getEntry(that, key);\n if (entry) {\n var next = entry.n;\n var prev = entry.p;\n delete that._i[entry.i];\n entry.r = true;\n if (prev) prev.n = next;\n if (next) next.p = prev;\n if (that._f == entry) that._f = next;\n if (that._l == entry) that._l = prev;\n that[SIZE]--;\n } return !!entry;\n },\n // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)\n // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)\n forEach: function forEach(callbackfn /* , that = undefined */) {\n validate(this, NAME);\n var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);\n var entry;\n while (entry = entry ? entry.n : this._f) {\n f(entry.v, entry.k, this);\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n }\n },\n // 23.1.3.7 Map.prototype.has(key)\n // 23.2.3.7 Set.prototype.has(value)\n has: function has(key) {\n return !!getEntry(validate(this, NAME), key);\n }\n });\n if (DESCRIPTORS) dP(C.prototype, 'size', {\n get: function () {\n return validate(this, NAME)[SIZE];\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var entry = getEntry(that, key);\n var prev, index;\n // change existing entry\n if (entry) {\n entry.v = value;\n // create new entry\n } else {\n that._l = entry = {\n i: index = fastKey(key, true), // <- index\n k: key, // <- key\n v: value, // <- value\n p: prev = that._l, // <- previous entry\n n: undefined, // <- next entry\n r: false // <- removed\n };\n if (!that._f) that._f = entry;\n if (prev) prev.n = entry;\n that[SIZE]++;\n // add to index\n if (index !== 'F') that._i[index] = entry;\n } return that;\n },\n getEntry: getEntry,\n setStrong: function (C, NAME, IS_MAP) {\n // add .keys, .values, .entries, [@@iterator]\n // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11\n $iterDefine(C, NAME, function (iterated, kind) {\n this._t = validate(iterated, NAME); // target\n this._k = kind; // kind\n this._l = undefined; // previous\n }, function () {\n var that = this;\n var kind = that._k;\n var entry = that._l;\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n // get next entry\n if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {\n // or finish the iteration\n that._t = undefined;\n return step(1);\n }\n // return step by kind\n if (kind == 'keys') return step(0, entry.k);\n if (kind == 'values') return step(0, entry.v);\n return step(0, [entry.k, entry.v]);\n }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);\n\n // add [@@species], 23.1.2.2, 23.2.2.2\n setSpecies(NAME);\n }\n};\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar MAP = 'Map';\n\n// 23.1 Map Objects\nmodule.exports = require('./_collection')(MAP, function (get) {\n return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.1.3.6 Map.prototype.get(key)\n get: function get(key) {\n var entry = strong.getEntry(validate(this, MAP), key);\n return entry && entry.v;\n },\n // 23.1.3.9 Map.prototype.set(key, value)\n set: function set(key, value) {\n return strong.def(validate(this, MAP), key === 0 ? 0 : key, value);\n }\n}, strong, true);\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar SET = 'Set';\n\n// 23.2 Set Objects\nmodule.exports = require('./_collection')(SET, function (get) {\n return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.2.3.1 Set.prototype.add(value)\n add: function add(value) {\n return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);\n }\n}, strong);\n","exports.f = Object.getOwnPropertySymbols;\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];\n } return T;\n} : $assign;\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar validate = require('./_validate-collection');\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar tmp = {};\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","'use strict';\nvar weak = require('./_collection-weak');\nvar validate = require('./_validate-collection');\nvar WEAK_SET = 'WeakSet';\n\n// 23.4 WeakSet Objects\nrequire('./_collection')(WEAK_SET, function (get) {\n return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.4.3.1 WeakSet.prototype.add(value)\n add: function add(value) {\n return weak.def(validate(this, WEAK_SET), value, true);\n }\n}, weak, false, true);\n","// 26.1.1 Reflect.apply(target, thisArgument, argumentsList)\nvar $export = require('./_export');\nvar aFunction = require('./_a-function');\nvar anObject = require('./_an-object');\nvar rApply = (require('./_global').Reflect || {}).apply;\nvar fApply = Function.apply;\n// MS Edge argumentsList argument is optional\n$export($export.S + $export.F * !require('./_fails')(function () {\n rApply(function () { /* empty */ });\n}), 'Reflect', {\n apply: function apply(target, thisArgument, argumentsList) {\n var T = aFunction(target);\n var L = anObject(argumentsList);\n return rApply ? rApply(T, thisArgument, L) : fApply.call(T, thisArgument, L);\n }\n});\n","// fast apply, http://jsperf.lnkit.com/fast-apply/5\nmodule.exports = function (fn, args, that) {\n var un = that === undefined;\n switch (args.length) {\n case 0: return un ? fn()\n : fn.call(that);\n case 1: return un ? fn(args[0])\n : fn.call(that, args[0]);\n case 2: return un ? fn(args[0], args[1])\n : fn.call(that, args[0], args[1]);\n case 3: return un ? fn(args[0], args[1], args[2])\n : fn.call(that, args[0], args[1], args[2]);\n case 4: return un ? fn(args[0], args[1], args[2], args[3])\n : fn.call(that, args[0], args[1], args[2], args[3]);\n } return fn.apply(that, args);\n};\n","'use strict';\nvar aFunction = require('./_a-function');\nvar isObject = require('./_is-object');\nvar invoke = require('./_invoke');\nvar arraySlice = [].slice;\nvar factories = {};\n\nvar construct = function (F, len, args) {\n if (!(len in factories)) {\n for (var n = [], i = 0; i < len; i++) n[i] = 'a[' + i + ']';\n // eslint-disable-next-line no-new-func\n factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')');\n } return factories[len](F, args);\n};\n\nmodule.exports = Function.bind || function bind(that /* , ...args */) {\n var fn = aFunction(this);\n var partArgs = arraySlice.call(arguments, 1);\n var bound = function (/* args... */) {\n var args = partArgs.concat(arraySlice.call(arguments));\n return this instanceof bound ? construct(fn, args.length, args) : invoke(fn, args, that);\n };\n if (isObject(fn.prototype)) bound.prototype = fn.prototype;\n return bound;\n};\n","// 26.1.2 Reflect.construct(target, argumentsList [, newTarget])\nvar $export = require('./_export');\nvar create = require('./_object-create');\nvar aFunction = require('./_a-function');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar bind = require('./_bind');\nvar rConstruct = (require('./_global').Reflect || {}).construct;\n\n// MS Edge supports only 2 arguments and argumentsList argument is optional\n// FF Nightly sets third argument as `new.target`, but does not create `this` from it\nvar NEW_TARGET_BUG = fails(function () {\n function F() { /* empty */ }\n return !(rConstruct(function () { /* empty */ }, [], F) instanceof F);\n});\nvar ARGS_BUG = !fails(function () {\n rConstruct(function () { /* empty */ });\n});\n\n$export($export.S + $export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', {\n construct: function construct(Target, args /* , newTarget */) {\n aFunction(Target);\n anObject(args);\n var newTarget = arguments.length < 3 ? Target : aFunction(arguments[2]);\n if (ARGS_BUG && !NEW_TARGET_BUG) return rConstruct(Target, args, newTarget);\n if (Target == newTarget) {\n // w/o altered newTarget, optimization for 0-4 arguments\n switch (args.length) {\n case 0: return new Target();\n case 1: return new Target(args[0]);\n case 2: return new Target(args[0], args[1]);\n case 3: return new Target(args[0], args[1], args[2]);\n case 4: return new Target(args[0], args[1], args[2], args[3]);\n }\n // w/o altered newTarget, lot of arguments case\n var $args = [null];\n $args.push.apply($args, args);\n return new (bind.apply(Target, $args))();\n }\n // with altered newTarget, not support built-in constructors\n var proto = newTarget.prototype;\n var instance = create(isObject(proto) ? proto : Object.prototype);\n var result = Function.apply.call(Target, instance, args);\n return isObject(result) ? result : instance;\n }\n});\n","// 26.1.3 Reflect.defineProperty(target, propertyKey, attributes)\nvar dP = require('./_object-dp');\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar toPrimitive = require('./_to-primitive');\n\n// MS Edge has broken Reflect.defineProperty - throwing instead of returning false\n$export($export.S + $export.F * require('./_fails')(function () {\n // eslint-disable-next-line no-undef\n Reflect.defineProperty(dP.f({}, 1, { value: 1 }), 1, { value: 2 });\n}), 'Reflect', {\n defineProperty: function defineProperty(target, propertyKey, attributes) {\n anObject(target);\n propertyKey = toPrimitive(propertyKey, true);\n anObject(attributes);\n try {\n dP.f(target, propertyKey, attributes);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","// 26.1.4 Reflect.deleteProperty(target, propertyKey)\nvar $export = require('./_export');\nvar gOPD = require('./_object-gopd').f;\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n deleteProperty: function deleteProperty(target, propertyKey) {\n var desc = gOPD(anObject(target), propertyKey);\n return desc && !desc.configurable ? false : delete target[propertyKey];\n }\n});\n","// 26.1.6 Reflect.get(target, propertyKey [, receiver])\nvar gOPD = require('./_object-gopd');\nvar getPrototypeOf = require('./_object-gpo');\nvar has = require('./_has');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\n\nfunction get(target, propertyKey /* , receiver */) {\n var receiver = arguments.length < 3 ? target : arguments[2];\n var desc, proto;\n if (anObject(target) === receiver) return target[propertyKey];\n if (desc = gOPD.f(target, propertyKey)) return has(desc, 'value')\n ? desc.value\n : desc.get !== undefined\n ? desc.get.call(receiver)\n : undefined;\n if (isObject(proto = getPrototypeOf(target))) return get(proto, propertyKey, receiver);\n}\n\n$export($export.S, 'Reflect', { get: get });\n","// 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey)\nvar gOPD = require('./_object-gopd');\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey) {\n return gOPD.f(anObject(target), propertyKey);\n }\n});\n","// 26.1.8 Reflect.getPrototypeOf(target)\nvar $export = require('./_export');\nvar getProto = require('./_object-gpo');\nvar anObject = require('./_an-object');\n\n$export($export.S, 'Reflect', {\n getPrototypeOf: function getPrototypeOf(target) {\n return getProto(anObject(target));\n }\n});\n","// 26.1.9 Reflect.has(target, propertyKey)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', {\n has: function has(target, propertyKey) {\n return propertyKey in target;\n }\n});\n","// 26.1.10 Reflect.isExtensible(target)\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar $isExtensible = Object.isExtensible;\n\n$export($export.S, 'Reflect', {\n isExtensible: function isExtensible(target) {\n anObject(target);\n return $isExtensible ? $isExtensible(target) : true;\n }\n});\n","// all object keys, includes non-enumerable and symbols\nvar gOPN = require('./_object-gopn');\nvar gOPS = require('./_object-gops');\nvar anObject = require('./_an-object');\nvar Reflect = require('./_global').Reflect;\nmodule.exports = Reflect && Reflect.ownKeys || function ownKeys(it) {\n var keys = gOPN.f(anObject(it));\n var getSymbols = gOPS.f;\n return getSymbols ? keys.concat(getSymbols(it)) : keys;\n};\n","// 26.1.11 Reflect.ownKeys(target)\nvar $export = require('./_export');\n\n$export($export.S, 'Reflect', { ownKeys: require('./_own-keys') });\n","// 26.1.12 Reflect.preventExtensions(target)\nvar $export = require('./_export');\nvar anObject = require('./_an-object');\nvar $preventExtensions = Object.preventExtensions;\n\n$export($export.S, 'Reflect', {\n preventExtensions: function preventExtensions(target) {\n anObject(target);\n try {\n if ($preventExtensions) $preventExtensions(target);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","// 26.1.13 Reflect.set(target, propertyKey, V [, receiver])\nvar dP = require('./_object-dp');\nvar gOPD = require('./_object-gopd');\nvar getPrototypeOf = require('./_object-gpo');\nvar has = require('./_has');\nvar $export = require('./_export');\nvar createDesc = require('./_property-desc');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\n\nfunction set(target, propertyKey, V /* , receiver */) {\n var receiver = arguments.length < 4 ? target : arguments[3];\n var ownDesc = gOPD.f(anObject(target), propertyKey);\n var existingDescriptor, proto;\n if (!ownDesc) {\n if (isObject(proto = getPrototypeOf(target))) {\n return set(proto, propertyKey, V, receiver);\n }\n ownDesc = createDesc(0);\n }\n if (has(ownDesc, 'value')) {\n if (ownDesc.writable === false || !isObject(receiver)) return false;\n existingDescriptor = gOPD.f(receiver, propertyKey) || createDesc(0);\n existingDescriptor.value = V;\n dP.f(receiver, propertyKey, existingDescriptor);\n return true;\n }\n return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true);\n}\n\n$export($export.S, 'Reflect', { set: set });\n","// 26.1.14 Reflect.setPrototypeOf(target, proto)\nvar $export = require('./_export');\nvar setProto = require('./_set-proto');\n\nif (setProto) $export($export.S, 'Reflect', {\n setPrototypeOf: function setPrototypeOf(target, proto) {\n setProto.check(target, proto);\n try {\n setProto.set(target, proto);\n return true;\n } catch (e) {\n return false;\n }\n }\n});\n","var ctx = require('./_ctx');\nvar invoke = require('./_invoke');\nvar html = require('./_html');\nvar cel = require('./_dom-create');\nvar global = require('./_global');\nvar process = global.process;\nvar setTask = global.setImmediate;\nvar clearTask = global.clearImmediate;\nvar MessageChannel = global.MessageChannel;\nvar Dispatch = global.Dispatch;\nvar counter = 0;\nvar queue = {};\nvar ONREADYSTATECHANGE = 'onreadystatechange';\nvar defer, channel, port;\nvar run = function () {\n var id = +this;\n // eslint-disable-next-line no-prototype-builtins\n if (queue.hasOwnProperty(id)) {\n var fn = queue[id];\n delete queue[id];\n fn();\n }\n};\nvar listener = function (event) {\n run.call(event.data);\n};\n// Node.js 0.9+ & IE10+ has setImmediate, otherwise:\nif (!setTask || !clearTask) {\n setTask = function setImmediate(fn) {\n var args = [];\n var i = 1;\n while (arguments.length > i) args.push(arguments[i++]);\n queue[++counter] = function () {\n // eslint-disable-next-line no-new-func\n invoke(typeof fn == 'function' ? fn : Function(fn), args);\n };\n defer(counter);\n return counter;\n };\n clearTask = function clearImmediate(id) {\n delete queue[id];\n };\n // Node.js 0.8-\n if (require('./_cof')(process) == 'process') {\n defer = function (id) {\n process.nextTick(ctx(run, id, 1));\n };\n // Sphere (JS game engine) Dispatch API\n } else if (Dispatch && Dispatch.now) {\n defer = function (id) {\n Dispatch.now(ctx(run, id, 1));\n };\n // Browsers with MessageChannel, includes WebWorkers\n } else if (MessageChannel) {\n channel = new MessageChannel();\n port = channel.port2;\n channel.port1.onmessage = listener;\n defer = ctx(port.postMessage, port, 1);\n // Browsers with postMessage, skip WebWorkers\n // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'\n } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {\n defer = function (id) {\n global.postMessage(id + '', '*');\n };\n global.addEventListener('message', listener, false);\n // IE8-\n } else if (ONREADYSTATECHANGE in cel('script')) {\n defer = function (id) {\n html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {\n html.removeChild(this);\n run.call(id);\n };\n };\n // Rest old browsers\n } else {\n defer = function (id) {\n setTimeout(ctx(run, id, 1), 0);\n };\n }\n}\nmodule.exports = {\n set: setTask,\n clear: clearTask\n};\n","var global = require('./_global');\nvar macrotask = require('./_task').set;\nvar Observer = global.MutationObserver || global.WebKitMutationObserver;\nvar process = global.process;\nvar Promise = global.Promise;\nvar isNode = require('./_cof')(process) == 'process';\n\nmodule.exports = function () {\n var head, last, notify;\n\n var flush = function () {\n var parent, fn;\n if (isNode && (parent = process.domain)) parent.exit();\n while (head) {\n fn = head.fn;\n head = head.next;\n try {\n fn();\n } catch (e) {\n if (head) notify();\n else last = undefined;\n throw e;\n }\n } last = undefined;\n if (parent) parent.enter();\n };\n\n // Node.js\n if (isNode) {\n notify = function () {\n process.nextTick(flush);\n };\n // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339\n } else if (Observer && !(global.navigator && global.navigator.standalone)) {\n var toggle = true;\n var node = document.createTextNode('');\n new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new\n notify = function () {\n node.data = toggle = !toggle;\n };\n // environments with maybe non-completely correct, but existent Promise\n } else if (Promise && Promise.resolve) {\n var promise = Promise.resolve();\n notify = function () {\n promise.then(flush);\n };\n // for other environments - macrotask based on:\n // - setImmediate\n // - MessageChannel\n // - window.postMessag\n // - onreadystatechange\n // - setTimeout\n } else {\n notify = function () {\n // strange IE + webpack dev server bug - use .call(global)\n macrotask.call(global, flush);\n };\n }\n\n return function (fn) {\n var task = { fn: fn, next: undefined };\n if (last) last.next = task;\n if (!head) {\n head = task;\n notify();\n } last = task;\n };\n};\n","'use strict';\n// 25.4.1.5 NewPromiseCapability(C)\nvar aFunction = require('./_a-function');\n\nfunction PromiseCapability(C) {\n var resolve, reject;\n this.promise = new C(function ($$resolve, $$reject) {\n if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');\n resolve = $$resolve;\n reject = $$reject;\n });\n this.resolve = aFunction(resolve);\n this.reject = aFunction(reject);\n}\n\nmodule.exports.f = function (C) {\n return new PromiseCapability(C);\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar global = require('./_global');\nvar ctx = require('./_ctx');\nvar classof = require('./_classof');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar aFunction = require('./_a-function');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar speciesConstructor = require('./_species-constructor');\nvar task = require('./_task').set;\nvar microtask = require('./_microtask')();\nvar newPromiseCapabilityModule = require('./_new-promise-capability');\nvar perform = require('./_perform');\nvar promiseResolve = require('./_promise-resolve');\nvar PROMISE = 'Promise';\nvar TypeError = global.TypeError;\nvar process = global.process;\nvar $Promise = global[PROMISE];\nvar isNode = classof(process) == 'process';\nvar empty = function () { /* empty */ };\nvar Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;\nvar newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;\n\nvar USE_NATIVE = !!function () {\n try {\n // correct subclassing with @@species support\n var promise = $Promise.resolve(1);\n var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) {\n exec(empty, empty);\n };\n // unhandled rejections tracking support, NodeJS Promise without it fails @@species test\n return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;\n } catch (e) { /* empty */ }\n}();\n\n// helpers\nvar isThenable = function (it) {\n var then;\n return isObject(it) && typeof (then = it.then) == 'function' ? then : false;\n};\nvar notify = function (promise, isReject) {\n if (promise._n) return;\n promise._n = true;\n var chain = promise._c;\n microtask(function () {\n var value = promise._v;\n var ok = promise._s == 1;\n var i = 0;\n var run = function (reaction) {\n var handler = ok ? reaction.ok : reaction.fail;\n var resolve = reaction.resolve;\n var reject = reaction.reject;\n var domain = reaction.domain;\n var result, then;\n try {\n if (handler) {\n if (!ok) {\n if (promise._h == 2) onHandleUnhandled(promise);\n promise._h = 1;\n }\n if (handler === true) result = value;\n else {\n if (domain) domain.enter();\n result = handler(value);\n if (domain) domain.exit();\n }\n if (result === reaction.promise) {\n reject(TypeError('Promise-chain cycle'));\n } else if (then = isThenable(result)) {\n then.call(result, resolve, reject);\n } else resolve(result);\n } else reject(value);\n } catch (e) {\n reject(e);\n }\n };\n while (chain.length > i) run(chain[i++]); // variable length - can't use forEach\n promise._c = [];\n promise._n = false;\n if (isReject && !promise._h) onUnhandled(promise);\n });\n};\nvar onUnhandled = function (promise) {\n task.call(global, function () {\n var value = promise._v;\n var unhandled = isUnhandled(promise);\n var result, handler, console;\n if (unhandled) {\n result = perform(function () {\n if (isNode) {\n process.emit('unhandledRejection', value, promise);\n } else if (handler = global.onunhandledrejection) {\n handler({ promise: promise, reason: value });\n } else if ((console = global.console) && console.error) {\n console.error('Unhandled promise rejection', value);\n }\n });\n // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should\n promise._h = isNode || isUnhandled(promise) ? 2 : 1;\n } promise._a = undefined;\n if (unhandled && result.e) throw result.v;\n });\n};\nvar isUnhandled = function (promise) {\n return promise._h !== 1 && (promise._a || promise._c).length === 0;\n};\nvar onHandleUnhandled = function (promise) {\n task.call(global, function () {\n var handler;\n if (isNode) {\n process.emit('rejectionHandled', promise);\n } else if (handler = global.onrejectionhandled) {\n handler({ promise: promise, reason: promise._v });\n }\n });\n};\nvar $reject = function (value) {\n var promise = this;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n promise._v = value;\n promise._s = 2;\n if (!promise._a) promise._a = promise._c.slice();\n notify(promise, true);\n};\nvar $resolve = function (value) {\n var promise = this;\n var then;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n try {\n if (promise === value) throw TypeError(\"Promise can't be resolved itself\");\n if (then = isThenable(value)) {\n microtask(function () {\n var wrapper = { _w: promise, _d: false }; // wrap\n try {\n then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));\n } catch (e) {\n $reject.call(wrapper, e);\n }\n });\n } else {\n promise._v = value;\n promise._s = 1;\n notify(promise, false);\n }\n } catch (e) {\n $reject.call({ _w: promise, _d: false }, e); // wrap\n }\n};\n\n// constructor polyfill\nif (!USE_NATIVE) {\n // 25.4.3.1 Promise(executor)\n $Promise = function Promise(executor) {\n anInstance(this, $Promise, PROMISE, '_h');\n aFunction(executor);\n Internal.call(this);\n try {\n executor(ctx($resolve, this, 1), ctx($reject, this, 1));\n } catch (err) {\n $reject.call(this, err);\n }\n };\n // eslint-disable-next-line no-unused-vars\n Internal = function Promise(executor) {\n this._c = []; // <- awaiting reactions\n this._a = undefined; // <- checked in isUnhandled reactions\n this._s = 0; // <- state\n this._d = false; // <- done\n this._v = undefined; // <- value\n this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled\n this._n = false; // <- notify\n };\n Internal.prototype = require('./_redefine-all')($Promise.prototype, {\n // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)\n then: function then(onFulfilled, onRejected) {\n var reaction = newPromiseCapability(speciesConstructor(this, $Promise));\n reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;\n reaction.fail = typeof onRejected == 'function' && onRejected;\n reaction.domain = isNode ? process.domain : undefined;\n this._c.push(reaction);\n if (this._a) this._a.push(reaction);\n if (this._s) notify(this, false);\n return reaction.promise;\n },\n // 25.4.5.1 Promise.prototype.catch(onRejected)\n 'catch': function (onRejected) {\n return this.then(undefined, onRejected);\n }\n });\n OwnPromiseCapability = function () {\n var promise = new Internal();\n this.promise = promise;\n this.resolve = ctx($resolve, promise, 1);\n this.reject = ctx($reject, promise, 1);\n };\n newPromiseCapabilityModule.f = newPromiseCapability = function (C) {\n return C === $Promise || C === Wrapper\n ? new OwnPromiseCapability(C)\n : newGenericPromiseCapability(C);\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });\nrequire('./_set-to-string-tag')($Promise, PROMISE);\nrequire('./_set-species')(PROMISE);\nWrapper = require('./_core')[PROMISE];\n\n// statics\n$export($export.S + $export.F * !USE_NATIVE, PROMISE, {\n // 25.4.4.5 Promise.reject(r)\n reject: function reject(r) {\n var capability = newPromiseCapability(this);\n var $$reject = capability.reject;\n $$reject(r);\n return capability.promise;\n }\n});\n$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {\n // 25.4.4.6 Promise.resolve(x)\n resolve: function resolve(x) {\n return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);\n }\n});\n$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) {\n $Promise.all(iter)['catch'](empty);\n})), PROMISE, {\n // 25.4.4.1 Promise.all(iterable)\n all: function all(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var resolve = capability.resolve;\n var reject = capability.reject;\n var result = perform(function () {\n var values = [];\n var index = 0;\n var remaining = 1;\n forOf(iterable, false, function (promise) {\n var $index = index++;\n var alreadyCalled = false;\n values.push(undefined);\n remaining++;\n C.resolve(promise).then(function (value) {\n if (alreadyCalled) return;\n alreadyCalled = true;\n values[$index] = value;\n --remaining || resolve(values);\n }, reject);\n });\n --remaining || resolve(values);\n });\n if (result.e) reject(result.v);\n return capability.promise;\n },\n // 25.4.4.4 Promise.race(iterable)\n race: function race(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var reject = capability.reject;\n var result = perform(function () {\n forOf(iterable, false, function (promise) {\n C.resolve(promise).then(capability.resolve, reject);\n });\n });\n if (result.e) reject(result.v);\n return capability.promise;\n }\n});\n","module.exports = function (exec) {\n try {\n return { e: false, v: exec() };\n } catch (e) {\n return { e: true, v: e };\n }\n};\n","var anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar newPromiseCapability = require('./_new-promise-capability');\n\nmodule.exports = function (C, x) {\n anObject(C);\n if (isObject(x) && x.constructor === C) return x;\n var promiseCapability = newPromiseCapability.f(C);\n var resolve = promiseCapability.resolve;\n resolve(x);\n return promiseCapability.promise;\n};\n","exports.f = require('./_wks');\n","var global = require('./_global');\nvar core = require('./_core');\nvar LIBRARY = require('./_library');\nvar wksExt = require('./_wks-ext');\nvar defineProperty = require('./_object-dp').f;\nmodule.exports = function (name) {\n var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});\n if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) });\n};\n","// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window\nvar toIObject = require('./_to-iobject');\nvar gOPN = require('./_object-gopn').f;\nvar toString = {}.toString;\n\nvar windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames\n ? Object.getOwnPropertyNames(window) : [];\n\nvar getWindowNames = function (it) {\n try {\n return gOPN(it);\n } catch (e) {\n return windowNames.slice();\n }\n};\n\nmodule.exports.f = function getOwnPropertyNames(it) {\n return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));\n};\n","'use strict';\n// ECMAScript 6 symbols shim\nvar global = require('./_global');\nvar has = require('./_has');\nvar DESCRIPTORS = require('./_descriptors');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar META = require('./_meta').KEY;\nvar $fails = require('./_fails');\nvar shared = require('./_shared');\nvar setToStringTag = require('./_set-to-string-tag');\nvar uid = require('./_uid');\nvar wks = require('./_wks');\nvar wksExt = require('./_wks-ext');\nvar wksDefine = require('./_wks-define');\nvar enumKeys = require('./_enum-keys');\nvar isArray = require('./_is-array');\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar createDesc = require('./_property-desc');\nvar _create = require('./_object-create');\nvar gOPNExt = require('./_object-gopn-ext');\nvar $GOPD = require('./_object-gopd');\nvar $DP = require('./_object-dp');\nvar $keys = require('./_object-keys');\nvar gOPD = $GOPD.f;\nvar dP = $DP.f;\nvar gOPN = gOPNExt.f;\nvar $Symbol = global.Symbol;\nvar $JSON = global.JSON;\nvar _stringify = $JSON && $JSON.stringify;\nvar PROTOTYPE = 'prototype';\nvar HIDDEN = wks('_hidden');\nvar TO_PRIMITIVE = wks('toPrimitive');\nvar isEnum = {}.propertyIsEnumerable;\nvar SymbolRegistry = shared('symbol-registry');\nvar AllSymbols = shared('symbols');\nvar OPSymbols = shared('op-symbols');\nvar ObjectProto = Object[PROTOTYPE];\nvar USE_NATIVE = typeof $Symbol == 'function';\nvar QObject = global.QObject;\n// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173\nvar setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;\n\n// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687\nvar setSymbolDesc = DESCRIPTORS && $fails(function () {\n return _create(dP({}, 'a', {\n get: function () { return dP(this, 'a', { value: 7 }).a; }\n })).a != 7;\n}) ? function (it, key, D) {\n var protoDesc = gOPD(ObjectProto, key);\n if (protoDesc) delete ObjectProto[key];\n dP(it, key, D);\n if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);\n} : dP;\n\nvar wrap = function (tag) {\n var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);\n sym._k = tag;\n return sym;\n};\n\nvar isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) {\n return typeof it == 'symbol';\n} : function (it) {\n return it instanceof $Symbol;\n};\n\nvar $defineProperty = function defineProperty(it, key, D) {\n if (it === ObjectProto) $defineProperty(OPSymbols, key, D);\n anObject(it);\n key = toPrimitive(key, true);\n anObject(D);\n if (has(AllSymbols, key)) {\n if (!D.enumerable) {\n if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));\n it[HIDDEN][key] = true;\n } else {\n if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;\n D = _create(D, { enumerable: createDesc(0, false) });\n } return setSymbolDesc(it, key, D);\n } return dP(it, key, D);\n};\nvar $defineProperties = function defineProperties(it, P) {\n anObject(it);\n var keys = enumKeys(P = toIObject(P));\n var i = 0;\n var l = keys.length;\n var key;\n while (l > i) $defineProperty(it, key = keys[i++], P[key]);\n return it;\n};\nvar $create = function create(it, P) {\n return P === undefined ? _create(it) : $defineProperties(_create(it), P);\n};\nvar $propertyIsEnumerable = function propertyIsEnumerable(key) {\n var E = isEnum.call(this, key = toPrimitive(key, true));\n if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;\n return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;\n};\nvar $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {\n it = toIObject(it);\n key = toPrimitive(key, true);\n if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;\n var D = gOPD(it, key);\n if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;\n return D;\n};\nvar $getOwnPropertyNames = function getOwnPropertyNames(it) {\n var names = gOPN(toIObject(it));\n var result = [];\n var i = 0;\n var key;\n while (names.length > i) {\n if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);\n } return result;\n};\nvar $getOwnPropertySymbols = function getOwnPropertySymbols(it) {\n var IS_OP = it === ObjectProto;\n var names = gOPN(IS_OP ? OPSymbols : toIObject(it));\n var result = [];\n var i = 0;\n var key;\n while (names.length > i) {\n if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);\n } return result;\n};\n\n// 19.4.1.1 Symbol([description])\nif (!USE_NATIVE) {\n $Symbol = function Symbol() {\n if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');\n var tag = uid(arguments.length > 0 ? arguments[0] : undefined);\n var $set = function (value) {\n if (this === ObjectProto) $set.call(OPSymbols, value);\n if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;\n setSymbolDesc(this, tag, createDesc(1, value));\n };\n if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, { configurable: true, set: $set });\n return wrap(tag);\n };\n redefine($Symbol[PROTOTYPE], 'toString', function toString() {\n return this._k;\n });\n\n $GOPD.f = $getOwnPropertyDescriptor;\n $DP.f = $defineProperty;\n require('./_object-gopn').f = gOPNExt.f = $getOwnPropertyNames;\n require('./_object-pie').f = $propertyIsEnumerable;\n require('./_object-gops').f = $getOwnPropertySymbols;\n\n if (DESCRIPTORS && !require('./_library')) {\n redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);\n }\n\n wksExt.f = function (name) {\n return wrap(wks(name));\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol });\n\nfor (var es6Symbols = (\n // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14\n 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'\n).split(','), j = 0; es6Symbols.length > j;)wks(es6Symbols[j++]);\n\nfor (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) wksDefine(wellKnownSymbols[k++]);\n\n$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {\n // 19.4.2.1 Symbol.for(key)\n 'for': function (key) {\n return has(SymbolRegistry, key += '')\n ? SymbolRegistry[key]\n : SymbolRegistry[key] = $Symbol(key);\n },\n // 19.4.2.5 Symbol.keyFor(sym)\n keyFor: function keyFor(sym) {\n if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');\n for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key;\n },\n useSetter: function () { setter = true; },\n useSimple: function () { setter = false; }\n});\n\n$export($export.S + $export.F * !USE_NATIVE, 'Object', {\n // 19.1.2.2 Object.create(O [, Properties])\n create: $create,\n // 19.1.2.4 Object.defineProperty(O, P, Attributes)\n defineProperty: $defineProperty,\n // 19.1.2.3 Object.defineProperties(O, Properties)\n defineProperties: $defineProperties,\n // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)\n getOwnPropertyDescriptor: $getOwnPropertyDescriptor,\n // 19.1.2.7 Object.getOwnPropertyNames(O)\n getOwnPropertyNames: $getOwnPropertyNames,\n // 19.1.2.8 Object.getOwnPropertySymbols(O)\n getOwnPropertySymbols: $getOwnPropertySymbols\n});\n\n// 24.3.2 JSON.stringify(value [, replacer [, space]])\n$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {\n var S = $Symbol();\n // MS Edge converts symbol values to JSON as {}\n // WebKit converts symbol values to JSON as null\n // V8 throws on boxed symbols\n return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';\n})), 'JSON', {\n stringify: function stringify(it) {\n var args = [it];\n var i = 1;\n var replacer, $replacer;\n while (arguments.length > i) args.push(arguments[i++]);\n $replacer = replacer = args[1];\n if (!isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined\n if (!isArray(replacer)) replacer = function (key, value) {\n if (typeof $replacer == 'function') value = $replacer.call(this, key, value);\n if (!isSymbol(value)) return value;\n };\n args[1] = replacer;\n return _stringify.apply($JSON, args);\n }\n});\n\n// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)\n$Symbol[PROTOTYPE][TO_PRIMITIVE] || require('./_hide')($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);\n// 19.4.3.5 Symbol.prototype[@@toStringTag]\nsetToStringTag($Symbol, 'Symbol');\n// 20.2.1.9 Math[@@toStringTag]\nsetToStringTag(Math, 'Math', true);\n// 24.3.3 JSON[@@toStringTag]\nsetToStringTag(global.JSON, 'JSON', true);\n","// all enumerable object keys, includes symbols\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nmodule.exports = function (it) {\n var result = getKeys(it);\n var getSymbols = gOPS.f;\n if (getSymbols) {\n var symbols = getSymbols(it);\n var isEnum = pIE.f;\n var i = 0;\n var key;\n while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key);\n } return result;\n};\n","// most Object methods by ES6 should accept primitives\nvar $export = require('./_export');\nvar core = require('./_core');\nvar fails = require('./_fails');\nmodule.exports = function (KEY, exec) {\n var fn = (core.Object || {})[KEY] || Object[KEY];\n var exp = {};\n exp[KEY] = exec(fn);\n $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp);\n};\n","// 19.1.2.5 Object.freeze(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('freeze', function ($freeze) {\n return function freeze(it) {\n return $freeze && isObject(it) ? $freeze(meta(it)) : it;\n };\n});\n","// 19.1.2.17 Object.seal(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('seal', function ($seal) {\n return function seal(it) {\n return $seal && isObject(it) ? $seal(meta(it)) : it;\n };\n});\n","// 19.1.2.15 Object.preventExtensions(O)\nvar isObject = require('./_is-object');\nvar meta = require('./_meta').onFreeze;\n\nrequire('./_object-sap')('preventExtensions', function ($preventExtensions) {\n return function preventExtensions(it) {\n return $preventExtensions && isObject(it) ? $preventExtensions(meta(it)) : it;\n };\n});\n","// 19.1.2.12 Object.isFrozen(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isFrozen', function ($isFrozen) {\n return function isFrozen(it) {\n return isObject(it) ? $isFrozen ? $isFrozen(it) : false : true;\n };\n});\n","// 19.1.2.13 Object.isSealed(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isSealed', function ($isSealed) {\n return function isSealed(it) {\n return isObject(it) ? $isSealed ? $isSealed(it) : false : true;\n };\n});\n","// 19.1.2.11 Object.isExtensible(O)\nvar isObject = require('./_is-object');\n\nrequire('./_object-sap')('isExtensible', function ($isExtensible) {\n return function isExtensible(it) {\n return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false;\n };\n});\n","// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)\nvar toIObject = require('./_to-iobject');\nvar $getOwnPropertyDescriptor = require('./_object-gopd').f;\n\nrequire('./_object-sap')('getOwnPropertyDescriptor', function () {\n return function getOwnPropertyDescriptor(it, key) {\n return $getOwnPropertyDescriptor(toIObject(it), key);\n };\n});\n","// 19.1.2.9 Object.getPrototypeOf(O)\nvar toObject = require('./_to-object');\nvar $getPrototypeOf = require('./_object-gpo');\n\nrequire('./_object-sap')('getPrototypeOf', function () {\n return function getPrototypeOf(it) {\n return $getPrototypeOf(toObject(it));\n };\n});\n","// 19.1.2.14 Object.keys(O)\nvar toObject = require('./_to-object');\nvar $keys = require('./_object-keys');\n\nrequire('./_object-sap')('keys', function () {\n return function keys(it) {\n return $keys(toObject(it));\n };\n});\n","// 19.1.2.7 Object.getOwnPropertyNames(O)\nrequire('./_object-sap')('getOwnPropertyNames', function () {\n return require('./_object-gopn-ext').f;\n});\n","// 19.1.3.1 Object.assign(target, source)\nvar $export = require('./_export');\n\n$export($export.S + $export.F, 'Object', { assign: require('./_object-assign') });\n","// 7.2.9 SameValue(x, y)\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare\n return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;\n};\n","// 19.1.3.10 Object.is(value1, value2)\nvar $export = require('./_export');\n$export($export.S, 'Object', { is: require('./_same-value') });\n","var dP = require('./_object-dp').f;\nvar FProto = Function.prototype;\nvar nameRE = /^\\s*function ([^ (]*)/;\nvar NAME = 'name';\n\n// 19.2.4.2 name\nNAME in FProto || require('./_descriptors') && dP(FProto, NAME, {\n configurable: true,\n get: function () {\n try {\n return ('' + this).match(nameRE)[1];\n } catch (e) {\n return '';\n }\n }\n});\n","var $export = require('./_export');\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\n\n$export($export.S, 'String', {\n // 21.1.2.4 String.raw(callSite, ...substitutions)\n raw: function raw(callSite) {\n var tpl = toIObject(callSite.raw);\n var len = toLength(tpl.length);\n var aLen = arguments.length;\n var res = [];\n var i = 0;\n while (len > i) {\n res.push(String(tpl[i++]));\n if (i < aLen) res.push(String(arguments[i]));\n } return res.join('');\n }\n});\n","var $export = require('./_export');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nvar fromCharCode = String.fromCharCode;\nvar $fromCodePoint = String.fromCodePoint;\n\n// length should be 1, old FF problem\n$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {\n // 21.1.2.2 String.fromCodePoint(...codePoints)\n fromCodePoint: function fromCodePoint(x) { // eslint-disable-line no-unused-vars\n var res = [];\n var aLen = arguments.length;\n var i = 0;\n var code;\n while (aLen > i) {\n code = +arguments[i++];\n if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');\n res.push(code < 0x10000\n ? fromCharCode(code)\n : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00)\n );\n } return res.join('');\n }\n});\n","var toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n// true -> String#at\n// false -> String#codePointAt\nmodule.exports = function (TO_STRING) {\n return function (that, pos) {\n var s = String(defined(that));\n var i = toInteger(pos);\n var l = s.length;\n var a, b;\n if (i < 0 || i >= l) return TO_STRING ? '' : undefined;\n a = s.charCodeAt(i);\n return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff\n ? TO_STRING ? s.charAt(i) : a\n : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;\n };\n};\n","'use strict';\nvar $export = require('./_export');\nvar $at = require('./_string-at')(false);\n$export($export.P, 'String', {\n // 21.1.3.3 String.prototype.codePointAt(pos)\n codePointAt: function codePointAt(pos) {\n return $at(this, pos);\n }\n});\n","'use strict';\nvar toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n\nmodule.exports = function repeat(count) {\n var str = String(defined(this));\n var res = '';\n var n = toInteger(count);\n if (n < 0 || n == Infinity) throw RangeError(\"Count can't be negative\");\n for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) res += str;\n return res;\n};\n","var $export = require('./_export');\n\n$export($export.P, 'String', {\n // 21.1.3.13 String.prototype.repeat(count)\n repeat: require('./_string-repeat')\n});\n","// 7.2.8 IsRegExp(argument)\nvar isObject = require('./_is-object');\nvar cof = require('./_cof');\nvar MATCH = require('./_wks')('match');\nmodule.exports = function (it) {\n var isRegExp;\n return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');\n};\n","// helper for String#{startsWith, endsWith, includes}\nvar isRegExp = require('./_is-regexp');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, searchString, NAME) {\n if (isRegExp(searchString)) throw TypeError('String#' + NAME + \" doesn't accept regex!\");\n return String(defined(that));\n};\n","var MATCH = require('./_wks')('match');\nmodule.exports = function (KEY) {\n var re = /./;\n try {\n '/./'[KEY](re);\n } catch (e) {\n try {\n re[MATCH] = false;\n return !'/./'[KEY](re);\n } catch (f) { /* empty */ }\n } return true;\n};\n","// 21.1.3.18 String.prototype.startsWith(searchString [, position ])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar STARTS_WITH = 'startsWith';\nvar $startsWith = ''[STARTS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(STARTS_WITH), 'String', {\n startsWith: function startsWith(searchString /* , position = 0 */) {\n var that = context(this, searchString, STARTS_WITH);\n var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));\n var search = String(searchString);\n return $startsWith\n ? $startsWith.call(that, search, index)\n : that.slice(index, index + search.length) === search;\n }\n});\n","// 21.1.3.6 String.prototype.endsWith(searchString [, endPosition])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar ENDS_WITH = 'endsWith';\nvar $endsWith = ''[ENDS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(ENDS_WITH), 'String', {\n endsWith: function endsWith(searchString /* , endPosition = @length */) {\n var that = context(this, searchString, ENDS_WITH);\n var endPosition = arguments.length > 1 ? arguments[1] : undefined;\n var len = toLength(that.length);\n var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len);\n var search = String(searchString);\n return $endsWith\n ? $endsWith.call(that, search, end)\n : that.slice(end - search.length, end) === search;\n }\n});\n","// 21.1.3.7 String.prototype.includes(searchString, position = 0)\n'use strict';\nvar $export = require('./_export');\nvar context = require('./_string-context');\nvar INCLUDES = 'includes';\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(INCLUDES), 'String', {\n includes: function includes(searchString /* , position = 0 */) {\n return !!~context(this, searchString, INCLUDES)\n .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","// 21.2.5.3 get RegExp.prototype.flags()\nif (require('./_descriptors') && /./g.flags != 'g') require('./_object-dp').f(RegExp.prototype, 'flags', {\n configurable: true,\n get: require('./_flags')\n});\n","'use strict';\n// 21.2.5.3 get RegExp.prototype.flags\nvar anObject = require('./_an-object');\nmodule.exports = function () {\n var that = anObject(this);\n var result = '';\n if (that.global) result += 'g';\n if (that.ignoreCase) result += 'i';\n if (that.multiline) result += 'm';\n if (that.unicode) result += 'u';\n if (that.sticky) result += 'y';\n return result;\n};\n","'use strict';\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar fails = require('./_fails');\nvar defined = require('./_defined');\nvar wks = require('./_wks');\n\nmodule.exports = function (KEY, length, exec) {\n var SYMBOL = wks(KEY);\n var fns = exec(defined, SYMBOL, ''[KEY]);\n var strfn = fns[0];\n var rxfn = fns[1];\n if (fails(function () {\n var O = {};\n O[SYMBOL] = function () { return 7; };\n return ''[KEY](O) != 7;\n })) {\n redefine(String.prototype, KEY, strfn);\n hide(RegExp.prototype, SYMBOL, length == 2\n // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)\n // 21.2.5.11 RegExp.prototype[@@split](string, limit)\n ? function (string, arg) { return rxfn.call(string, this, arg); }\n // 21.2.5.6 RegExp.prototype[@@match](string)\n // 21.2.5.9 RegExp.prototype[@@search](string)\n : function (string) { return rxfn.call(string, this); }\n );\n }\n};\n","// @@match logic\nrequire('./_fix-re-wks')('match', 1, function (defined, MATCH, $match) {\n // 21.1.3.11 String.prototype.match(regexp)\n return [function match(regexp) {\n 'use strict';\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[MATCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));\n }, $match];\n});\n","// @@replace logic\nrequire('./_fix-re-wks')('replace', 2, function (defined, REPLACE, $replace) {\n // 21.1.3.14 String.prototype.replace(searchValue, replaceValue)\n return [function replace(searchValue, replaceValue) {\n 'use strict';\n var O = defined(this);\n var fn = searchValue == undefined ? undefined : searchValue[REPLACE];\n return fn !== undefined\n ? fn.call(searchValue, O, replaceValue)\n : $replace.call(String(O), searchValue, replaceValue);\n }, $replace];\n});\n","// @@split logic\nrequire('./_fix-re-wks')('split', 2, function (defined, SPLIT, $split) {\n 'use strict';\n var isRegExp = require('./_is-regexp');\n var _split = $split;\n var $push = [].push;\n var $SPLIT = 'split';\n var LENGTH = 'length';\n var LAST_INDEX = 'lastIndex';\n if (\n 'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||\n 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||\n 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||\n '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||\n '.'[$SPLIT](/()()/)[LENGTH] > 1 ||\n ''[$SPLIT](/.?/)[LENGTH]\n ) {\n var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group\n // based on es5-shim implementation, need to rework it\n $split = function (separator, limit) {\n var string = String(this);\n if (separator === undefined && limit === 0) return [];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) return _split.call(string, separator, limit);\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n var splitLimit = limit === undefined ? 4294967295 : limit >>> 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var separator2, match, lastIndex, lastLength, i;\n // Doesn't need flags gy, but they don't hurt\n if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\\\s)', flags);\n while (match = separatorCopy.exec(string)) {\n // `separatorCopy.lastIndex` is not reliable cross-browser\n lastIndex = match.index + match[0][LENGTH];\n if (lastIndex > lastLastIndex) {\n output.push(string.slice(lastLastIndex, match.index));\n // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG\n // eslint-disable-next-line no-loop-func\n if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () {\n for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined;\n });\n if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));\n lastLength = match[0][LENGTH];\n lastLastIndex = lastIndex;\n if (output[LENGTH] >= splitLimit) break;\n }\n if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop\n }\n if (lastLastIndex === string[LENGTH]) {\n if (lastLength || !separatorCopy.test('')) output.push('');\n } else output.push(string.slice(lastLastIndex));\n return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;\n };\n // Chakra, V8\n } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {\n $split = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit);\n };\n }\n // 21.1.3.17 String.prototype.split(separator, limit)\n return [function split(separator, limit) {\n var O = defined(this);\n var fn = separator == undefined ? undefined : separator[SPLIT];\n return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit);\n }, $split];\n});\n","// @@search logic\nrequire('./_fix-re-wks')('search', 1, function (defined, SEARCH, $search) {\n // 21.1.3.15 String.prototype.search(regexp)\n return [function search(regexp) {\n 'use strict';\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[SEARCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));\n }, $search];\n});\n","'use strict';\nvar $defineProperty = require('./_object-dp');\nvar createDesc = require('./_property-desc');\n\nmodule.exports = function (object, index, value) {\n if (index in object) $defineProperty.f(object, index, createDesc(0, value));\n else object[index] = value;\n};\n","'use strict';\nvar ctx = require('./_ctx');\nvar $export = require('./_export');\nvar toObject = require('./_to-object');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar toLength = require('./_to-length');\nvar createProperty = require('./_create-property');\nvar getIterFn = require('./core.get-iterator-method');\n\n$export($export.S + $export.F * !require('./_iter-detect')(function (iter) { Array.from(iter); }), 'Array', {\n // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)\n from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {\n var O = toObject(arrayLike);\n var C = typeof this == 'function' ? this : Array;\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var index = 0;\n var iterFn = getIterFn(O);\n var length, result, step, iterator;\n if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);\n // if object isn't iterable or it's array with default iterator - use simple case\n if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {\n for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {\n createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);\n }\n } else {\n length = toLength(O.length);\n for (result = new C(length); length > index; index++) {\n createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);\n }\n }\n result.length = index;\n return result;\n }\n});\n","'use strict';\nvar $export = require('./_export');\nvar createProperty = require('./_create-property');\n\n// WebKit Array.of isn't generic\n$export($export.S + $export.F * require('./_fails')(function () {\n function F() { /* empty */ }\n return !(Array.of.call(F) instanceof F);\n}), 'Array', {\n // 22.1.2.3 Array.of( ...items)\n of: function of(/* ...args */) {\n var index = 0;\n var aLen = arguments.length;\n var result = new (typeof this == 'function' ? this : Array)(aLen);\n while (aLen > index) createProperty(result, index, arguments[index++]);\n result.length = aLen;\n return result;\n }\n});\n","// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)\nvar $export = require('./_export');\n\n$export($export.P, 'Array', { copyWithin: require('./_array-copy-within') });\n\nrequire('./_add-to-unscopables')('copyWithin');\n","'use strict';\n// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(5);\nvar KEY = 'find';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n find: function find(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","'use strict';\n// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(6);\nvar KEY = 'findIndex';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n findIndex: function findIndex(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)\nvar $export = require('./_export');\n\n$export($export.P, 'Array', { fill: require('./_array-fill') });\n\nrequire('./_add-to-unscopables')('fill');\n","// 20.1.2.2 Number.isFinite(number)\nvar $export = require('./_export');\nvar _isFinite = require('./_global').isFinite;\n\n$export($export.S, 'Number', {\n isFinite: function isFinite(it) {\n return typeof it == 'number' && _isFinite(it);\n }\n});\n","// 20.1.2.3 Number.isInteger(number)\nvar isObject = require('./_is-object');\nvar floor = Math.floor;\nmodule.exports = function isInteger(it) {\n return !isObject(it) && isFinite(it) && floor(it) === it;\n};\n","// 20.1.2.3 Number.isInteger(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { isInteger: require('./_is-integer') });\n","// 20.1.2.5 Number.isSafeInteger(number)\nvar $export = require('./_export');\nvar isInteger = require('./_is-integer');\nvar abs = Math.abs;\n\n$export($export.S, 'Number', {\n isSafeInteger: function isSafeInteger(number) {\n return isInteger(number) && abs(number) <= 0x1fffffffffffff;\n }\n});\n","// 20.1.2.4 Number.isNaN(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', {\n isNaN: function isNaN(number) {\n // eslint-disable-next-line no-self-compare\n return number != number;\n }\n});\n","// 20.1.2.1 Number.EPSILON\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { EPSILON: Math.pow(2, -52) });\n","// 20.1.2.10 Number.MIN_SAFE_INTEGER\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff });\n","// 20.1.2.6 Number.MAX_SAFE_INTEGER\nvar $export = require('./_export');\n\n$export($export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff });\n","// 20.2.2.20 Math.log1p(x)\nmodule.exports = Math.log1p || function log1p(x) {\n return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x);\n};\n","// 20.2.2.3 Math.acosh(x)\nvar $export = require('./_export');\nvar log1p = require('./_math-log1p');\nvar sqrt = Math.sqrt;\nvar $acosh = Math.acosh;\n\n$export($export.S + $export.F * !($acosh\n // V8 bug: https://code.google.com/p/v8/issues/detail?id=3509\n && Math.floor($acosh(Number.MAX_VALUE)) == 710\n // Tor Browser bug: Math.acosh(Infinity) -> NaN\n && $acosh(Infinity) == Infinity\n), 'Math', {\n acosh: function acosh(x) {\n return (x = +x) < 1 ? NaN : x > 94906265.62425156\n ? Math.log(x) + Math.LN2\n : log1p(x - 1 + sqrt(x - 1) * sqrt(x + 1));\n }\n});\n","// 20.2.2.5 Math.asinh(x)\nvar $export = require('./_export');\nvar $asinh = Math.asinh;\n\nfunction asinh(x) {\n return !isFinite(x = +x) || x == 0 ? x : x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1));\n}\n\n// Tor Browser bug: Math.asinh(0) -> -0\n$export($export.S + $export.F * !($asinh && 1 / $asinh(0) > 0), 'Math', { asinh: asinh });\n","// 20.2.2.7 Math.atanh(x)\nvar $export = require('./_export');\nvar $atanh = Math.atanh;\n\n// Tor Browser bug: Math.atanh(-0) -> 0\n$export($export.S + $export.F * !($atanh && 1 / $atanh(-0) < 0), 'Math', {\n atanh: function atanh(x) {\n return (x = +x) == 0 ? x : Math.log((1 + x) / (1 - x)) / 2;\n }\n});\n","// 20.2.2.28 Math.sign(x)\nmodule.exports = Math.sign || function sign(x) {\n // eslint-disable-next-line no-self-compare\n return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;\n};\n","// 20.2.2.9 Math.cbrt(x)\nvar $export = require('./_export');\nvar sign = require('./_math-sign');\n\n$export($export.S, 'Math', {\n cbrt: function cbrt(x) {\n return sign(x = +x) * Math.pow(Math.abs(x), 1 / 3);\n }\n});\n","// 20.2.2.11 Math.clz32(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n clz32: function clz32(x) {\n return (x >>>= 0) ? 31 - Math.floor(Math.log(x + 0.5) * Math.LOG2E) : 32;\n }\n});\n","// 20.2.2.12 Math.cosh(x)\nvar $export = require('./_export');\nvar exp = Math.exp;\n\n$export($export.S, 'Math', {\n cosh: function cosh(x) {\n return (exp(x = +x) + exp(-x)) / 2;\n }\n});\n","// 20.2.2.14 Math.expm1(x)\nvar $expm1 = Math.expm1;\nmodule.exports = (!$expm1\n // Old FF bug\n || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168\n // Tor Browser bug\n || $expm1(-2e-17) != -2e-17\n) ? function expm1(x) {\n return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1;\n} : $expm1;\n","// 20.2.2.14 Math.expm1(x)\nvar $export = require('./_export');\nvar $expm1 = require('./_math-expm1');\n\n$export($export.S + $export.F * ($expm1 != Math.expm1), 'Math', { expm1: $expm1 });\n","// 20.2.2.16 Math.fround(x)\nvar sign = require('./_math-sign');\nvar pow = Math.pow;\nvar EPSILON = pow(2, -52);\nvar EPSILON32 = pow(2, -23);\nvar MAX32 = pow(2, 127) * (2 - EPSILON32);\nvar MIN32 = pow(2, -126);\n\nvar roundTiesToEven = function (n) {\n return n + 1 / EPSILON - 1 / EPSILON;\n};\n\nmodule.exports = Math.fround || function fround(x) {\n var $abs = Math.abs(x);\n var $sign = sign(x);\n var a, result;\n if ($abs < MIN32) return $sign * roundTiesToEven($abs / MIN32 / EPSILON32) * MIN32 * EPSILON32;\n a = (1 + EPSILON32 / EPSILON) * $abs;\n result = a - (a - $abs);\n // eslint-disable-next-line no-self-compare\n if (result > MAX32 || result != result) return $sign * Infinity;\n return $sign * result;\n};\n","// 20.2.2.16 Math.fround(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { fround: require('./_math-fround') });\n","// 20.2.2.17 Math.hypot([value1[, value2[, … ]]])\nvar $export = require('./_export');\nvar abs = Math.abs;\n\n$export($export.S, 'Math', {\n hypot: function hypot(value1, value2) { // eslint-disable-line no-unused-vars\n var sum = 0;\n var i = 0;\n var aLen = arguments.length;\n var larg = 0;\n var arg, div;\n while (i < aLen) {\n arg = abs(arguments[i++]);\n if (larg < arg) {\n div = larg / arg;\n sum = sum * div * div + 1;\n larg = arg;\n } else if (arg > 0) {\n div = arg / larg;\n sum += div * div;\n } else sum += arg;\n }\n return larg === Infinity ? Infinity : larg * Math.sqrt(sum);\n }\n});\n","// 20.2.2.18 Math.imul(x, y)\nvar $export = require('./_export');\nvar $imul = Math.imul;\n\n// some WebKit versions fails with big numbers, some has wrong arity\n$export($export.S + $export.F * require('./_fails')(function () {\n return $imul(0xffffffff, 5) != -5 || $imul.length != 2;\n}), 'Math', {\n imul: function imul(x, y) {\n var UINT16 = 0xffff;\n var xn = +x;\n var yn = +y;\n var xl = UINT16 & xn;\n var yl = UINT16 & yn;\n return 0 | xl * yl + ((UINT16 & xn >>> 16) * yl + xl * (UINT16 & yn >>> 16) << 16 >>> 0);\n }\n});\n","// 20.2.2.20 Math.log1p(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { log1p: require('./_math-log1p') });\n","// 20.2.2.21 Math.log10(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n log10: function log10(x) {\n return Math.log(x) * Math.LOG10E;\n }\n});\n","// 20.2.2.22 Math.log2(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n log2: function log2(x) {\n return Math.log(x) / Math.LN2;\n }\n});\n","// 20.2.2.28 Math.sign(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { sign: require('./_math-sign') });\n","// 20.2.2.30 Math.sinh(x)\nvar $export = require('./_export');\nvar expm1 = require('./_math-expm1');\nvar exp = Math.exp;\n\n// V8 near Chromium 38 has a problem with very small numbers\n$export($export.S + $export.F * require('./_fails')(function () {\n return !Math.sinh(-2e-17) != -2e-17;\n}), 'Math', {\n sinh: function sinh(x) {\n return Math.abs(x = +x) < 1\n ? (expm1(x) - expm1(-x)) / 2\n : (exp(x - 1) - exp(-x - 1)) * (Math.E / 2);\n }\n});\n","// 20.2.2.33 Math.tanh(x)\nvar $export = require('./_export');\nvar expm1 = require('./_math-expm1');\nvar exp = Math.exp;\n\n$export($export.S, 'Math', {\n tanh: function tanh(x) {\n var a = expm1(x = +x);\n var b = expm1(-x);\n return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (exp(x) + exp(-x));\n }\n});\n","// 20.2.2.34 Math.trunc(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n trunc: function trunc(it) {\n return (it > 0 ? Math.floor : Math.ceil)(it);\n }\n});\n","'use strict';\n// https://github.com/tc39/Array.prototype.includes\nvar $export = require('./_export');\nvar $includes = require('./_array-includes')(true);\n\n$export($export.P, 'Array', {\n includes: function includes(el /* , fromIndex = 0 */) {\n return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n\nrequire('./_add-to-unscopables')('includes');\n","var getKeys = require('./_object-keys');\nvar toIObject = require('./_to-iobject');\nvar isEnum = require('./_object-pie').f;\nmodule.exports = function (isEntries) {\n return function (it) {\n var O = toIObject(it);\n var keys = getKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) if (isEnum.call(O, key = keys[i++])) {\n result.push(isEntries ? [key, O[key]] : O[key]);\n } return result;\n };\n};\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $values = require('./_object-to-array')(false);\n\n$export($export.S, 'Object', {\n values: function values(it) {\n return $values(it);\n }\n});\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $entries = require('./_object-to-array')(true);\n\n$export($export.S, 'Object', {\n entries: function entries(it) {\n return $entries(it);\n }\n});\n","// https://github.com/tc39/proposal-object-getownpropertydescriptors\nvar $export = require('./_export');\nvar ownKeys = require('./_own-keys');\nvar toIObject = require('./_to-iobject');\nvar gOPD = require('./_object-gopd');\nvar createProperty = require('./_create-property');\n\n$export($export.S, 'Object', {\n getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {\n var O = toIObject(object);\n var getDesc = gOPD.f;\n var keys = ownKeys(O);\n var result = {};\n var i = 0;\n var key, desc;\n while (keys.length > i) {\n desc = getDesc(O, key = keys[i++]);\n if (desc !== undefined) createProperty(result, key, desc);\n }\n return result;\n }\n});\n","// https://github.com/tc39/proposal-string-pad-start-end\nvar toLength = require('./_to-length');\nvar repeat = require('./_string-repeat');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, maxLength, fillString, left) {\n var S = String(defined(that));\n var stringLength = S.length;\n var fillStr = fillString === undefined ? ' ' : String(fillString);\n var intMaxLength = toLength(maxLength);\n if (intMaxLength <= stringLength || fillStr == '') return S;\n var fillLen = intMaxLength - stringLength;\n var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));\n if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);\n return left ? stringFiller + S : S + stringFiller;\n};\n","var global = require('./_global');\nvar navigator = global.navigator;\n\nmodule.exports = navigator && navigator.userAgent || '';\n","'use strict';\n// https://github.com/tc39/proposal-string-pad-start-end\nvar $export = require('./_export');\nvar $pad = require('./_string-pad');\nvar userAgent = require('./_user-agent');\n\n// https://github.com/zloirock/core-js/issues/280\n$export($export.P + $export.F * /Version\\/10\\.\\d+(\\.\\d+)? Safari\\//.test(userAgent), 'String', {\n padStart: function padStart(maxLength /* , fillString = ' ' */) {\n return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true);\n }\n});\n","'use strict';\n// https://github.com/tc39/proposal-string-pad-start-end\nvar $export = require('./_export');\nvar $pad = require('./_string-pad');\nvar userAgent = require('./_user-agent');\n\n// https://github.com/zloirock/core-js/issues/280\n$export($export.P + $export.F * /Version\\/10\\.\\d+(\\.\\d+)? Safari\\//.test(userAgent), 'String', {\n padEnd: function padEnd(maxLength /* , fillString = ' ' */) {\n return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false);\n }\n});\n","// ie9- setTimeout & setInterval additional parameters fix\nvar global = require('./_global');\nvar $export = require('./_export');\nvar userAgent = require('./_user-agent');\nvar slice = [].slice;\nvar MSIE = /MSIE .\\./.test(userAgent); // <- dirty ie9- check\nvar wrap = function (set) {\n return function (fn, time /* , ...args */) {\n var boundArgs = arguments.length > 2;\n var args = boundArgs ? slice.call(arguments, 2) : false;\n return set(boundArgs ? function () {\n // eslint-disable-next-line no-new-func\n (typeof fn == 'function' ? fn : Function(fn)).apply(this, args);\n } : fn, time);\n };\n};\n$export($export.G + $export.B + $export.F * MSIE, {\n setTimeout: wrap(global.setTimeout),\n setInterval: wrap(global.setInterval)\n});\n","var $export = require('./_export');\nvar $task = require('./_task');\n$export($export.G + $export.B, {\n setImmediate: $task.set,\n clearImmediate: $task.clear\n});\n","var $iterators = require('./es6.array.iterator');\nvar getKeys = require('./_object-keys');\nvar redefine = require('./_redefine');\nvar global = require('./_global');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar wks = require('./_wks');\nvar ITERATOR = wks('iterator');\nvar TO_STRING_TAG = wks('toStringTag');\nvar ArrayValues = Iterators.Array;\n\nvar DOMIterables = {\n CSSRuleList: true, // TODO: Not spec compliant, should be false.\n CSSStyleDeclaration: false,\n CSSValueList: false,\n ClientRectList: false,\n DOMRectList: false,\n DOMStringList: false,\n DOMTokenList: true,\n DataTransferItemList: false,\n FileList: false,\n HTMLAllCollection: false,\n HTMLCollection: false,\n HTMLFormElement: false,\n HTMLSelectElement: false,\n MediaList: true, // TODO: Not spec compliant, should be false.\n MimeTypeArray: false,\n NamedNodeMap: false,\n NodeList: true,\n PaintRequestList: false,\n Plugin: false,\n PluginArray: false,\n SVGLengthList: false,\n SVGNumberList: false,\n SVGPathSegList: false,\n SVGPointList: false,\n SVGStringList: false,\n SVGTransformList: false,\n SourceBufferList: false,\n StyleSheetList: true, // TODO: Not spec compliant, should be false.\n TextTrackCueList: false,\n TextTrackList: false,\n TouchList: false\n};\n\nfor (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {\n var NAME = collections[i];\n var explicit = DOMIterables[NAME];\n var Collection = global[NAME];\n var proto = Collection && Collection.prototype;\n var key;\n if (proto) {\n if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);\n if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);\n Iterators[NAME] = ArrayValues;\n if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true);\n }\n}\n","/**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * https://raw.github.com/facebook/regenerator/master/LICENSE file. An\n * additional grant of patent rights can be found in the PATENTS file in\n * the same directory.\n */\n\n!(function(global) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n var inModule = typeof module === \"object\";\n var runtime = global.regeneratorRuntime;\n if (runtime) {\n if (inModule) {\n // If regeneratorRuntime is defined globally and we're in a module,\n // make the exports object identical to regeneratorRuntime.\n module.exports = runtime;\n }\n // Don't bother evaluating the rest of this file if the runtime was\n // already defined globally.\n return;\n }\n\n // Define the runtime globally (as expected by generated code) as either\n // module.exports (if we're in a module) or a new, empty object.\n runtime = global.regeneratorRuntime = inModule ? module.exports : {};\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n runtime.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunctionPrototype[toStringTagSymbol] =\n GeneratorFunction.displayName = \"GeneratorFunction\";\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n prototype[method] = function(arg) {\n return this._invoke(method, arg);\n };\n });\n }\n\n runtime.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n runtime.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n if (!(toStringTagSymbol in genFun)) {\n genFun[toStringTagSymbol] = \"GeneratorFunction\";\n }\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n runtime.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return Promise.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return Promise.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration. If the Promise is rejected, however, the\n // result for this iteration will be rejected with the same\n // reason. Note that rejections of yielded Promises are not\n // thrown back into the generator function, as is the case\n // when an awaited Promise is rejected. This difference in\n // behavior between yield and await is important, because it\n // allows the consumer to decide what to do with the yielded\n // rejection (swallow it and continue, manually .throw it back\n // into the generator, abandon iteration, whatever). With\n // await, by contrast, there is no opportunity to examine the\n // rejection reason outside the generator function, so the\n // only option is to throw it from the await expression, and\n // let the generator function handle the exception.\n result.value = unwrapped;\n resolve(result);\n }, reject);\n }\n }\n\n if (typeof global.process === \"object\" && global.process.domain) {\n invoke = global.process.domain.bind(invoke);\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new Promise(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n runtime.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n runtime.async = function(innerFn, outerFn, self, tryLocsList) {\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList)\n );\n\n return runtime.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n if (delegate.iterator.return) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n Gp[toStringTagSymbol] = \"Generator\";\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n runtime.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n runtime.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n})(\n // Among the various tricks for obtaining a reference to the global\n // object, this seems to be the most reliable technique that does not\n // use indirect eval (which violates Content Security Policy).\n typeof global === \"object\" ? global :\n typeof window === \"object\" ? window :\n typeof self === \"object\" ? self : this\n);\n","// Polyfill for creating CustomEvents on IE9/10/11\n\n// code pulled from:\n// https://github.com/d4tocchini/customevent-polyfill\n// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill\n\ntry {\n var ce = new window.CustomEvent('test');\n ce.preventDefault();\n if (ce.defaultPrevented !== true) {\n // IE has problems with .preventDefault() on custom events\n // http://stackoverflow.com/questions/23349191\n throw new Error('Could not prevent default');\n }\n} catch(e) {\n var CustomEvent = function(event, params) {\n var evt, origPrevent;\n params = params || {\n bubbles: false,\n cancelable: false,\n detail: undefined\n };\n\n evt = document.createEvent(\"CustomEvent\");\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n origPrevent = evt.preventDefault;\n evt.preventDefault = function () {\n origPrevent.call(this);\n try {\n Object.defineProperty(this, 'defaultPrevented', {\n get: function () {\n return true;\n }\n });\n } catch(e) {\n this.defaultPrevented = true;\n }\n };\n return evt;\n };\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent; // expose definition to window\n}\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n\n switch (`${provider}:${type}`) {\n case 'html5:video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n case 'html5:audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || canPlayInline);\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!this.isHTML5 || !utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Check directly if codecs specified\n if (type.includes('codecs=')) {\n return media.canPlayType(type).replace(/no/, '');\n }\n\n // Type specific checks\n if (this.isVideo) {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.isAudio) {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText`\n result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\nexport default { providers, types };\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport loadjs from 'loadjs';\nimport support from './support';\nimport { providers } from './types';\n\nconst utils = {\n // Check variable types\n is: {\n plyr(input) {\n return this.instanceof(input, window.Plyr);\n },\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.nullOrUndefined(input) && Array.isArray(input);\n },\n weakMap(input) {\n return this.instanceof(input, window.WeakMap);\n },\n nodeList(input) {\n return this.instanceof(input, window.NodeList);\n },\n element(input) {\n return this.instanceof(input, window.Element);\n },\n textNode(input) {\n return this.getConstructor(input) === Text;\n },\n event(input) {\n return this.instanceof(input, window.Event);\n },\n cue(input) {\n return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);\n },\n track(input) {\n return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));\n },\n url(input) {\n return !this.nullOrUndefined(input) && /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-/]))?/.test(input);\n },\n nullOrUndefined(input) {\n return input === null || typeof input === 'undefined';\n },\n empty(input) {\n return (\n this.nullOrUndefined(input) ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||\n (this.object(input) && !Object.keys(input).length)\n );\n },\n instanceof(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n getConstructor(input) {\n return !this.nullOrUndefined(input) ? input.constructor : null;\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Fetch wrapper\n // Using XHR to avoid issues with older browsers\n fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.statusText);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n },\n\n // Load an external script\n loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (!utils.is.string(url)) {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = utils.is.string(id);\n let isCached = false;\n\n const exists = () => document.querySelectorAll(`#${id}`).length;\n\n function injectSprite(data) {\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n // Create container\n const container = document.createElement('div');\n utils.toggleHidden(container, true);\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n injectSprite.call(container, data.content);\n return;\n }\n }\n\n // Get the sprite\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.empty(result)) {\n return;\n }\n\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n injectSprite.call(container, result);\n })\n .catch(() => {});\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new <element>\n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove element(s)\n removeElement(element) {\n if (utils.is.nodeList(element) || utils.is.array(element)) {\n Array.from(element).forEach(utils.removeElement);\n return;\n }\n\n if (!utils.is.element(element) || !utils.is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Replace element\n replaceElement(newChild, oldChild) {\n if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n if (!utils.is.element(element) || utils.is.empty(attributes)) {\n return;\n }\n\n Object.entries(attributes).forEach(([\n key,\n value,\n ]) => {\n element.setAttribute(key, value);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle hidden\n toggleHidden(element, hidden) {\n if (!utils.is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!utils.is.boolean(hide)) {\n hide = !element.hasAttribute('hidden');\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.element(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.element(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus(element = null, toggle = false) {\n if (!utils.is.element(element)) {\n return;\n }\n\n const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n if (toggle) {\n utils.on(this.elements.container, 'keydown', trap, false);\n } else {\n utils.off(this.elements.container, 'keydown', trap, false);\n }\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no elemetns, event, or callback\n if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements) || utils.is.array(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events = '', callback, passive = true, capture = false) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!utils.is.element(element) || utils.is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: utils.is.plyr(this) ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // If multiple elements passed\n if (utils.is.array(element) || utils.is.nodeList(element)) {\n Array.from(element).forEach(target => utils.toggleState(target, input));\n return;\n }\n\n // Bail if no target\n if (!utils.is.element(element)) {\n return;\n }\n\n // Get state\n const pressed = element.getAttribute('aria-pressed') === 'true';\n const state = utils.is.boolean(input) ? input : !pressed;\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Format string\n format(input, ...args) {\n if (utils.is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : '');\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return (current / max * 100).toFixed(2);\n },\n\n // Time helpers\n getHours(value) {\n return parseInt((value / 60 / 60) % 60, 10);\n },\n getMinutes(value) {\n return parseInt((value / 60) % 60, 10);\n },\n getSeconds(value) {\n return parseInt(value % 60, 10);\n },\n\n // Format time to UI friendly string\n formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!utils.is.number(time)) {\n return this.formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = this.getHours(time);\n const mins = this.getMinutes(time);\n const secs = this.getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n },\n\n // Replace all occurances of a string in a string\n replaceAll(input = '', find = '', replace = '') {\n return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n },\n\n // Convert to title case\n toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n },\n\n // Convert string to pascalCase\n toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = utils.replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = utils.replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = utils.toTitleCase(string);\n\n // Convert to pascal case\n return utils.replaceAll(string, ' ', '');\n },\n\n // Convert string to pascalCase\n toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = utils.toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n },\n\n // Deep extend destination object with N more objects\n extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!utils.is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (utils.is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n utils.extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return utils.extend(target, ...sources);\n },\n\n // Remove duplicates in an array\n dedupe(array) {\n if (!utils.is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n },\n\n // Get the closest value in an array\n closest(array, value) {\n if (!utils.is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n },\n\n // Get the provider for a given URL\n getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.empty(url)) {\n return null;\n }\n\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert a URL to a location object\n parseUrl(url) {\n const parser = document.createElement('a');\n parser.href = url;\n return parser;\n },\n\n // Get URL query parameters\n getUrlParams(input) {\n let search = input;\n\n // Parse URL if needed\n if (input.startsWith('http://') || input.startsWith('https://')) {\n ({ search } = this.parseUrl(input));\n }\n\n if (this.is.empty(search)) {\n return null;\n }\n\n const hashes = search.slice(search.indexOf('?') + 1).split('&');\n\n return hashes.reduce((params, hash) => {\n const [\n key,\n val,\n ] = hash.split('=');\n\n return Object.assign(params, { [key]: decodeURIComponent(val) });\n }, {});\n },\n\n // Convert object to URL parameters\n buildUrlParams(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n get transitionEndEvent() {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return utils.is.string(type) ? events[type] : false;\n },\n\n // Force repaint of element\n repaint(element) {\n setTimeout(() => {\n utils.toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n utils.toggleHidden(element, false);\n }, 0);\n },\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return null;\n }\n\n return this.media.querySelectorAll('source');\n },\n\n // Get quality levels\n getQualityOptions() {\n if (!this.isHTML5) {\n return null;\n }\n\n // Get sources\n const sources = html5.getSources.call(this);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n // Get <source> with size attribute\n const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size')));\n\n // If none, bail\n if (utils.is.empty(sizes)) {\n return null;\n }\n\n // Reduce to unique list\n return utils.dedupe(sizes.map(source => Number(source.getAttribute('size'))));\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return null;\n }\n\n const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source);\n\n if (utils.is.empty(matches)) {\n return null;\n }\n\n return Number(matches[0].getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n if (utils.is.empty(sources)) {\n return;\n }\n\n // Get matches for requested size\n const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input);\n\n // No matches for requested size\n if (utils.is.empty(matches)) {\n return;\n }\n\n // Get supported sources\n const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type')));\n\n // No supported sources\n if (utils.is.empty(supported)) {\n return;\n }\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality: input,\n });\n\n // Get current state\n const { currentTime, playing } = player;\n\n // Set new source\n player.media.src = supported[0].getAttribute('src');\n\n // Load new source\n player.media.load();\n\n // Resume playing\n if (playing) {\n player.play();\n }\n\n // Restore time\n player.currentTime = currentTime;\n\n // Trigger change event\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n utils.removeElement(html5.getSources());\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport utils from './utils';\n\nconst i18n = {\n get(key = '', config = {}) {\n if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {\n return '';\n }\n\n let string = config.i18n[key];\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([\n key,\n value,\n ]) => {\n string = utils.replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n ui.updateVolume.call(this);\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n utils.dispatchEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Set the poster image\n ui.setPoster.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (utils.is.nodeList(this.elements.buttons.play)) {\n Array.from(this.elements.buttons.play).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Set the poster image\n setPoster() {\n if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) {\n return;\n }\n\n // Set the inline style\n const posters = this.poster.split(',');\n this.elements.poster.style.backgroundImage = posters.map(p => `url('${p}')`).join(',');\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set ARIA state\n utils.toggleState(this.elements.buttons.play, this.playing);\n\n // Only update controls on non timeupdate events\n if (utils.is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n this.toggleControls(!this.playing);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = [\n 'stalled',\n 'waiting',\n ].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Check if media failed to load\n checkFailed() {\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState\n this.failed = this.media.networkState === 3;\n\n if (this.failed) {\n utils.toggleClass(this.elements.container, this.config.classNames.loading, false);\n utils.toggleClass(this.elements.container, this.config.classNames.error, true);\n }\n\n // Clear timer\n clearTimeout(this.timers.failed);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.element(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (utils.is.element(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!utils.is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set <progress> value\n setProgress(target, input) {\n const value = utils.is.number(input) ? input : 0;\n const progress = utils.is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !utils.is.event(event)) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!utils.is.element(target) || !utils.is.number(time)) {\n return;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = utils.getHours(this.duration) > 0;\n\n // eslint-disable-next-line no-param-reassign\n target.textContent = utils.formatTime(time, forceHours, inverted);\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded\n durationUpdate() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's a spot to display duration\n const hasDuration = utils.is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport i18n from './i18n';\nimport support from './support';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria value for https://github.com/sampotts/plyr/issues/905\n range.setAttribute('aria-valuenow', range.value);\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n },\n\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (utils.is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type, attr) {\n let text = i18n.get(type, this.config);\n const attributes = Object.assign({}, attr);\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n if ('class' in attributes) {\n attributes.class += ` ${this.config.classNames.hidden}`;\n } else {\n attributes.class = this.config.classNames.hidden;\n }\n\n return utils.createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (utils.is.empty(text)) {\n return null;\n }\n\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const button = utils.createElement('button');\n const attributes = Object.assign({}, attr);\n let type = utils.toCamelCase(buttonType);\n\n let toggle = false;\n let label;\n let icon;\n let labelPressed;\n let iconPressed;\n\n if (!('type' in attributes)) {\n attributes.type = 'button';\n }\n\n if ('class' in attributes) {\n if (attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n toggle = true;\n label = 'play';\n labelPressed = 'pause';\n icon = 'play';\n iconPressed = 'pause';\n break;\n\n case 'mute':\n toggle = true;\n label = 'mute';\n labelPressed = 'unmute';\n icon = 'volume';\n iconPressed = 'muted';\n break;\n\n case 'captions':\n toggle = true;\n label = 'enableCaptions';\n labelPressed = 'disableCaptions';\n icon = 'captions-off';\n iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n toggle = true;\n label = 'enterFullscreen';\n labelPressed = 'exitFullscreen';\n icon = 'enter-fullscreen';\n iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n label = 'play';\n icon = 'play';\n break;\n\n default:\n label = type;\n icon = buttonType;\n }\n\n // Setup toggle icon and labels\n if (toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));\n button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));\n button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));\n\n // Add aria attributes\n attributes['aria-pressed'] = false;\n } else {\n button.appendChild(controls.createIcon.call(this, icon));\n button.appendChild(controls.createLabel.call(this, label));\n }\n\n // Merge attributes\n utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n\n utils.setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!utils.is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek label\n const label = utils.createElement(\n 'label',\n {\n for: attributes.id,\n id: `${attributes.id}-label`,\n class: this.config.classNames.hidden,\n },\n i18n.get(type, this.config),\n );\n\n // Seek input\n const input = utils.createElement(\n 'input',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-labelledby': `${attributes.id}-label`,\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return {\n label,\n input,\n };\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = utils.createElement(\n 'progress',\n utils.extend(\n utils.getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(utils.createElement('span', null, '0'));\n\n let suffix = '';\n switch (type) {\n case 'played':\n suffix = i18n.get('played', this.config);\n break;\n\n case 'buffer':\n suffix = i18n.get('buffered', this.config);\n break;\n\n default:\n break;\n }\n\n progress.textContent = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = utils.createElement('div', utils.extend(attributes, {\n class: `plyr__time ${attributes.class}`,\n 'aria-label': i18n.get(type, this.config),\n }), '00:00');\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Create a settings menu item\n createMenuItem(value, list, type, title, badge = null, checked = false) {\n const item = utils.createElement('li');\n\n const label = utils.createElement('label', {\n class: this.config.classNames.control,\n });\n\n const radio = utils.createElement(\n 'input',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'radio',\n name: `plyr-${type}`,\n value,\n checked,\n class: 'plyr__sr-only',\n }),\n );\n\n const faux = utils.createElement('span', { hidden: '' });\n\n label.appendChild(radio);\n label.appendChild(faux);\n label.insertAdjacentHTML('beforeend', title);\n\n if (utils.is.element(badge)) {\n label.appendChild(badge);\n }\n\n item.appendChild(label);\n list.appendChild(item);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !utils.is.element(this.elements.inputs.seek) ||\n !utils.is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.inputs.seek.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (utils.is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (utils.is.event(event) && [\n 'mouseenter',\n 'mouseleave',\n ].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Hide/show a tab\n toggleTab(setting, toggle) {\n utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);\n },\n\n // Set the quality menu\n // TODO: Vimeo support\n setQualityMenu(options) {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panes.quality.querySelector('ul');\n\n // Set options if passed and filter based on config\n if (utils.is.array(options)) {\n this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n let label = '';\n\n switch (quality) {\n case 2160:\n label = '4K';\n break;\n\n case 1440:\n case 1080:\n case 720:\n label = 'HD';\n break;\n\n case 576:\n case 480:\n label = 'SD';\n break;\n\n default:\n break;\n }\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n const label = controls.getLabel.call(this, 'quality', quality);\n controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Translate a value into a nice label\n // TODO: Localisation\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (utils.is.number(value)) {\n return `${value}p`;\n }\n\n return utils.toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panes[setting];\n let value = null;\n let list = container;\n\n switch (setting) {\n case 'captions':\n if (this.captions.active) {\n if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) {\n value = this.captions.language;\n } else {\n value = 'enabled';\n }\n } else {\n value = '';\n }\n\n break;\n\n default:\n value = !utils.is.empty(input) ? input : this[setting];\n\n // Get default\n if (utils.is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n\n break;\n }\n\n // Get the list if we need to\n if (!utils.is.element(list)) {\n list = pane && pane.querySelector('ul');\n }\n\n // If there's no list it means it's not been rendered...\n if (!utils.is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`input[value=\"${value}\"]`);\n\n if (utils.is.element(target)) {\n target.checked = true;\n }\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panes.loop.querySelector('ul');\n\n // Show the pane and tab\n utils.toggleHidden(this.elements.settings.tabs.loop, false);\n utils.toggleHidden(this.elements.settings.panes.loop, false);\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.loop.options);\n controls.toggleTab.call(this, 'loop', toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n options.forEach(option => {\n const item = utils.createElement('li');\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panes.captions.querySelector('ul');\n\n // Toggle the pane and tab\n const toggle = captions.getTracks.call(this).length;\n controls.toggleTab.call(this, type, toggle);\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Re-map the tracks into just the data we need\n const tracks = captions.getTracks.call(this).map(track => ({\n language: !utils.is.empty(track.language) ? track.language : 'enabled',\n label: captions.getLabel.call(this, track),\n }));\n\n // Add the \"Disabled\" option to turn off captions\n tracks.unshift({\n language: '',\n label: i18n.get('disabled', this.config),\n });\n\n // Generate options\n tracks.forEach(track => {\n controls.createMenuItem.call(\n this,\n track.language,\n list,\n 'language',\n track.label,\n track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null,\n track.language.toLowerCase() === this.captions.language.toLowerCase(),\n );\n });\n\n // Store reference\n this.options.captions = tracks.map(track => track.language);\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Do nothing if not selected\n if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) {\n return;\n }\n\n // Menu required\n if (!utils.is.element(this.elements.settings.panes.speed)) {\n return;\n }\n\n const type = 'speed';\n\n // Set the speed options\n if (utils.is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleTab.call(this, type, toggle);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the list to populate\n const list = this.elements.settings.panes.speed.querySelector('ul');\n\n // Empty the menu\n utils.emptyElement(list);\n\n // Create items\n this.options.speed.forEach(speed => {\n const label = controls.getLabel.call(this, 'speed', speed);\n controls.createMenuItem.call(this, speed, list, type, label);\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { tabs } = this.elements.settings;\n const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);\n\n utils.toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Show/hide menu\n toggleMenu(event) {\n const { form } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!utils.is.element(form) || !utils.is.element(button)) {\n return;\n }\n\n const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');\n\n if (utils.is.event(event)) {\n const isMenuItem = utils.is.element(form) && form.contains(event.target);\n const isButton = event.target === this.elements.buttons.settings;\n\n // If the click was inside the form or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && !isButton && show)) {\n return;\n }\n\n // Prevent the toggle being caught by the doc listener\n if (isButton) {\n event.stopPropagation();\n }\n }\n\n // Set form and button attributes\n if (utils.is.element(button)) {\n button.setAttribute('aria-expanded', show);\n }\n\n if (utils.is.element(form)) {\n utils.toggleHidden(form, !show);\n utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n if (show) {\n form.removeAttribute('tabindex');\n } else {\n form.setAttribute('tabindex', -1);\n }\n }\n },\n\n // Get the natural size of a tab\n getTabSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Prevent input's being unchecked due to the name being identical\n Array.from(clone.querySelectorAll('input[name]')).forEach(input => {\n const name = input.getAttribute('name');\n input.setAttribute('name', `${name}-clone`);\n });\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n utils.removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Toggle Menu\n showTab(target = '') {\n const { menu } = this.elements.settings;\n const pane = document.getElementById(target);\n\n // Nothing to show, bail\n if (!utils.is.element(pane)) {\n return;\n }\n\n // Are we targetting a tab? If not, bail\n const isTab = pane.getAttribute('role') === 'tabpanel';\n if (!isTab) {\n return;\n }\n\n // Hide all other tabs\n // Get other tabs\n const current = menu.querySelector('[role=\"tabpanel\"]:not([hidden])');\n const container = current.parentNode;\n\n // Set other toggles to be expanded false\n Array.from(menu.querySelectorAll(`[aria-controls=\"${current.getAttribute('id')}\"]`)).forEach(toggle => {\n toggle.setAttribute('aria-expanded', false);\n });\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getTabSize.call(this, pane);\n\n // Restore auto height/width\n const restore = e => {\n // We're only bothered about height and width on the container\n if (e.target !== container || ![\n 'width',\n 'height',\n ].includes(e.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n utils.off(container, utils.transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n utils.on(container, utils.transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n utils.toggleHidden(current, true);\n current.setAttribute('tabindex', -1);\n\n // Set attributes on target\n utils.toggleHidden(pane, false);\n\n const tabs = utils.getElements.call(this, `[aria-controls=\"${target}\"]`);\n Array.from(tabs).forEach(tab => {\n tab.setAttribute('aria-expanded', true);\n });\n pane.removeAttribute('tabindex');\n\n // Focus the first item\n pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Do nothing if we want no controls\n if (utils.is.empty(this.config.controls)) {\n return null;\n }\n\n // Create the container\n const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n const seek = controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n });\n progress.appendChild(seek.label);\n progress.appendChild(seek.input);\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = utils.createElement(\n 'span',\n {\n role: 'tooltip',\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n container.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n const volume = utils.createElement('div', {\n class: 'plyr__volume',\n });\n\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n const range = controls.createRange.call(\n this,\n 'volume',\n utils.extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n );\n volume.appendChild(range.label);\n volume.appendChild(range.input);\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n const menu = utils.createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n menu.appendChild(\n controls.createButton.call(this, 'settings', {\n id: `plyr-settings-toggle-${data.id}`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const form = utils.createElement('form', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tablist',\n tabindex: -1,\n });\n\n const inner = utils.createElement('div');\n\n const home = utils.createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,\n role: 'tabpanel',\n });\n\n // Create the tab list\n const tabs = utils.createElement('ul', {\n role: 'tablist',\n });\n\n // Build the tabs\n this.config.settings.forEach(type => {\n const tab = utils.createElement('li', {\n role: 'tab',\n hidden: '',\n });\n\n const button = utils.createElement(\n 'button',\n utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n id: `plyr-settings-${data.id}-${type}-tab`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-${type}`,\n 'aria-expanded': false,\n }),\n i18n.get(type, this.config),\n );\n\n const value = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n button.appendChild(value);\n tab.appendChild(button);\n tabs.appendChild(tab);\n\n this.elements.settings.tabs[type] = tab;\n });\n\n home.appendChild(tabs);\n inner.appendChild(home);\n\n // Build the panes\n this.config.settings.forEach(type => {\n const pane = utils.createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,\n role: 'tabpanel',\n tabindex: -1,\n });\n\n const back = utils.createElement(\n 'button',\n {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}-home`,\n 'aria-expanded': false,\n },\n i18n.get(type, this.config),\n );\n\n pane.appendChild(back);\n\n const options = utils.createElement('ul');\n\n pane.appendChild(options);\n inner.appendChild(pane);\n\n this.elements.settings.panes[type] = pane;\n });\n\n form.appendChild(inner);\n menu.appendChild(form);\n container.appendChild(menu);\n\n this.elements.settings.form = form;\n this.elements.settings.menu = menu;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n utils.loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {\n // String or HTMLElement passed as the option\n container = this.config.controls;\n } else if (utils.is.function(this.config.controls)) {\n // A custom function to build controls\n // The function can return a HTMLElement or String\n container = this.config.controls.call(this, props);\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([\n key,\n value,\n ]) => {\n result = utils.replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (utils.is.string(this.config.controls)) {\n container = replace(container);\n } else if (utils.is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (utils.is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!utils.is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML\n if (utils.is.element(container)) {\n target.appendChild(container);\n } else if (container) {\n target.insertAdjacentHTML('beforeend', container);\n }\n\n // Find the elements if need be\n if (!utils.is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Edge sometimes doesn't finish the paint so force a redraw\n if (window.navigator.userAgent.includes('Edge')) {\n utils.repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const labels = utils.getElements.call(\n this,\n [\n this.config.selectors.controls.wrapper,\n ' ',\n this.config.selectors.labels,\n ' .',\n this.config.classNames.hidden,\n ].join(''),\n );\n\n Array.from(labels).forEach(label => {\n utils.toggleClass(label, this.config.classNames.hidden, false);\n utils.toggleClass(label, this.config.classNames.tooltip, true);\n label.setAttribute('role', 'tooltip');\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport i18n from './i18n';\nimport support from './support';\nimport utils from './utils';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Set default language if not set\n const stored = this.storage.get('language');\n\n if (!utils.is.empty(stored)) {\n this.captions.language = stored;\n }\n\n if (utils.is.empty(this.captions.language)) {\n this.captions.language = this.config.captions.language.toLowerCase();\n }\n\n // Set captions enabled state if not set\n if (!utils.is.boolean(this.captions.active)) {\n const active = this.storage.get('captions');\n\n if (utils.is.boolean(active)) {\n this.captions.active = active;\n } else {\n this.captions.active = this.config.captions.active;\n }\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!utils.is.element(this.elements.captions)) {\n this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));\n\n utils.insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Set the class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));\n\n // Get tracks\n const tracks = captions.getTracks.call(this);\n\n // If no caption file exists, hide container for caption text\n if (utils.is.empty(tracks)) {\n return;\n }\n\n // Get browser info\n const browser = utils.getBrowser();\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const href = utils.parseUrl(src);\n\n if (href.hostname !== window.location.href.hostname && [\n 'http:',\n 'https:',\n ].includes(href.protocol)) {\n utils\n .fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n utils.removeElement(track);\n });\n }\n });\n }\n\n // Set language\n captions.setLanguage.call(this);\n\n // Enable UI\n captions.show.call(this);\n\n // Set available languages in list\n if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Set the captions language\n setLanguage() {\n // Setup HTML5 track rendering\n if (this.isHTML5 && this.isVideo) {\n captions.getTracks.call(this).forEach(track => {\n // Show track\n utils.on(track, 'cuechange', event => captions.setCue.call(this, event));\n\n // Turn off native caption rendering to avoid double captions\n // eslint-disable-next-line\n track.mode = 'hidden';\n });\n\n // Get current track\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Check if suported kind\n if (utils.is.track(currentTrack)) {\n // If we change the active track while a cue is already displayed we need to update it\n if (Array.from(currentTrack.activeCues || []).length) {\n captions.setCue.call(this, currentTrack);\n }\n }\n } else if (this.isVimeo && this.captions.active) {\n this.embed.enableTextTrack(this.language);\n }\n },\n\n // Get the tracks\n getTracks() {\n // Return empty array at least\n if (utils.is.nullOrUndefined(this.media)) {\n return [];\n }\n\n // Only get accepted kinds\n return Array.from(this.media.textTracks || []).filter(track => [\n 'captions',\n 'subtitles',\n ].includes(track.kind));\n },\n\n // Get the current track for the current language\n getCurrentTrack() {\n const tracks = captions.getTracks.call(this);\n\n if (!tracks.length) {\n return null;\n }\n\n // Get track based on current language\n let track = tracks.find(track => track.language.toLowerCase() === this.language);\n\n // Get the <track> with default attribute\n if (!track) {\n track = utils.getElement.call(this, 'track[default]');\n }\n\n // Get the first track\n if (!track) {\n [track] = tracks;\n }\n\n return track;\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (utils.is.track(currentTrack)) {\n if (!utils.is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!utils.is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Display active caption if it contains text\n setCue(input) {\n // Get the track from the event if needed\n const track = utils.is.event(input) ? input.target : input;\n const { activeCues } = track;\n const active = activeCues.length && activeCues[0];\n const currentTrack = captions.getCurrentTrack.call(this);\n\n // Only display current track\n if (track !== currentTrack) {\n return;\n }\n\n // Display a cue, if there is one\n if (utils.is.cue(active)) {\n captions.setText.call(this, active.getCueAsHTML());\n } else {\n captions.setText.call(this, null);\n }\n\n utils.dispatchEvent.call(this, this.media, 'cuechange');\n },\n\n // Set the current caption\n setText(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (utils.is.element(this.elements.captions)) {\n const content = utils.createElement('span');\n\n // Empty the container\n utils.emptyElement(this.elements.captions);\n\n // Default to empty\n const caption = !utils.is.nullOrUndefined(input) ? input : '';\n\n // Set the span content\n if (utils.is.string(caption)) {\n content.textContent = caption.trim();\n } else {\n content.appendChild(caption);\n }\n\n // Set new caption text\n this.elements.captions.appendChild(content);\n } else {\n this.debug.warn('No captions element to render to');\n }\n },\n\n // Display captions container and button (for initialization)\n show() {\n // Try to load the value from storage\n let active = this.storage.get('captions');\n\n // Otherwise fall back to the default config\n if (!utils.is.boolean(active)) {\n ({ active } = this.config.captions);\n } else {\n this.captions.active = active;\n }\n\n if (active) {\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true);\n utils.toggleState(this.elements.buttons.captions, true);\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [\n 4320,\n 2880,\n 2160,\n 1440,\n 1080,\n 720,\n 576,\n 480,\n 360,\n 240,\n 'default', // YouTube's \"auto\"\n ],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [\n 0.5,\n 0.75,\n 1,\n 1.25,\n 1.5,\n 1.75,\n 2,\n ],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: (navigator.language || navigator.userLanguage).split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: [\n 'captions',\n 'quality',\n 'speed',\n ],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n },\n\n // URLs\n urls: {\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n ads: 'plyr__ads',\n control: 'plyr__control',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n error: 'plyr--has-error',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// ==========================================================================\n\nimport utils from './utils';\n\nconst browser = utils.getBrowser();\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (utils.is.element(button)) {\n utils.toggleState(button, this.active);\n }\n\n // Trigger an event\n utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n utils.trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n // TODO: Filter for target??\n onChange.call(this);\n });\n\n // Fullscreen toggle on double click\n utils.on(this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (utils.is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n\n prefixes.some(pre => {\n if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native) {\n return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.playing) {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!utils.is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!utils.is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport utils from './utils';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.player.currentTime = this.player.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n this.player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n this.player.muted = !this.player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.player.forward();\n break;\n\n case 37:\n // Arrow back\n this.player.rewind();\n break;\n\n case 70:\n // F key\n this.player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n this.player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.player.loop = !this.player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) {\n this.player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n this.player.touch = true;\n\n // Add touch class\n utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);\n\n // Clean up\n utils.off(document.body, 'touchstart', this.firstTouch);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n // Keyboard shortcuts\n if (this.player.config.keyboard.global) {\n utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n utils.on(document.body, 'touchstart', this.firstTouch);\n }\n\n // Container listeners\n container() {\n // Keyboard shortcuts\n if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {\n utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.player.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.player.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.player.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => {\n this.player.toggleControls(event);\n });\n }\n }\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));\n\n // Display duration\n utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event));\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n utils.on(this.player.media, 'loadeddata', () => {\n utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);\n utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);\n });\n\n // Handle the media finishing\n utils.on(this.player.media, 'ended', () => {\n // Show poster on end\n if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {\n // Restart\n this.player.restart();\n }\n });\n\n // Check for buffer progress\n utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event));\n\n // Handle volume changes\n utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event));\n\n // Handle play/pause\n utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));\n\n // Loading state\n utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));\n\n // Check if media failed to load\n // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n utils.on(this.player.media, 'playing', () => {\n if (!this.player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (this.player.ads.enabled && !this.player.ads.initialized) {\n // Wait for manager response\n this.player.ads.managerPromise.then(() => this.player.ads.play()).catch(() => this.player.play());\n }\n });\n\n // Click video\n if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this.player, `.${this.player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!utils.is.element(wrapper)) {\n return;\n }\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.player.config.hideControls && this.player.touch && !this.player.paused) {\n return;\n }\n\n if (this.player.paused) {\n this.player.play();\n } else if (this.player.ended) {\n this.player.restart();\n this.player.play();\n } else {\n this.player.pause();\n }\n });\n }\n\n // Disable right click\n if (this.player.supported.ui && this.player.config.disableContextMenu) {\n utils.on(\n this.player.elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n utils.on(this.player.media, 'volumechange', () => {\n // Save to storage\n this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });\n });\n\n // Speed change\n utils.on(this.player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'speed');\n\n // Save to storage\n this.player.storage.set({ speed: this.player.speed });\n });\n\n // Quality request\n utils.on(this.player.media, 'qualityrequested', event => {\n // Save to storage\n this.player.storage.set({ quality: event.detail.quality });\n });\n\n // Quality change\n utils.on(this.player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);\n });\n\n // Caption language change\n utils.on(this.player.media, 'languagechange', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ language: this.player.language });\n });\n\n // Captions toggle\n utils.on(this.player.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this.player, 'captions');\n\n // Save to storage\n this.player.storage.set({ captions: this.player.captions.active });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.player.media, this.player.config.events.concat([\n 'keyup',\n 'keydown',\n ]).join(' '), event => {\n let detail = {};\n\n // Get error details from media\n if (event.type === 'error') {\n detail = this.player.media.error;\n }\n\n utils.dispatchEvent.call(this.player, this.player.elements.container, event.type, true, detail);\n });\n }\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Run default and custom handlers\n const proxy = (event, defaultHandler, customHandlerKey) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(this.player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && utils.is.function(defaultHandler)) {\n defaultHandler.call(this.player, event);\n }\n };\n\n // Trigger custom and default handlers\n const on = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const customHandler = this.player.config.listeners[customHandlerKey];\n const hasCustomHandler = utils.is.function(customHandler);\n\n utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n };\n\n // Play/pause toggle\n on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play');\n\n // Pause\n on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');\n\n // Rewind\n on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');\n\n // Rewind\n on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');\n\n // Mute toggle\n on(\n this.player.elements.buttons.mute,\n 'click',\n () => {\n this.player.muted = !this.player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions);\n\n // Fullscreen toggle\n on(\n this.player.elements.buttons.fullscreen,\n 'click',\n () => {\n this.player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n on(\n this.player.elements.buttons.pip,\n 'click',\n () => {\n this.player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');\n\n // Settings menu\n on(this.player.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this.player, event);\n });\n\n // Settings menu\n on(this.player.elements.settings.form, 'click', event => {\n event.stopPropagation();\n\n // Go back to home tab on click\n const showHomeTab = () => {\n const id = `plyr-settings-${this.player.id}-home`;\n controls.showTab.call(this.player, id);\n };\n\n // Settings menu items - use event delegation as items are added/removed\n if (utils.matches(event.target, this.player.config.selectors.inputs.language)) {\n proxy(\n event,\n () => {\n this.player.language = event.target.value;\n showHomeTab();\n },\n 'language',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.quality)) {\n proxy(\n event,\n () => {\n this.player.quality = event.target.value;\n showHomeTab();\n },\n 'quality',\n );\n } else if (utils.matches(event.target, this.player.config.selectors.inputs.speed)) {\n proxy(\n event,\n () => {\n this.player.speed = parseFloat(event.target.value);\n showHomeTab();\n },\n 'speed',\n );\n } else {\n const tab = event.target;\n controls.showTab.call(this.player, tab.getAttribute('aria-controls'));\n }\n });\n\n // Seek\n on(\n this.player.elements.inputs.seek,\n inputEvent,\n event => {\n this.player.currentTime = event.target.value / event.target.max * this.player.duration;\n },\n 'seek',\n );\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) {\n on(this.player.elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (this.player.currentTime === 0) {\n return;\n }\n\n this.player.config.invertTime = !this.player.config.invertTime;\n ui.timeUpdate.call(this.player);\n });\n }\n\n // Volume\n on(\n this.player.elements.inputs.volume,\n inputEvent,\n event => {\n this.player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n on(utils.getElements.call(this.player, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this.player, event.target);\n });\n }\n\n // Seek tooltip\n on(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event));\n\n // Toggle controls visibility based on mouse movement\n if (this.player.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mouseenter mouseleave', event => {\n this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.player.elements.controls.pressed = [\n 'mousedown',\n 'touchstart',\n ].includes(event.type);\n });\n\n // Focus in/out on controls\n on(this.player.elements.controls, 'focusin focusout', event => {\n this.player.toggleControls(event);\n });\n }\n\n // Mouse wheel for volume\n on(\n this.player.elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.player.decreaseVolume(step);\n direction = -1;\n } else {\n this.player.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.player.increaseVolume(step);\n direction = 1;\n } else {\n this.player.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n\n // Reset on destroy\n clear() {\n this.global(false);\n }\n}\n\nexport default Listeners;\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from './../captions';\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n vimeo.setAspectRatio.call(this);\n\n // Load the API if not already\n if (!utils.is.object(window.Vimeo)) {\n utils\n .loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // Set aspect ratio\n // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n if (this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n // muted: player.muted,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n };\n const params = utils.buildUrlParams(options);\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = utils.parseVimeoId(source);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = utils.format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Inject the package\n const wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = utils.replaceElement(wrapper, player.media);\n\n // Get poster image\n utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (utils.is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set attribute\n player.media.setAttribute('poster', url.href);\n\n // Update\n ui.setPoster.call(player);\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play().then(() => {\n player.media.paused = false;\n });\n };\n\n player.media.pause = () => {\n player.embed.pause().then(() => {\n player.media.paused = true;\n });\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time).catch(() => {\n // Do nothing\n });\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([\n player.embed.getVideoWidth(),\n player.embed.getVideoHeight(),\n ]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.setText.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n utils.dispatchEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport controls from './../controls';\nimport ui from './../ui';\nimport utils from './../utils';\n\n// Standardise YouTube quality unit\nfunction mapQualityUnit(input) {\n switch (input) {\n case 'hd2160':\n return 2160;\n\n case 2160:\n return 'hd2160';\n\n case 'hd1440':\n return 1440;\n\n case 1440:\n return 'hd1440';\n\n case 'hd1080':\n return 1080;\n\n case 1080:\n return 'hd1080';\n\n case 'hd720':\n return 720;\n\n case 720:\n return 'hd720';\n\n case 'large':\n return 480;\n\n case 480:\n return 'large';\n\n case 'medium':\n return 360;\n\n case 360:\n return 'medium';\n\n case 'small':\n return 240;\n\n case 240:\n return 'small';\n\n default:\n return 'default';\n }\n}\n\nfunction mapQualityUnits(levels) {\n if (utils.is.empty(levels)) {\n return levels;\n }\n\n return utils.dedupe(levels.map(level => mapQualityUnit(level)));\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n youtube.setAspectRatio.call(this);\n\n // Setup API\n if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n utils.loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (utils.is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (utils.is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (utils.is.string(key) && !utils.is.empty(key)) {\n const url = utils.format(this.config.urls.youtube.api, videoId, key);\n\n utils\n .fetch(url)\n .then(result => {\n if (utils.is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // Set aspect ratio\n setAspectRatio() {\n const ratio = this.config.ratio.split(':');\n this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`;\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (utils.is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = utils.parseYouTubeId(source);\n const id = utils.generateId(player.provider);\n const container = utils.createElement('div', { id });\n player.media = utils.replaceElement(container, player.media);\n\n // Set poster image\n player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId));\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n playerVars: {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: 1, // Allow iOS inline playback\n\n // Tracking for stats\n // origin: window ? `${window.location.protocol}//${window.location.host}` : null,\n widget_referrer: window ? window.location.href : null,\n\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n },\n events: {\n onError(event) {\n // If we've already fired an error, don't do it again\n // YouTube fires onError twice\n if (utils.is.object(player.media.error)) {\n return;\n }\n\n const detail = {\n code: event.data,\n };\n\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n switch (event.data) {\n case 2:\n detail.message =\n 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.';\n break;\n\n case 5:\n detail.message =\n 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';\n break;\n\n case 100:\n detail.message =\n 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';\n break;\n\n case 101:\n case 150:\n detail.message = 'The owner of the requested video does not allow it to be played in embedded players.';\n break;\n\n default:\n detail.message = 'An unknown error occured';\n break;\n }\n\n player.media.error = detail;\n\n utils.dispatchEvent.call(player, player.media, 'error');\n },\n onPlaybackQualityChange() {\n utils.dispatchEvent.call(player, player.media, 'qualitychange', false, {\n quality: player.media.quality,\n });\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n instance.playVideo();\n };\n\n player.media.pause = () => {\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n return mapQualityUnit(instance.getPlaybackQuality());\n },\n set(input) {\n const quality = input;\n\n // Set via API\n instance.setPlaybackQuality(mapQualityUnit(quality));\n\n // Trigger request event\n utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {\n quality,\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n utils.dispatchEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n player.media.paused = true;\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n utils.dispatchEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // If we were seeking, fire seeked event\n if (player.media.seeking) {\n utils.dispatchEvent.call(player, player.media, 'seeked');\n }\n player.media.seeking = false;\n\n // Only fire play if paused before\n if (player.media.paused) {\n utils.dispatchEvent.call(player, player.media, 'play');\n }\n player.media.paused = false;\n\n utils.dispatchEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n }\n\n // Get quality\n controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));\n\n break;\n\n case 2:\n player.media.paused = true;\n\n utils.dispatchEvent.call(player, player.media, 'pause');\n\n break;\n\n default:\n break;\n }\n\n utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport utils from './utils';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = utils.createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isEmbed) {\n switch (this.provider) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n } else if (this.isHTML5) {\n html5.extend.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport i18n from '../i18n';\nimport utils from '../utils';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.publisherId = player.config.ads.publisherId;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId);\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) {\n utils\n .loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the default tag URL\n get tagUrl() {\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${utils.buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = utils.createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = utils.formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!utils.is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (utils.is.element(seekElement)) {\n const cuePercentage = 100 / this.player.duration * cuePoint;\n const cue = utils.createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Get skippable state\n // TODO: Skip button\n // this.player.debug.warn(this.manager.getAdSkippableState());\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n utils.dispatchEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('seeking', () => {\n time = this.player.currentTime;\n return time;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (utils.is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (utils.is.array(handlers)) {\n handlers.forEach(handler => {\n if (utils.is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!utils.is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!utils.is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport { providers } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n this.type = input.type;\n this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;\n\n // Check for support\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // Create new markup\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n this.media = utils.createElement('video');\n break;\n\n case 'html5:audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube:video':\n case 'vimeo:video':\n this.media = utils.createElement('div', {\n src: input.sources[0].src,\n });\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!utils.is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport utils from './utils';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (utils.is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return utils.is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (utils.is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.3.6\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport Console from './console';\nimport controls from './controls';\nimport defaults from './defaults';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport { providers, types } from './types';\nimport ui from './ui';\nimport utils from './utils';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n captions: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n let params = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (utils.is.element(iframe)) {\n // Detect provider\n url = iframe.getAttribute('src');\n this.provider = utils.getProviderByUrl(url);\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n params = utils.getUrlParams(url);\n if (!utils.is.empty(params)) {\n const truthy = [\n '1',\n 'true',\n ];\n\n if (truthy.includes(params.autoplay)) {\n this.config.autoplay = true;\n }\n if (truthy.includes(params.loop)) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(params.playsinline);\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!utils.is.element(this.elements.container)) {\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n }\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n this.ads = new Ads(this);\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!utils.is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !utils.is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = utils.is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (utils.is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (utils.is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // True duration\n const realDuration = this.media ? Number(this.media.duration) : 0;\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!utils.is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - (utils.is.number(step) ? step : 1);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n }\n\n if (!utils.is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!utils.is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n let quality = null;\n\n if (!utils.is.empty(input)) {\n quality = Number(input);\n }\n\n if (!utils.is.number(quality) || quality === 0) {\n quality = this.storage.get('quality');\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.selected;\n }\n\n if (!utils.is.number(quality)) {\n quality = this.config.quality.default;\n }\n\n if (!this.options.quality.length) {\n return;\n }\n\n if (!this.options.quality.includes(quality)) {\n const closest = utils.closest(this.options.quality, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);\n quality = closest;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n ui.setPoster.call(this);\n }\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);\n\n // Nothing to change...\n if (this.captions.active === show) {\n return;\n }\n\n // Set global\n this.captions.active = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.active);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n /**\n * Set the captions language\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // If empty string is passed, assume disable captions\n if (utils.is.empty(input)) {\n this.toggleCaptions(false);\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // Check for support\n if (!this.options.captions.includes(language)) {\n this.debug.warn(`Unsupported language option: ${language}`);\n return;\n }\n\n // Ensure captions are enabled\n this.toggleCaptions(true);\n\n // Enabled only\n if (language === 'enabled') {\n return;\n }\n\n // If nothing to change, bail\n if (this.language === language) {\n return;\n }\n\n // Update config\n this.captions.language = language;\n\n // Clear caption\n captions.setText.call(this, null);\n\n // Update captions\n captions.setLanguage.call(this);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n }\n\n /**\n * Get the current captions language\n */\n get language() {\n return this.captions.language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} toggle - Whether to show the controls\n */\n toggleControls(toggle) {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // Don't hide if no UI support or it's audio\n if (!this.supported.ui || this.isAudio) {\n return;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n\n // Get toggle state if not set\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Events that show the controls\n const showEvents = [\n 'touchstart',\n 'touchmove',\n 'mouseenter',\n 'mousemove',\n 'focusin',\n ];\n\n // Events that delay hiding\n const delayEvents = [\n 'touchmove',\n 'touchend',\n 'mousemove',\n ];\n\n // Whether to show controls\n show = showEvents.includes(toggle.type);\n\n // Delay hiding on move events\n if (delayEvents.includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (!this.touch && toggle.type === 'focusin') {\n delay = 3000;\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer on every call\n clearTimeout(this.timers.controls);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.paused || this.loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.paused || this.loading) {\n return;\n }\n\n // Delay for hiding on touch\n if (this.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || this.playing) {\n this.timers.controls = setTimeout(() => {\n // We need controls of course...\n if (!utils.is.element(this.elements.controls)) {\n return;\n }\n\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Restore transition behaviour\n if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) {\n utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false);\n }\n\n // Set hideControls class\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, this.config.hideControls);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n utils.removeElement(this.elements.buttons.play);\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n this.listeners.clear();\n\n // Replace the container with the original element provided\n utils.replaceElement(this.elements.original, this.elements.container);\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Type specific stuff\n switch (`${this.provider}:${this.type}`) {\n case 'html5:video':\n case 'html5:audio':\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n case 'youtube:video':\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && utils.is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo:video':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return utils.loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (utils.is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (utils.is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (utils.is.array(selector)) {\n targets = selector.filter(i => utils.is.element(i));\n }\n\n if (utils.is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nexport default Plyr;\n"]}
\ No newline at end of file +{"version":3,"sources":["node_modules/custom-event-polyfill/polyfill.js","node_modules/url-polyfill/url-polyfill.js","node_modules/core-js/modules/_a-function.js","node_modules/core-js/modules/_ctx.js","node_modules/core-js/modules/_global.js","node_modules/core-js/modules/_core.js","node_modules/core-js/modules/_is-object.js","node_modules/core-js/modules/_an-object.js","node_modules/core-js/modules/_fails.js","node_modules/core-js/modules/_descriptors.js","node_modules/core-js/modules/_dom-create.js","node_modules/core-js/modules/_ie8-dom-define.js","node_modules/core-js/modules/_to-primitive.js","node_modules/core-js/modules/_object-dp.js","node_modules/core-js/modules/_property-desc.js","node_modules/core-js/modules/_hide.js","node_modules/core-js/modules/_has.js","node_modules/core-js/modules/_uid.js","node_modules/core-js/modules/_redefine.js","node_modules/core-js/modules/_export.js","node_modules/core-js/modules/_defined.js","node_modules/core-js/modules/_to-object.js","node_modules/core-js/modules/_iter-call.js","node_modules/core-js/modules/_iterators.js","node_modules/core-js/modules/_shared.js","node_modules/core-js/modules/_wks.js","node_modules/core-js/modules/_is-array-iter.js","node_modules/core-js/modules/_to-integer.js","node_modules/core-js/modules/_to-length.js","node_modules/core-js/modules/_create-property.js","node_modules/core-js/modules/_cof.js","node_modules/core-js/modules/_classof.js","node_modules/core-js/modules/core.get-iterator-method.js","node_modules/core-js/modules/_iter-detect.js","node_modules/core-js/modules/es6.array.from.js","node_modules/core-js/modules/_iobject.js","node_modules/core-js/modules/_is-array.js","node_modules/core-js/modules/_array-species-constructor.js","node_modules/core-js/modules/_array-species-create.js","node_modules/core-js/modules/_array-methods.js","node_modules/core-js/modules/_add-to-unscopables.js","node_modules/core-js/modules/es6.array.find.js","node_modules/core-js/modules/_object-pie.js","node_modules/core-js/modules/_to-iobject.js","node_modules/core-js/modules/_object-gopd.js","node_modules/core-js/modules/_set-proto.js","node_modules/core-js/modules/_inherit-if-required.js","node_modules/core-js/modules/_to-absolute-index.js","node_modules/core-js/modules/_array-includes.js","node_modules/core-js/modules/_shared-key.js","node_modules/core-js/modules/_object-keys-internal.js","node_modules/core-js/modules/_enum-bug-keys.js","node_modules/core-js/modules/_object-gopn.js","node_modules/core-js/modules/_string-ws.js","node_modules/core-js/modules/_string-trim.js","node_modules/core-js/modules/_object-keys.js","node_modules/core-js/modules/_object-dps.js","node_modules/core-js/modules/_html.js","node_modules/core-js/modules/_object-create.js","node_modules/core-js/modules/es6.number.constructor.js","node_modules/core-js/modules/_object-sap.js","node_modules/core-js/modules/es6.object.keys.js","node_modules/core-js/modules/_is-regexp.js","node_modules/core-js/modules/_string-context.js","node_modules/core-js/modules/_fails-is-regexp.js","node_modules/core-js/modules/es6.string.includes.js","node_modules/core-js/modules/es7.array.includes.js","node_modules/core-js/modules/_same-value.js","node_modules/core-js/modules/_regexp-exec-abstract.js","node_modules/core-js/modules/_flags.js","node_modules/core-js/modules/_regexp-exec.js","node_modules/core-js/modules/es6.regexp.exec.js","node_modules/core-js/modules/_fix-re-wks.js","node_modules/core-js/modules/es6.regexp.search.js","node_modules/core-js/modules/es6.regexp.flags.js","node_modules/core-js/modules/es6.regexp.to-string.js","node_modules/core-js/modules/_iter-step.js","node_modules/core-js/modules/_set-to-string-tag.js","node_modules/core-js/modules/_iter-create.js","node_modules/core-js/modules/_object-gpo.js","node_modules/core-js/modules/_iter-define.js","node_modules/core-js/modules/es6.array.iterator.js","node_modules/core-js/modules/web.dom.iterable.js","node_modules/core-js/modules/_string-at.js","node_modules/core-js/modules/es6.string.iterator.js","node_modules/core-js/modules/_meta.js","node_modules/core-js/modules/_object-gops.js","node_modules/core-js/modules/_object-assign.js","node_modules/core-js/modules/_redefine-all.js","node_modules/core-js/modules/_an-instance.js","node_modules/core-js/modules/_for-of.js","node_modules/core-js/modules/_validate-collection.js","node_modules/core-js/modules/_collection-weak.js","node_modules/core-js/modules/es6.weak-map.js","node_modules/core-js/modules/_collection.js","node_modules/core-js/modules/_strict-method.js","node_modules/core-js/modules/es6.array.sort.js","node_modules/core-js/modules/es6.object.assign.js","node_modules/core-js/modules/_species-constructor.js","node_modules/core-js/modules/_advance-string-index.js","node_modules/core-js/modules/es6.regexp.split.js","node_modules/core-js/modules/_object-to-array.js","node_modules/core-js/modules/es7.object.entries.js","node_modules/core-js/modules/es7.object.values.js","node_modules/core-js/modules/es6.regexp.replace.js","node_modules/core-js/modules/_invoke.js","node_modules/core-js/modules/_task.js","node_modules/core-js/modules/_microtask.js","node_modules/core-js/modules/_new-promise-capability.js","node_modules/core-js/modules/es6.promise.js","node_modules/core-js/modules/_perform.js","node_modules/core-js/modules/_user-agent.js","node_modules/core-js/modules/_set-species.js","node_modules/core-js/modules/_promise-resolve.js","node_modules/core-js/modules/es6.string.starts-with.js","node_modules/core-js/modules/es6.number.is-nan.js","src/js/utils/is.js","src/js/utils/events.js","src/js/utils/elements.js","src/js/utils/animation.js","src/js/utils/browser.js","src/js/support.js","src/js/html5.js","src/js/utils/arrays.js","src/js/utils/objects.js","node_modules/core-js/modules/es6.regexp.constructor.js","src/js/utils/strings.js","src/js/utils/i18n.js","src/js/storage.js","src/js/utils/fetch.js","src/js/utils/loadSprite.js","node_modules/core-js/modules/es6.math.trunc.js","src/js/utils/time.js","src/js/controls.js","src/js/utils/urls.js","src/js/captions.js","src/js/config/defaults.js","src/js/config/states.js","src/js/config/types.js","src/js/console.js","src/js/fullscreen.js","node_modules/core-js/modules/_math-sign.js","src/js/utils/loadImage.js","node_modules/core-js/modules/es6.math.sign.js","src/js/ui.js","src/js/utils/style.js","src/js/listeners.js","node_modules/core-js/modules/es6.function.name.js","node_modules/core-js/modules/es6.regexp.match.js","node_modules/loadjs/dist/loadjs.umd.js","src/js/utils/loadScript.js","src/js/plugins/vimeo.js","src/js/plugins/youtube.js","src/js/media.js","src/js/plugins/ads.js","node_modules/core-js/modules/es6.array.find-index.js","src/js/plugins/previewThumbnails.js","src/js/source.js","src/js/plyr.js"],"names":["window","ce","CustomEvent","cancelable","preventDefault","defaultPrevented","Error","e","event","params","evt","origPrevent","bubbles","detail","undefined","document","createEvent","initCustomEvent","call","this","Object","defineProperty","get","prototype","Event","global","iteratorSupported","Symbol","iterator","error","checkIfIteratorIsSupported","createIterator","items","next","value","shift","done","serializeParam","encodeURIComponent","replace","deserializeParam","decodeURIComponent","URLSearchParams","toString","searchString","writable","typeofSearchString","_fromString","_this","forEach","name","append","TypeError","i","length","entry","key","hasOwnProperty","proto","_entries","push","String","delete","getAll","slice","has","set","callback","thisArg","entries","keys","values","searchArray","join","polyfillURLSearchParams","sort","a","b","enumerable","configurable","attribute","attributes","split","self","u","URL","pathname","href","searchParams","checkIfURLIsSupported","_URL","url","base","baseElement","doc","location","implementation","createHTMLDocument","createElement","head","appendChild","indexOf","err","anchorElement","body","protocol","test","search","enableSearchUpdate","enableSearchParamsUpdate","methodName","method","apply","arguments","attributeName","_anchorElement","linkURLWithAnchorAttribute","_updateSearchParams","defineProperties","origin","expectedPort","http:","https:","ftp:","addPortToOrigin","port","hostname","password","username","createObjectURL","blob","revokeObjectURL","polyfillURL","getOrigin","setInterval","_aFunction","it","_ctx","fn","that","aFunction","c","module","exports","Math","Function","__g","core","version","__e","_isObject","_anObject","isObject","_fails","exec","_descriptors","require$$0","is","_domCreate","_ie8DomDefine","require$$1","require$$2","_toPrimitive","S","val","valueOf","dP","O","P","Attributes","anObject","toPrimitive","IE8_DOM_DEFINE","_propertyDesc","bitmap","_hide","object","f","createDesc","_has","id","px","random","_uid","concat","SRC","$toString","TPL","inspectSource","safe","isFunction","hide","$export","type","source","own","out","exp","IS_FORCED","F","IS_GLOBAL","G","IS_STATIC","IS_PROTO","IS_BIND","B","target","expProto","ctx","redefine","U","W","R","_export","_defined","_toObject","defined","_iterCall","ret","_iterators","store","mode","copyright","USE_SYMBOL","uid","ITERATOR","ArrayProto","Array","_isArrayIter","Iterators","ceil","floor","_toInteger","isNaN","min","_toLength","toInteger","_createProperty","index","$defineProperty","_cof","TAG","ARG","cof","_classof","T","tryGet","callee","core_getIteratorMethod","getIteratorMethod","classof","SAFE_CLOSING","_iterDetect","skipClosing","arr","iter","from","arrayLike","result","step","toObject","C","aLen","mapfn","mapping","iterFn","getIterFn","isArrayIter","toLength","createProperty","_iobject","propertyIsEnumerable","_isArray","isArray","arg","SPECIES","_arraySpeciesCreate","original","constructor","_arrayMethods","TYPE","$create","IS_MAP","IS_FILTER","IS_SOME","IS_EVERY","IS_FIND_INDEX","NO_HOLES","create","asc","$this","callbackfn","res","IObject","UNSCOPABLES","_addToUnscopables","$find","forced","find","_toIobject","gOPD","getOwnPropertyDescriptor","toIObject","pIE","check","setPrototypeOf","buggy","__proto__","_inheritIfRequired","max","_arrayIncludes","IS_INCLUDES","el","fromIndex","toAbsoluteIndex","shared","_sharedKey","arrayIndexOf","IE_PROTO","_objectKeysInternal","names","_enumBugKeys","hiddenKeys","getOwnPropertyNames","$keys","_stringWs","space","spaces","ltrim","RegExp","rtrim","exporter","KEY","ALIAS","FORCE","fails","trim","string","_stringTrim","_objectKeys","enumBugKeys","_objectDps","Properties","getKeys","_html","documentElement","Empty","createDict","iframeDocument","iframe","style","display","src","contentWindow","open","write","lt","close","_objectCreate","dPs","gOPN","$trim","require$$3","$Number","Base","BROKEN_COF","require$$4","TRIM","toNumber","argument","third","radix","maxCode","first","charCodeAt","NaN","code","digits","l","parseInt","inheritIfRequired","require$$5","j","require$$6","MATCH","_isRegexp","isRegExp","_stringContext","NAME","_failsIsRegexp","re","includes","context","$includes","_sameValue","x","y","builtinExec","_regexpExecAbstract","_flags","ignoreCase","multiline","unicode","sticky","nativeExec","nativeReplace","patchedExec","UPDATES_LAST_INDEX_WRONG","re1","re2","NPCG_INCLUDED","str","lastIndex","reCopy","match","regexpFlags","_regexpExec","regexpExec","wks","REPLACE_SUPPORTS_NAMED_GROUPS","groups","SPLIT_WORKS_WITH_OVERWRITTEN_EXEC","originalExec","_fixReWks","SYMBOL","DELEGATES_TO_SYMBOL","DELEGATES_TO_EXEC","execCalled","nativeRegExpMethod","fns","nativeMethod","regexp","arg2","forceStringMethod","strfn","rxfn","SEARCH","$search","maybeCallNative","rx","previousLastIndex","sameValue","regExpExec","flags","define","DESCRIPTORS","$flags","_iterStep","def","_setToStringTag","tag","stat","IteratorPrototype","_iterCreate","Constructor","descriptor","setToStringTag","ObjectProto","_objectGpo","getPrototypeOf","BUGGY","returnThis","_iterDefine","DEFAULT","IS_SET","FORCED","$iterCreate","methods","getMethod","kind","DEF_VALUES","VALUES_BUG","$native","$default","$entries","$anyNative","es6_array_iterator","iterated","_t","_i","_k","Arguments","addToUnscopables","TO_STRING_TAG","ArrayValues","DOMIterables","CSSRuleList","CSSStyleDeclaration","CSSValueList","ClientRectList","DOMRectList","DOMStringList","DOMTokenList","DataTransferItemList","FileList","HTMLAllCollection","HTMLCollection","HTMLFormElement","HTMLSelectElement","MediaList","MimeTypeArray","NamedNodeMap","NodeList","PaintRequestList","Plugin","PluginArray","SVGLengthList","SVGNumberList","SVGPathSegList","SVGPointList","SVGStringList","SVGTransformList","SourceBufferList","StyleSheetList","TextTrackCueList","TextTrackList","TouchList","collections","explicit","Collection","$iterators","_stringAt","TO_STRING","pos","s","charAt","$at","point","META","setDesc","isExtensible","FREEZE","preventExtensions","setMeta","w","meta","NEED","fastKey","getWeak","onFreeze","getOwnPropertySymbols","$assign","assign","_objectAssign","A","K","k","getSymbols","gOPS","isEnum","_redefineAll","_anInstance","forbiddenField","BREAK","RETURN","iterable","_validateCollection","arrayFind","createArrayMethod","arrayFindIndex","uncaughtFrozenStore","_l","UncaughtFrozenStore","findUncaughtFrozen","splice","_collectionWeak","getConstructor","wrapper","ADDER","anInstance","forOf","redefineAll","data","validate","$has","ufstore","InternalMap","each","weak","tmp","$WeakMap","common","IS_WEAK","fixMethod","instance","HASNT_CHAINING","THROWS_ON_PRIMITIVES","ACCEPT_ITERABLES","$iterDetect","BUGGY_ZERO","$instance","clear","setStrong","freeze","_f","$sort","comparefn","_speciesConstructor","D","at","_advanceStringIndex","$min","$push","SUPPORTS_Y","SPLIT","$split","internalSplit","separator","limit","lastLength","output","lastLastIndex","splitLimit","separatorCopy","splitter","speciesConstructor","unicodeMatching","lim","callRegExpExec","p","q","z","advanceStringIndex","_objectToArray","isEntries","$values","SUBSTITUTION_SYMBOLS","SUBSTITUTION_SYMBOLS_NO_NAMED","REPLACE","$replace","searchValue","replaceValue","functionalReplace","fullUnicode","results","accumulatedResult","nextSourcePosition","matched","position","captures","namedCaptures","replacerArgs","replacement","getSubstitution","tailPos","m","symbols","ch","capture","n","defer","channel","process","setTask","setImmediate","clearTask","clearImmediate","MessageChannel","Dispatch","counter","queue","run","listener","args","un","invoke","nextTick","now","port2","port1","onmessage","postMessage","addEventListener","importScripts","cel","html","removeChild","setTimeout","_task","macrotask","Observer","MutationObserver","WebKitMutationObserver","Promise","isNode","PromiseCapability","resolve","reject","promise","$$resolve","$$reject","Internal","newGenericPromiseCapability","OwnPromiseCapability","Wrapper","_perform","v","navigator","_userAgent","userAgent","_setSpecies","task","microtask","last","notify","flush","parent","domain","exit","enter","standalone","then","toggle","node","createTextNode","observe","characterData","versions","v8","$Promise","empty","newPromiseCapability","newPromiseCapabilityModule","USE_NATIVE","FakePromise","PromiseRejectionEvent","isThenable","isReject","_n","chain","_c","_v","ok","_s","reaction","exited","handler","fail","_h","onHandleUnhandled","onUnhandled","console","unhandled","isUnhandled","perform","emit","onunhandledrejection","reason","_a","onrejectionhandled","$reject","_d","_w","$resolve","executor","onFulfilled","onRejected","catch","r","capability","promiseCapability","promiseResolve","require$$7","all","remaining","$index","alreadyCalled","race","$startsWith","startsWith","number","input","instanceOf","Boolean","isNullOrUndefined","isString","isNodeList","isEmpty","is$1","nullOrUndefined","Number","boolean","function","array","weakMap","WeakMap","nodeList","element","Element","textNode","Text","keyboardEvent","KeyboardEvent","cue","TextTrackCue","VTTCue","track","TextTrack","supportsPassiveListeners","supported","options","removeEventListener","toggleListener","passive","events","eventListeners","on","off","once","_this2","onceCallback","_len","_key","triggerEvent","plyr","dispatchEvent","wrap","elements","targets","reverse","child","cloneNode","parentNode","sibling","nextSibling","insertBefore","setAttributes","filter","_ref","_slicedToArray","_ref3","_ref4","setAttribute","text","innerText","insertElement","removeElement","emptyElement","childNodes","lastChild","replaceElement","newChild","oldChild","replaceChild","getAttributesFromSelector","sel","existingAttributes","existing","selector","className","parts","class","toggleHidden","hidden","removeAttribute","toggleClass","force","map","classList","contains","hasClass","matches","querySelectorAll","getElements","container","getElement","querySelector","setFocus","tabFocus","focus","preventScroll","config","classNames","transitionEndEvent","WebkitTransition","MozTransition","OTransition","transition","repaint","offsetHeight","range","browser","isIE","documentMode","isEdge","isWebkit","isIPhone","platform","isIos","defaultCodecs","audio/ogg","audio/wav","video/webm","video/mp4","video/ogg","support","audio","video","provider","playsinline","canPlayInline","api","ui","rangeInput","pip","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","mime","mediaType","isHTML5","media","canPlayType","textTracks","touch","transitions","reducedMotion","matchMedia","html5","getSources","getAttribute","getQualityOptions","extend","player","_player$media","currentTime","paused","preload","readyState","play","load","quality","cancelRequests","blankVideo","debug","log","dedupe","item","getDeep","path","reduce","obj","sources","_defineProperty","$RegExp","CORRECT_NEW","tiRE","piRE","fiU","proxy","format","replaceAll","toTitleCase","toUpperCase","substr","toLowerCase","toCamelCase","toPascalCase","getHTML","innerHTML","resources","vimeo","youtube","i18n","{seektime}","seekTime","{title}","title","_ref2","Storage","_classCallCheck","enabled","storage","localStorage","getItem","json","JSON","parse","setItem","stringify","removeItem","fetch","responseType","request","XMLHttpRequest","responseText","response","status","send","loadSprite","hasId","exists","getElementById","update","insertAdjacentElement","useStorage","cached","content","trunc","getHours","getMinutes","getSeconds","formatTime","time","displayHours","inverted","hours","mins","secs","controls","getIconUrl","cors","iconUrl","host","svg4everybody","findElements","selectors","buttons","pause","restart","rewind","fastForward","mute","settings","captions","fullscreen","progress","inputs","seek","volume","buffer","duration","seekTooltip","tooltip","warn","toggleNativeControls","createIcon","iconPath","iconPrefix","icon","createElementNS","role","focusable","use","setAttributeNS","createLabel","attr","createBadge","badge","menu","createButton","buttonType","props","label","labelPressed","iconPressed","control","button","createRange","autocomplete","aria-label","aria-valuemin","aria-valuemax","aria-valuenow","updateRangeFill","createProgress","aria-hidden","suffixKey","played","suffix","createTime","bindMenuItemShortcuts","menuItem","which","stopPropagation","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","list","_ref$badge","_ref$checked","checked","aria-checked","flex","children","listeners","bind","currentTrack","speed","parseFloat","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","_this3","current","toFixed","getElementsByTagName","nodeValue","setProgress","buffered","percent","setProperty","updateSeekTooltip","_this4","tooltips","clientRect","getBoundingClientRect","visible","width","pageX","left","timeUpdate","invert","invertTime","seeking","durationUpdate","pow","hasDuration","displayDuration","toggleMenuButton","setting","updateSetting","pane","panels","default","getLabel","setQualityMenu","_this5","checkMenu","getBadge","sorting","setCaptionsMenu","_this6","tracks","getTracks","toggled","language","unshift","setSpeedMenu","_this7","isVimeo","some","popup","firstItem","toggleMenu","show","isMenuItem","getMenuSize","tab","clone","opacity","scrollWidth","height","scrollHeight","_this8","size","restore","propertyName","setDownloadLink","download","_this9","aria-haspopup","aria-controls","aria-expanded","inner","home","backButton","urls","isEmbed","inject","_this10","seektime","addProperty","controlPressed","_this$config","labels","parseUrl","parser","buildUrlParams","setup","isVideo","isYouTube","languages","userLanguage","active","trackEvents","_this$captions","currentTrackNode","languageExists","updateCues","setLanguage","activeClass","findTrack","_toConsumableArray","embed","enableTextTrack","sortIsDefault","sorted","every","getCurrentTrack","cues","activeCues","getCueAsHTML","cueText","caption","defaults","autoplay","autopause","toggleInvert","ratio","clickToPlay","hideControls","resetOnEnd","disableContextMenu","loop","selected","keyboard","focused","fallback","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","start","end","reset","disabled","advertisement","qualityBadge","2160","1440","1080","720","576","480","sdk","googleIMA","editable","embedContainer","poster","posterEnabled","ads","playing","stopped","loading","hover","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","google","publisherId","tagUrl","byline","portrait","transparent","noCookie","rel","showinfo","iv_load_policy","modestbranding","providers","types","noop","Console","onChange","keyCode","activeElement","shiftKey","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","overflow","viewport","property","hasProperty","cleanupViewport","part","Fullscreen","prefix","forceFallback","native","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","_mathSign","sign","loadImage","minWidth","image","Image","onload","onerror","naturalWidth","addStyleHook","build","checkPlaying","ready","setTitle","setPoster","togglePoster","enable","backgroundImage","backgroundSize","toggleControls","checkLoading","clearTimeout","timers","recentTouchSeek","lastSeekTime","Date","setAspectRatio","_ratio$split$map2","padding","paddingBottom","offset","transform","Listeners","lastKey","focusTimer","lastKeyDown","handleKey","setTabFocus","firstTouch","repeat","altKey","ctrlKey","metaKey","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","usingNative","timeStamp","wasKeyDown","delay","setPlayerSize","measure","rect","resized","_player$fullscreen","isEnter","_setPlayerSize","firstChild","_player$embed$ratio$s2","videoWidth","videoHeight","maxWidth","margin","setGutter","hasAudio","initialized","managerPromise","isAudio","ended","proxyEvents","_event$detail","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","currentTarget","hasAttribute","seekTo","loaded","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","_map2","deltaX","deltaY","direction","abs","FProto","nameRE","$match","matchStr","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","executeCallbacks","depsNotFound","success","loadFile","callbackFn","numTries","isCss","async","maxTries","numRetries","beforeCallbackFn","before","pathStripped","onbeforeload","ev","sheet","cssText","loadjs","paths","arg1","numWaiting","loadFiles","deps","bundleIds","subscribe","isDefined","factory","loadScript","assurePlaybackState","hasPlayed","Vimeo","gesture","$2","thumbnail_large","Player","disableTextTrack","stop","restorePause","setVolume","setCurrentTime","setPlaybackRate","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","_dimensions","setAutopause","state","getVideoTitle","getCurrentTime","getDuration","getTextTracks","_ref$cues","strippedCues","fragment","createDocumentFragment","getPaused","seconds","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getTitle","videoId","getVideoData","snippet","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","onError","message","2","5","100","101","150","onPlaybackRateChange","playbackRate","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","getAvailablePlaybackRates","clearInterval","buffering","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","displayContainer","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","LOG","adError","getMessage","cancel","contentComplete","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","init","zIndex","destroy","_this11","handlers","_this12","AV_PUBLISHERID","AV_CHANNELID","AV_URL","cb","AV_WIDTH","AV_HEIGHT","AV_CDIM2","findIndex","PreviewThumbnails","thumbnails","lastMouseMoveTime","mouseDown","loadedImages","thumb","scrubbing","getThumbnails","render","determineContainerAutoSizing","promises","getThumbnail","vttDataString","processedList","thumbnail","frames","frame","line","startTime","lineSplit","_lineSplit","_lineSplit$1$split2","h","matchTimes","endTime","urlPrefix","substring","lastIndexOf","tempImage","naturalHeight","percentage","mousePosX","showImageAtCurrentTime","toggleThumbContainer","toggleScrubbingContainer","lastTime","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","hasThumb","qualityIndex","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","filename","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","tagName","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","clientHeight","sizeSpecifiedInCSS","thumbWidth","thumbAspectRatio","setThumbContainerPos","seekbarRect","plyrRect","minVal","maxVal","right","clientWidth","previewPos","multiplier","top","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","change","_sources$","_sources$$provider","crossorigin","Plyr","failed","jQuery","getProviderByUrl","truthy","tabindex","webkitShowPlaybackTargetPicker","isHidden","hiding","eventName","soft","unload","inputIsValid","fauxDuration","realDuration","Infinity","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","updateStorage","prev","curr","closest","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","inline","t"],"mappings":"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","file":"plyr.polyfilled.min.js","sourcesContent":["// Polyfill for creating CustomEvents on IE9/10/11\n\n// code pulled from:\n// https://github.com/d4tocchini/customevent-polyfill\n// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill\n\n(function() {\n if (typeof window === 'undefined') {\n return;\n }\n\n try {\n var ce = new window.CustomEvent('test', { cancelable: true });\n ce.preventDefault();\n if (ce.defaultPrevented !== true) {\n // IE has problems with .preventDefault() on custom events\n // http://stackoverflow.com/questions/23349191\n throw new Error('Could not prevent default');\n }\n } catch (e) {\n var CustomEvent = function(event, params) {\n var evt, origPrevent;\n params = params || {\n bubbles: false,\n cancelable: false,\n detail: undefined\n };\n\n evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(\n event,\n params.bubbles,\n params.cancelable,\n params.detail\n );\n origPrevent = evt.preventDefault;\n evt.preventDefault = function() {\n origPrevent.call(this);\n try {\n Object.defineProperty(this, 'defaultPrevented', {\n get: function() {\n return true;\n }\n });\n } catch (e) {\n this.defaultPrevented = true;\n }\n };\n return evt;\n };\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent; // expose definition to window\n }\n})();\n","(function(global) {\r\n /**\r\n * Polyfill URLSearchParams\r\n *\r\n * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js\r\n */\r\n\r\n var checkIfIteratorIsSupported = function() {\r\n try {\r\n return !!Symbol.iterator;\r\n } catch (error) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var iteratorSupported = checkIfIteratorIsSupported();\r\n\r\n var createIterator = function(items) {\r\n var iterator = {\r\n next: function() {\r\n var value = items.shift();\r\n return { done: value === void 0, value: value };\r\n }\r\n };\r\n\r\n if (iteratorSupported) {\r\n iterator[Symbol.iterator] = function() {\r\n return iterator;\r\n };\r\n }\r\n\r\n return iterator;\r\n };\r\n\r\n /**\r\n * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing\r\n * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.\r\n */\r\n var serializeParam = function(value) {\r\n return encodeURIComponent(value).replace(/%20/g, '+');\r\n };\r\n\r\n var deserializeParam = function(value) {\r\n return decodeURIComponent(value).replace(/\\+/g, ' ');\r\n };\r\n\r\n var polyfillURLSearchParams = function() {\r\n\r\n var URLSearchParams = function(searchString) {\r\n Object.defineProperty(this, '_entries', { writable: true, value: {} });\r\n var typeofSearchString = typeof searchString;\r\n\r\n if (typeofSearchString === 'undefined') {\r\n // do nothing\r\n } else if (typeofSearchString === 'string') {\r\n if (searchString !== '') {\r\n this._fromString(searchString);\r\n }\r\n } else if (searchString instanceof URLSearchParams) {\r\n var _this = this;\r\n searchString.forEach(function(value, name) {\r\n _this.append(name, value);\r\n });\r\n } else if ((searchString !== null) && (typeofSearchString === 'object')) {\r\n if (Object.prototype.toString.call(searchString) === '[object Array]') {\r\n for (var i = 0; i < searchString.length; i++) {\r\n var entry = searchString[i];\r\n if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {\r\n this.append(entry[0], entry[1]);\r\n } else {\r\n throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\\'s input');\r\n }\r\n }\r\n } else {\r\n for (var key in searchString) {\r\n if (searchString.hasOwnProperty(key)) {\r\n this.append(key, searchString[key]);\r\n }\r\n }\r\n }\r\n } else {\r\n throw new TypeError('Unsupported input\\'s type for URLSearchParams');\r\n }\r\n };\r\n\r\n var proto = URLSearchParams.prototype;\r\n\r\n proto.append = function(name, value) {\r\n if (name in this._entries) {\r\n this._entries[name].push(String(value));\r\n } else {\r\n this._entries[name] = [String(value)];\r\n }\r\n };\r\n\r\n proto.delete = function(name) {\r\n delete this._entries[name];\r\n };\r\n\r\n proto.get = function(name) {\r\n return (name in this._entries) ? this._entries[name][0] : null;\r\n };\r\n\r\n proto.getAll = function(name) {\r\n return (name in this._entries) ? this._entries[name].slice(0) : [];\r\n };\r\n\r\n proto.has = function(name) {\r\n return (name in this._entries);\r\n };\r\n\r\n proto.set = function(name, value) {\r\n this._entries[name] = [String(value)];\r\n };\r\n\r\n proto.forEach = function(callback, thisArg) {\r\n var entries;\r\n for (var name in this._entries) {\r\n if (this._entries.hasOwnProperty(name)) {\r\n entries = this._entries[name];\r\n for (var i = 0; i < entries.length; i++) {\r\n callback.call(thisArg, entries[i], name, this);\r\n }\r\n }\r\n }\r\n };\r\n\r\n proto.keys = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push(name);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.values = function() {\r\n var items = [];\r\n this.forEach(function(value) {\r\n items.push(value);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.entries = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n if (iteratorSupported) {\r\n proto[Symbol.iterator] = proto.entries;\r\n }\r\n\r\n proto.toString = function() {\r\n var searchArray = [];\r\n this.forEach(function(value, name) {\r\n searchArray.push(serializeParam(name) + '=' + serializeParam(value));\r\n });\r\n return searchArray.join('&');\r\n };\r\n\r\n\r\n global.URLSearchParams = URLSearchParams;\r\n };\r\n\r\n if (!('URLSearchParams' in global) || (new URLSearchParams('?a=1').toString() !== 'a=1')) {\r\n polyfillURLSearchParams();\r\n }\r\n\r\n var proto = URLSearchParams.prototype;\r\n\r\n if (typeof proto.sort !== 'function') {\r\n proto.sort = function() {\r\n var _this = this;\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n if (!_this._entries) {\r\n _this.delete(name);\r\n }\r\n });\r\n items.sort(function(a, b) {\r\n if (a[0] < b[0]) {\r\n return -1;\r\n } else if (a[0] > b[0]) {\r\n return +1;\r\n } else {\r\n return 0;\r\n }\r\n });\r\n if (_this._entries) { // force reset because IE keeps keys index\r\n _this._entries = {};\r\n }\r\n for (var i = 0; i < items.length; i++) {\r\n this.append(items[i][0], items[i][1]);\r\n }\r\n };\r\n }\r\n\r\n if (typeof proto._fromString !== 'function') {\r\n Object.defineProperty(proto, '_fromString', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function(searchString) {\r\n if (this._entries) {\r\n this._entries = {};\r\n } else {\r\n var keys = [];\r\n this.forEach(function(value, name) {\r\n keys.push(name);\r\n });\r\n for (var i = 0; i < keys.length; i++) {\r\n this.delete(keys[i]);\r\n }\r\n }\r\n\r\n searchString = searchString.replace(/^\\?/, '');\r\n var attributes = searchString.split('&');\r\n var attribute;\r\n for (var i = 0; i < attributes.length; i++) {\r\n attribute = attributes[i].split('=');\r\n this.append(\r\n deserializeParam(attribute[0]),\r\n (attribute.length > 1) ? deserializeParam(attribute[1]) : ''\r\n );\r\n }\r\n }\r\n });\r\n }\r\n\r\n // HTMLAnchorElement\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n\r\n(function(global) {\r\n /**\r\n * Polyfill URL\r\n *\r\n * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js\r\n */\r\n\r\n var checkIfURLIsSupported = function() {\r\n try {\r\n var u = new URL('b', 'http://a');\r\n u.pathname = 'c%20d';\r\n return (u.href === 'http://a/c%20d') && u.searchParams;\r\n } catch (e) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var polyfillURL = function() {\r\n var _URL = global.URL;\r\n\r\n var URL = function(url, base) {\r\n if (typeof url !== 'string') url = String(url);\r\n\r\n // Only create another document if the base is different from current location.\r\n var doc = document, baseElement;\r\n if (base && (global.location === void 0 || base !== global.location.href)) {\r\n doc = document.implementation.createHTMLDocument('');\r\n baseElement = doc.createElement('base');\r\n baseElement.href = base;\r\n doc.head.appendChild(baseElement);\r\n try {\r\n if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);\r\n } catch (err) {\r\n throw new Error('URL unable to set base ' + base + ' due to ' + err);\r\n }\r\n }\r\n\r\n var anchorElement = doc.createElement('a');\r\n anchorElement.href = url;\r\n if (baseElement) {\r\n doc.body.appendChild(anchorElement);\r\n anchorElement.href = anchorElement.href; // force href to refresh\r\n }\r\n\r\n if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {\r\n throw new TypeError('Invalid URL');\r\n }\r\n\r\n Object.defineProperty(this, '_anchorElement', {\r\n value: anchorElement\r\n });\r\n\r\n\r\n // create a linked searchParams which reflect its changes on URL\r\n var searchParams = new URLSearchParams(this.search);\r\n var enableSearchUpdate = true;\r\n var enableSearchParamsUpdate = true;\r\n var _this = this;\r\n ['append', 'delete', 'set'].forEach(function(methodName) {\r\n var method = searchParams[methodName];\r\n searchParams[methodName] = function() {\r\n method.apply(searchParams, arguments);\r\n if (enableSearchUpdate) {\r\n enableSearchParamsUpdate = false;\r\n _this.search = searchParams.toString();\r\n enableSearchParamsUpdate = true;\r\n }\r\n };\r\n });\r\n\r\n Object.defineProperty(this, 'searchParams', {\r\n value: searchParams,\r\n enumerable: true\r\n });\r\n\r\n var search = void 0;\r\n Object.defineProperty(this, '_updateSearchParams', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function() {\r\n if (this.search !== search) {\r\n search = this.search;\r\n if (enableSearchParamsUpdate) {\r\n enableSearchUpdate = false;\r\n this.searchParams._fromString(this.search);\r\n enableSearchUpdate = true;\r\n }\r\n }\r\n }\r\n });\r\n };\r\n\r\n var proto = URL.prototype;\r\n\r\n var linkURLWithAnchorAttribute = function(attributeName) {\r\n Object.defineProperty(proto, attributeName, {\r\n get: function() {\r\n return this._anchorElement[attributeName];\r\n },\r\n set: function(value) {\r\n this._anchorElement[attributeName] = value;\r\n },\r\n enumerable: true\r\n });\r\n };\r\n\r\n ['hash', 'host', 'hostname', 'port', 'protocol']\r\n .forEach(function(attributeName) {\r\n linkURLWithAnchorAttribute(attributeName);\r\n });\r\n\r\n Object.defineProperty(proto, 'search', {\r\n get: function() {\r\n return this._anchorElement['search'];\r\n },\r\n set: function(value) {\r\n this._anchorElement['search'] = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperties(proto, {\r\n\r\n 'toString': {\r\n get: function() {\r\n var _this = this;\r\n return function() {\r\n return _this.href;\r\n };\r\n }\r\n },\r\n\r\n 'href': {\r\n get: function() {\r\n return this._anchorElement.href.replace(/\\?$/, '');\r\n },\r\n set: function(value) {\r\n this._anchorElement.href = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'pathname': {\r\n get: function() {\r\n return this._anchorElement.pathname.replace(/(^\\/?)/, '/');\r\n },\r\n set: function(value) {\r\n this._anchorElement.pathname = value;\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'origin': {\r\n get: function() {\r\n // get expected port from protocol\r\n var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];\r\n // add port to origin if, expected port is different than actual port\r\n // and it is not empty f.e http://foo:8080\r\n // 8080 != 80 && 8080 != ''\r\n var addPortToOrigin = this._anchorElement.port != expectedPort &&\r\n this._anchorElement.port !== '';\r\n\r\n return this._anchorElement.protocol +\r\n '//' +\r\n this._anchorElement.hostname +\r\n (addPortToOrigin ? (':' + this._anchorElement.port) : '');\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'password': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'username': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n });\r\n\r\n URL.createObjectURL = function(blob) {\r\n return _URL.createObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n URL.revokeObjectURL = function(url) {\r\n return _URL.revokeObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n global.URL = URL;\r\n\r\n };\r\n\r\n if (!checkIfURLIsSupported()) {\r\n polyfillURL();\r\n }\r\n\r\n if ((global.location !== void 0) && !('origin' in global.location)) {\r\n var getOrigin = function() {\r\n return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');\r\n };\r\n\r\n try {\r\n Object.defineProperty(global.location, 'origin', {\r\n get: getOrigin,\r\n enumerable: true\r\n });\r\n } catch (e) {\r\n setInterval(function() {\r\n global.location.origin = getOrigin();\r\n }, 100);\r\n }\r\n }\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var core = module.exports = { version: '2.6.3' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar TO_STRING = 'toString';\nvar $toString = Function[TO_STRING];\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","module.exports = {};\n","var core = require('./_core');\nvar global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\n\n(module.exports = function (key, value) {\n return store[key] || (store[key] = value !== undefined ? value : {});\n})('versions', []).push({\n version: core.version,\n mode: require('./_library') ? 'pure' : 'global',\n copyright: '© 2019 Denis Pushkarev (zloirock.ru)'\n});\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","'use strict';\nvar $defineProperty = require('./_object-dp');\nvar createDesc = require('./_property-desc');\n\nmodule.exports = function (object, index, value) {\n if (index in object) $defineProperty.f(object, index, createDesc(0, value));\n else object[index] = value;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","'use strict';\nvar ctx = require('./_ctx');\nvar $export = require('./_export');\nvar toObject = require('./_to-object');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar toLength = require('./_to-length');\nvar createProperty = require('./_create-property');\nvar getIterFn = require('./core.get-iterator-method');\n\n$export($export.S + $export.F * !require('./_iter-detect')(function (iter) { Array.from(iter); }), 'Array', {\n // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)\n from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {\n var O = toObject(arrayLike);\n var C = typeof this == 'function' ? this : Array;\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var index = 0;\n var iterFn = getIterFn(O);\n var length, result, step, iterator;\n if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);\n // if object isn't iterable or it's array with default iterator - use simple case\n if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {\n for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {\n createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);\n }\n } else {\n length = toLength(O.length);\n for (result = new C(length); length > index; index++) {\n createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);\n }\n }\n result.length = index;\n return result;\n }\n});\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","// 22.1.3.31 Array.prototype[@@unscopables]\nvar UNSCOPABLES = require('./_wks')('unscopables');\nvar ArrayProto = Array.prototype;\nif (ArrayProto[UNSCOPABLES] == undefined) require('./_hide')(ArrayProto, UNSCOPABLES, {});\nmodule.exports = function (key) {\n ArrayProto[UNSCOPABLES][key] = true;\n};\n","'use strict';\n// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(5);\nvar KEY = 'find';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n find: function find(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","exports.f = {}.propertyIsEnumerable;\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)\nvar $keys = require('./_object-keys-internal');\nvar hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype');\n\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {\n return $keys(O, hiddenKeys);\n};\n","module.exports = '\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003' +\n '\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';\n","var $export = require('./_export');\nvar defined = require('./_defined');\nvar fails = require('./_fails');\nvar spaces = require('./_string-ws');\nvar space = '[' + spaces + ']';\nvar non = '\\u200b\\u0085';\nvar ltrim = RegExp('^' + space + space + '*');\nvar rtrim = RegExp(space + space + '*$');\n\nvar exporter = function (KEY, exec, ALIAS) {\n var exp = {};\n var FORCE = fails(function () {\n return !!spaces[KEY]() || non[KEY]() != non;\n });\n var fn = exp[KEY] = FORCE ? exec(trim) : spaces[KEY];\n if (ALIAS) exp[ALIAS] = fn;\n $export($export.P + $export.F * FORCE, 'String', exp);\n};\n\n// 1 -> String#trimLeft\n// 2 -> String#trimRight\n// 3 -> String#trim\nvar trim = exporter.trim = function (string, TYPE) {\n string = String(defined(string));\n if (TYPE & 1) string = string.replace(ltrim, '');\n if (TYPE & 2) string = string.replace(rtrim, '');\n return string;\n};\n\nmodule.exports = exporter;\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","'use strict';\nvar global = require('./_global');\nvar has = require('./_has');\nvar cof = require('./_cof');\nvar inheritIfRequired = require('./_inherit-if-required');\nvar toPrimitive = require('./_to-primitive');\nvar fails = require('./_fails');\nvar gOPN = require('./_object-gopn').f;\nvar gOPD = require('./_object-gopd').f;\nvar dP = require('./_object-dp').f;\nvar $trim = require('./_string-trim').trim;\nvar NUMBER = 'Number';\nvar $Number = global[NUMBER];\nvar Base = $Number;\nvar proto = $Number.prototype;\n// Opera ~12 has broken Object#toString\nvar BROKEN_COF = cof(require('./_object-create')(proto)) == NUMBER;\nvar TRIM = 'trim' in String.prototype;\n\n// 7.1.3 ToNumber(argument)\nvar toNumber = function (argument) {\n var it = toPrimitive(argument, false);\n if (typeof it == 'string' && it.length > 2) {\n it = TRIM ? it.trim() : $trim(it, 3);\n var first = it.charCodeAt(0);\n var third, radix, maxCode;\n if (first === 43 || first === 45) {\n third = it.charCodeAt(2);\n if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix\n } else if (first === 48) {\n switch (it.charCodeAt(1)) {\n case 66: case 98: radix = 2; maxCode = 49; break; // fast equal /^0b[01]+$/i\n case 79: case 111: radix = 8; maxCode = 55; break; // fast equal /^0o[0-7]+$/i\n default: return +it;\n }\n for (var digits = it.slice(2), i = 0, l = digits.length, code; i < l; i++) {\n code = digits.charCodeAt(i);\n // parseInt parses a string to a first unavailable symbol\n // but ToNumber should return NaN if a string contains unavailable symbols\n if (code < 48 || code > maxCode) return NaN;\n } return parseInt(digits, radix);\n }\n } return +it;\n};\n\nif (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) {\n $Number = function Number(value) {\n var it = arguments.length < 1 ? 0 : value;\n var that = this;\n return that instanceof $Number\n // check on 1..constructor(foo) case\n && (BROKEN_COF ? fails(function () { proto.valueOf.call(that); }) : cof(that) != NUMBER)\n ? inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it);\n };\n for (var keys = require('./_descriptors') ? gOPN(Base) : (\n // ES3:\n 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +\n // ES6 (in case, if modules with ES6 Number statics required before):\n 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +\n 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger'\n ).split(','), j = 0, key; keys.length > j; j++) {\n if (has(Base, key = keys[j]) && !has($Number, key)) {\n dP($Number, key, gOPD(Base, key));\n }\n }\n $Number.prototype = proto;\n proto.constructor = $Number;\n require('./_redefine')(global, NUMBER, $Number);\n}\n","// most Object methods by ES6 should accept primitives\nvar $export = require('./_export');\nvar core = require('./_core');\nvar fails = require('./_fails');\nmodule.exports = function (KEY, exec) {\n var fn = (core.Object || {})[KEY] || Object[KEY];\n var exp = {};\n exp[KEY] = exec(fn);\n $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp);\n};\n","// 19.1.2.14 Object.keys(O)\nvar toObject = require('./_to-object');\nvar $keys = require('./_object-keys');\n\nrequire('./_object-sap')('keys', function () {\n return function keys(it) {\n return $keys(toObject(it));\n };\n});\n","// 7.2.8 IsRegExp(argument)\nvar isObject = require('./_is-object');\nvar cof = require('./_cof');\nvar MATCH = require('./_wks')('match');\nmodule.exports = function (it) {\n var isRegExp;\n return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');\n};\n","// helper for String#{startsWith, endsWith, includes}\nvar isRegExp = require('./_is-regexp');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, searchString, NAME) {\n if (isRegExp(searchString)) throw TypeError('String#' + NAME + \" doesn't accept regex!\");\n return String(defined(that));\n};\n","var MATCH = require('./_wks')('match');\nmodule.exports = function (KEY) {\n var re = /./;\n try {\n '/./'[KEY](re);\n } catch (e) {\n try {\n re[MATCH] = false;\n return !'/./'[KEY](re);\n } catch (f) { /* empty */ }\n } return true;\n};\n","// 21.1.3.7 String.prototype.includes(searchString, position = 0)\n'use strict';\nvar $export = require('./_export');\nvar context = require('./_string-context');\nvar INCLUDES = 'includes';\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(INCLUDES), 'String', {\n includes: function includes(searchString /* , position = 0 */) {\n return !!~context(this, searchString, INCLUDES)\n .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","'use strict';\n// https://github.com/tc39/Array.prototype.includes\nvar $export = require('./_export');\nvar $includes = require('./_array-includes')(true);\n\n$export($export.P, 'Array', {\n includes: function includes(el /* , fromIndex = 0 */) {\n return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n\nrequire('./_add-to-unscopables')('includes');\n","// 7.2.9 SameValue(x, y)\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare\n return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;\n};\n","'use strict';\n\nvar classof = require('./_classof');\nvar builtinExec = RegExp.prototype.exec;\n\n // `RegExpExec` abstract operation\n// https://tc39.github.io/ecma262/#sec-regexpexec\nmodule.exports = function (R, S) {\n var exec = R.exec;\n if (typeof exec === 'function') {\n var result = exec.call(R, S);\n if (typeof result !== 'object') {\n throw new TypeError('RegExp exec method returned something other than an Object or null');\n }\n return result;\n }\n if (classof(R) !== 'RegExp') {\n throw new TypeError('RegExp#exec called on incompatible receiver');\n }\n return builtinExec.call(R, S);\n};\n","'use strict';\n// 21.2.5.3 get RegExp.prototype.flags\nvar anObject = require('./_an-object');\nmodule.exports = function () {\n var that = anObject(this);\n var result = '';\n if (that.global) result += 'g';\n if (that.ignoreCase) result += 'i';\n if (that.multiline) result += 'm';\n if (that.unicode) result += 'u';\n if (that.sticky) result += 'y';\n return result;\n};\n","'use strict';\n\nvar regexpFlags = require('./_flags');\n\nvar nativeExec = RegExp.prototype.exec;\n// This always refers to the native implementation, because the\n// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,\n// which loads this file before patching the method.\nvar nativeReplace = String.prototype.replace;\n\nvar patchedExec = nativeExec;\n\nvar LAST_INDEX = 'lastIndex';\n\nvar UPDATES_LAST_INDEX_WRONG = (function () {\n var re1 = /a/,\n re2 = /b*/g;\n nativeExec.call(re1, 'a');\n nativeExec.call(re2, 'a');\n return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0;\n})();\n\n// nonparticipating capturing group, copied from es5-shim's String#split patch.\nvar NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;\n\nvar PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED;\n\nif (PATCH) {\n patchedExec = function exec(str) {\n var re = this;\n var lastIndex, reCopy, match, i;\n\n if (NPCG_INCLUDED) {\n reCopy = new RegExp('^' + re.source + '$(?!\\\\s)', regexpFlags.call(re));\n }\n if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX];\n\n match = nativeExec.call(re, str);\n\n if (UPDATES_LAST_INDEX_WRONG && match) {\n re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex;\n }\n if (NPCG_INCLUDED && match && match.length > 1) {\n // Fix browsers whose `exec` methods don't consistently return `undefined`\n // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/\n // eslint-disable-next-line no-loop-func\n nativeReplace.call(match[0], reCopy, function () {\n for (i = 1; i < arguments.length - 2; i++) {\n if (arguments[i] === undefined) match[i] = undefined;\n }\n });\n }\n\n return match;\n };\n}\n\nmodule.exports = patchedExec;\n","'use strict';\nvar regexpExec = require('./_regexp-exec');\nrequire('./_export')({\n target: 'RegExp',\n proto: true,\n forced: regexpExec !== /./.exec\n}, {\n exec: regexpExec\n});\n","'use strict';\nrequire('./es6.regexp.exec');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar fails = require('./_fails');\nvar defined = require('./_defined');\nvar wks = require('./_wks');\nvar regexpExec = require('./_regexp-exec');\n\nvar SPECIES = wks('species');\n\nvar REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {\n // #replace needs built-in support for named groups.\n // #match works fine because it just return the exec results, even if it has\n // a \"grops\" property.\n var re = /./;\n re.exec = function () {\n var result = [];\n result.groups = { a: '7' };\n return result;\n };\n return ''.replace(re, '$<a>') !== '7';\n});\n\nvar SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = (function () {\n // Chrome 51 has a buggy \"split\" implementation when RegExp#exec !== nativeExec\n var re = /(?:)/;\n var originalExec = re.exec;\n re.exec = function () { return originalExec.apply(this, arguments); };\n var result = 'ab'.split(re);\n return result.length === 2 && result[0] === 'a' && result[1] === 'b';\n})();\n\nmodule.exports = function (KEY, length, exec) {\n var SYMBOL = wks(KEY);\n\n var DELEGATES_TO_SYMBOL = !fails(function () {\n // String methods call symbol-named RegEp methods\n var O = {};\n O[SYMBOL] = function () { return 7; };\n return ''[KEY](O) != 7;\n });\n\n var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !fails(function () {\n // Symbol-named RegExp methods call .exec\n var execCalled = false;\n var re = /a/;\n re.exec = function () { execCalled = true; return null; };\n if (KEY === 'split') {\n // RegExp[@@split] doesn't call the regex's exec method, but first creates\n // a new one. We need to return the patched regex when creating the new one.\n re.constructor = {};\n re.constructor[SPECIES] = function () { return re; };\n }\n re[SYMBOL]('');\n return !execCalled;\n }) : undefined;\n\n if (\n !DELEGATES_TO_SYMBOL ||\n !DELEGATES_TO_EXEC ||\n (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) ||\n (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)\n ) {\n var nativeRegExpMethod = /./[SYMBOL];\n var fns = exec(\n defined,\n SYMBOL,\n ''[KEY],\n function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) {\n if (regexp.exec === regexpExec) {\n if (DELEGATES_TO_SYMBOL && !forceStringMethod) {\n // The native String method already delegates to @@method (this\n // polyfilled function), leasing to infinite recursion.\n // We avoid it by directly calling the native @@method method.\n return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };\n }\n return { done: true, value: nativeMethod.call(str, regexp, arg2) };\n }\n return { done: false };\n }\n );\n var strfn = fns[0];\n var rxfn = fns[1];\n\n redefine(String.prototype, KEY, strfn);\n hide(RegExp.prototype, SYMBOL, length == 2\n // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)\n // 21.2.5.11 RegExp.prototype[@@split](string, limit)\n ? function (string, arg) { return rxfn.call(string, this, arg); }\n // 21.2.5.6 RegExp.prototype[@@match](string)\n // 21.2.5.9 RegExp.prototype[@@search](string)\n : function (string) { return rxfn.call(string, this); }\n );\n }\n};\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar sameValue = require('./_same-value');\nvar regExpExec = require('./_regexp-exec-abstract');\n\n// @@search logic\nrequire('./_fix-re-wks')('search', 1, function (defined, SEARCH, $search, maybeCallNative) {\n return [\n // `String.prototype.search` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.search\n function search(regexp) {\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[SEARCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));\n },\n // `RegExp.prototype[@@search]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@search\n function (regexp) {\n var res = maybeCallNative($search, regexp, this);\n if (res.done) return res.value;\n var rx = anObject(regexp);\n var S = String(this);\n var previousLastIndex = rx.lastIndex;\n if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;\n var result = regExpExec(rx, S);\n if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;\n return result === null ? -1 : result.index;\n }\n ];\n});\n","// 21.2.5.3 get RegExp.prototype.flags()\nif (require('./_descriptors') && /./g.flags != 'g') require('./_object-dp').f(RegExp.prototype, 'flags', {\n configurable: true,\n get: require('./_flags')\n});\n","'use strict';\nrequire('./es6.regexp.flags');\nvar anObject = require('./_an-object');\nvar $flags = require('./_flags');\nvar DESCRIPTORS = require('./_descriptors');\nvar TO_STRING = 'toString';\nvar $toString = /./[TO_STRING];\n\nvar define = function (fn) {\n require('./_redefine')(RegExp.prototype, TO_STRING, fn, true);\n};\n\n// 21.2.5.14 RegExp.prototype.toString()\nif (require('./_fails')(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) {\n define(function toString() {\n var R = anObject(this);\n return '/'.concat(R.source, '/',\n 'flags' in R ? R.flags : !DESCRIPTORS && R instanceof RegExp ? $flags.call(R) : undefined);\n });\n// FF44- RegExp#toString has a wrong name\n} else if ($toString.name != TO_STRING) {\n define(function toString() {\n return $toString.call(this);\n });\n}\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = $native || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","'use strict';\nvar addToUnscopables = require('./_add-to-unscopables');\nvar step = require('./_iter-step');\nvar Iterators = require('./_iterators');\nvar toIObject = require('./_to-iobject');\n\n// 22.1.3.4 Array.prototype.entries()\n// 22.1.3.13 Array.prototype.keys()\n// 22.1.3.29 Array.prototype.values()\n// 22.1.3.30 Array.prototype[@@iterator]()\nmodule.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) {\n this._t = toIObject(iterated); // target\n this._i = 0; // next index\n this._k = kind; // kind\n// 22.1.5.2.1 %ArrayIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var kind = this._k;\n var index = this._i++;\n if (!O || index >= O.length) {\n this._t = undefined;\n return step(1);\n }\n if (kind == 'keys') return step(0, index);\n if (kind == 'values') return step(0, O[index]);\n return step(0, [index, O[index]]);\n}, 'values');\n\n// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)\nIterators.Arguments = Iterators.Array;\n\naddToUnscopables('keys');\naddToUnscopables('values');\naddToUnscopables('entries');\n","var $iterators = require('./es6.array.iterator');\nvar getKeys = require('./_object-keys');\nvar redefine = require('./_redefine');\nvar global = require('./_global');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar wks = require('./_wks');\nvar ITERATOR = wks('iterator');\nvar TO_STRING_TAG = wks('toStringTag');\nvar ArrayValues = Iterators.Array;\n\nvar DOMIterables = {\n CSSRuleList: true, // TODO: Not spec compliant, should be false.\n CSSStyleDeclaration: false,\n CSSValueList: false,\n ClientRectList: false,\n DOMRectList: false,\n DOMStringList: false,\n DOMTokenList: true,\n DataTransferItemList: false,\n FileList: false,\n HTMLAllCollection: false,\n HTMLCollection: false,\n HTMLFormElement: false,\n HTMLSelectElement: false,\n MediaList: true, // TODO: Not spec compliant, should be false.\n MimeTypeArray: false,\n NamedNodeMap: false,\n NodeList: true,\n PaintRequestList: false,\n Plugin: false,\n PluginArray: false,\n SVGLengthList: false,\n SVGNumberList: false,\n SVGPathSegList: false,\n SVGPointList: false,\n SVGStringList: false,\n SVGTransformList: false,\n SourceBufferList: false,\n StyleSheetList: true, // TODO: Not spec compliant, should be false.\n TextTrackCueList: false,\n TextTrackList: false,\n TouchList: false\n};\n\nfor (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {\n var NAME = collections[i];\n var explicit = DOMIterables[NAME];\n var Collection = global[NAME];\n var proto = Collection && Collection.prototype;\n var key;\n if (proto) {\n if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);\n if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);\n Iterators[NAME] = ArrayValues;\n if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true);\n }\n}\n","var toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n// true -> String#at\n// false -> String#codePointAt\nmodule.exports = function (TO_STRING) {\n return function (that, pos) {\n var s = String(defined(that));\n var i = toInteger(pos);\n var l = s.length;\n var a, b;\n if (i < 0 || i >= l) return TO_STRING ? '' : undefined;\n a = s.charCodeAt(i);\n return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff\n ? TO_STRING ? s.charAt(i) : a\n : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;\n };\n};\n","'use strict';\nvar $at = require('./_string-at')(true);\n\n// 21.1.3.27 String.prototype[@@iterator]()\nrequire('./_iter-define')(String, 'String', function (iterated) {\n this._t = String(iterated); // target\n this._i = 0; // next index\n// 21.1.5.2.1 %StringIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var index = this._i;\n var point;\n if (index >= O.length) return { value: undefined, done: true };\n point = $at(O, index);\n this._i += point.length;\n return { value: point, done: false };\n});\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","exports.f = Object.getOwnPropertySymbols;\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];\n } return T;\n} : $assign;\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar validate = require('./_validate-collection');\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar tmp = {};\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","'use strict';\nvar fails = require('./_fails');\n\nmodule.exports = function (method, arg) {\n return !!method && fails(function () {\n // eslint-disable-next-line no-useless-call\n arg ? method.call(null, function () { /* empty */ }, 1) : method.call(null);\n });\n};\n","'use strict';\nvar $export = require('./_export');\nvar aFunction = require('./_a-function');\nvar toObject = require('./_to-object');\nvar fails = require('./_fails');\nvar $sort = [].sort;\nvar test = [1, 2, 3];\n\n$export($export.P + $export.F * (fails(function () {\n // IE8-\n test.sort(undefined);\n}) || !fails(function () {\n // V8 bug\n test.sort(null);\n // Old WebKit\n}) || !require('./_strict-method')($sort)), 'Array', {\n // 22.1.3.25 Array.prototype.sort(comparefn)\n sort: function sort(comparefn) {\n return comparefn === undefined\n ? $sort.call(toObject(this))\n : $sort.call(toObject(this), aFunction(comparefn));\n }\n});\n","// 19.1.3.1 Object.assign(target, source)\nvar $export = require('./_export');\n\n$export($export.S + $export.F, 'Object', { assign: require('./_object-assign') });\n","// 7.3.20 SpeciesConstructor(O, defaultConstructor)\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar SPECIES = require('./_wks')('species');\nmodule.exports = function (O, D) {\n var C = anObject(O).constructor;\n var S;\n return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);\n};\n","'use strict';\nvar at = require('./_string-at')(true);\n\n // `AdvanceStringIndex` abstract operation\n// https://tc39.github.io/ecma262/#sec-advancestringindex\nmodule.exports = function (S, index, unicode) {\n return index + (unicode ? at(S, index).length : 1);\n};\n","'use strict';\n\nvar isRegExp = require('./_is-regexp');\nvar anObject = require('./_an-object');\nvar speciesConstructor = require('./_species-constructor');\nvar advanceStringIndex = require('./_advance-string-index');\nvar toLength = require('./_to-length');\nvar callRegExpExec = require('./_regexp-exec-abstract');\nvar regexpExec = require('./_regexp-exec');\nvar fails = require('./_fails');\nvar $min = Math.min;\nvar $push = [].push;\nvar $SPLIT = 'split';\nvar LENGTH = 'length';\nvar LAST_INDEX = 'lastIndex';\nvar MAX_UINT32 = 0xffffffff;\n\n// babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError\nvar SUPPORTS_Y = !fails(function () { RegExp(MAX_UINT32, 'y'); });\n\n// @@split logic\nrequire('./_fix-re-wks')('split', 2, function (defined, SPLIT, $split, maybeCallNative) {\n var internalSplit;\n if (\n 'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||\n 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||\n 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||\n '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||\n '.'[$SPLIT](/()()/)[LENGTH] > 1 ||\n ''[$SPLIT](/.?/)[LENGTH]\n ) {\n // based on es5-shim implementation, need to rework it\n internalSplit = function (separator, limit) {\n var string = String(this);\n if (separator === undefined && limit === 0) return [];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) return $split.call(string, separator, limit);\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n var splitLimit = limit === undefined ? MAX_UINT32 : limit >>> 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var match, lastIndex, lastLength;\n while (match = regexpExec.call(separatorCopy, string)) {\n lastIndex = separatorCopy[LAST_INDEX];\n if (lastIndex > lastLastIndex) {\n output.push(string.slice(lastLastIndex, match.index));\n if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));\n lastLength = match[0][LENGTH];\n lastLastIndex = lastIndex;\n if (output[LENGTH] >= splitLimit) break;\n }\n if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop\n }\n if (lastLastIndex === string[LENGTH]) {\n if (lastLength || !separatorCopy.test('')) output.push('');\n } else output.push(string.slice(lastLastIndex));\n return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;\n };\n // Chakra, V8\n } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {\n internalSplit = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit);\n };\n } else {\n internalSplit = $split;\n }\n\n return [\n // `String.prototype.split` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.split\n function split(separator, limit) {\n var O = defined(this);\n var splitter = separator == undefined ? undefined : separator[SPLIT];\n return splitter !== undefined\n ? splitter.call(separator, O, limit)\n : internalSplit.call(String(O), separator, limit);\n },\n // `RegExp.prototype[@@split]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split\n //\n // NOTE: This cannot be properly polyfilled in engines that don't support\n // the 'y' flag.\n function (regexp, limit) {\n var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split);\n if (res.done) return res.value;\n\n var rx = anObject(regexp);\n var S = String(this);\n var C = speciesConstructor(rx, RegExp);\n\n var unicodeMatching = rx.unicode;\n var flags = (rx.ignoreCase ? 'i' : '') +\n (rx.multiline ? 'm' : '') +\n (rx.unicode ? 'u' : '') +\n (SUPPORTS_Y ? 'y' : 'g');\n\n // ^(? + rx + ) is needed, in combination with some S slicing, to\n // simulate the 'y' flag.\n var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];\n var p = 0;\n var q = 0;\n var A = [];\n while (q < S.length) {\n splitter.lastIndex = SUPPORTS_Y ? q : 0;\n var z = callRegExpExec(splitter, SUPPORTS_Y ? S : S.slice(q));\n var e;\n if (\n z === null ||\n (e = $min(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p\n ) {\n q = advanceStringIndex(S, q, unicodeMatching);\n } else {\n A.push(S.slice(p, q));\n if (A.length === lim) return A;\n for (var i = 1; i <= z.length - 1; i++) {\n A.push(z[i]);\n if (A.length === lim) return A;\n }\n q = p = e;\n }\n }\n A.push(S.slice(p));\n return A;\n }\n ];\n});\n","var getKeys = require('./_object-keys');\nvar toIObject = require('./_to-iobject');\nvar isEnum = require('./_object-pie').f;\nmodule.exports = function (isEntries) {\n return function (it) {\n var O = toIObject(it);\n var keys = getKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) if (isEnum.call(O, key = keys[i++])) {\n result.push(isEntries ? [key, O[key]] : O[key]);\n } return result;\n };\n};\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $entries = require('./_object-to-array')(true);\n\n$export($export.S, 'Object', {\n entries: function entries(it) {\n return $entries(it);\n }\n});\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $values = require('./_object-to-array')(false);\n\n$export($export.S, 'Object', {\n values: function values(it) {\n return $values(it);\n }\n});\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar toInteger = require('./_to-integer');\nvar advanceStringIndex = require('./_advance-string-index');\nvar regExpExec = require('./_regexp-exec-abstract');\nvar max = Math.max;\nvar min = Math.min;\nvar floor = Math.floor;\nvar SUBSTITUTION_SYMBOLS = /\\$([$&`']|\\d\\d?|<[^>]*>)/g;\nvar SUBSTITUTION_SYMBOLS_NO_NAMED = /\\$([$&`']|\\d\\d?)/g;\n\nvar maybeToString = function (it) {\n return it === undefined ? it : String(it);\n};\n\n// @@replace logic\nrequire('./_fix-re-wks')('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) {\n return [\n // `String.prototype.replace` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.replace\n function replace(searchValue, replaceValue) {\n var O = defined(this);\n var fn = searchValue == undefined ? undefined : searchValue[REPLACE];\n return fn !== undefined\n ? fn.call(searchValue, O, replaceValue)\n : $replace.call(String(O), searchValue, replaceValue);\n },\n // `RegExp.prototype[@@replace]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace\n function (regexp, replaceValue) {\n var res = maybeCallNative($replace, regexp, this, replaceValue);\n if (res.done) return res.value;\n\n var rx = anObject(regexp);\n var S = String(this);\n var functionalReplace = typeof replaceValue === 'function';\n if (!functionalReplace) replaceValue = String(replaceValue);\n var global = rx.global;\n if (global) {\n var fullUnicode = rx.unicode;\n rx.lastIndex = 0;\n }\n var results = [];\n while (true) {\n var result = regExpExec(rx, S);\n if (result === null) break;\n results.push(result);\n if (!global) break;\n var matchStr = String(result[0]);\n if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);\n }\n var accumulatedResult = '';\n var nextSourcePosition = 0;\n for (var i = 0; i < results.length; i++) {\n result = results[i];\n var matched = String(result[0]);\n var position = max(min(toInteger(result.index), S.length), 0);\n var captures = [];\n // NOTE: This is equivalent to\n // captures = result.slice(1).map(maybeToString)\n // but for some reason `nativeSlice.call(result, 1, result.length)` (called in\n // the slice polyfill when slicing native arrays) \"doesn't work\" in safari 9 and\n // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.\n for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));\n var namedCaptures = result.groups;\n if (functionalReplace) {\n var replacerArgs = [matched].concat(captures, position, S);\n if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);\n var replacement = String(replaceValue.apply(undefined, replacerArgs));\n } else {\n replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);\n }\n if (position >= nextSourcePosition) {\n accumulatedResult += S.slice(nextSourcePosition, position) + replacement;\n nextSourcePosition = position + matched.length;\n }\n }\n return accumulatedResult + S.slice(nextSourcePosition);\n }\n ];\n\n // https://tc39.github.io/ecma262/#sec-getsubstitution\n function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {\n var tailPos = position + matched.length;\n var m = captures.length;\n var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;\n if (namedCaptures !== undefined) {\n namedCaptures = toObject(namedCaptures);\n symbols = SUBSTITUTION_SYMBOLS;\n }\n return $replace.call(replacement, symbols, function (match, ch) {\n var capture;\n switch (ch.charAt(0)) {\n case '$': return '$';\n case '&': return matched;\n case '`': return str.slice(0, position);\n case \"'\": return str.slice(tailPos);\n case '<':\n capture = namedCaptures[ch.slice(1, -1)];\n break;\n default: // \\d\\d?\n var n = +ch;\n if (n === 0) return match;\n if (n > m) {\n var f = floor(n / 10);\n if (f === 0) return match;\n if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);\n return match;\n }\n capture = captures[n - 1];\n }\n return capture === undefined ? '' : capture;\n });\n }\n});\n","// fast apply, http://jsperf.lnkit.com/fast-apply/5\nmodule.exports = function (fn, args, that) {\n var un = that === undefined;\n switch (args.length) {\n case 0: return un ? fn()\n : fn.call(that);\n case 1: return un ? fn(args[0])\n : fn.call(that, args[0]);\n case 2: return un ? fn(args[0], args[1])\n : fn.call(that, args[0], args[1]);\n case 3: return un ? fn(args[0], args[1], args[2])\n : fn.call(that, args[0], args[1], args[2]);\n case 4: return un ? fn(args[0], args[1], args[2], args[3])\n : fn.call(that, args[0], args[1], args[2], args[3]);\n } return fn.apply(that, args);\n};\n","var ctx = require('./_ctx');\nvar invoke = require('./_invoke');\nvar html = require('./_html');\nvar cel = require('./_dom-create');\nvar global = require('./_global');\nvar process = global.process;\nvar setTask = global.setImmediate;\nvar clearTask = global.clearImmediate;\nvar MessageChannel = global.MessageChannel;\nvar Dispatch = global.Dispatch;\nvar counter = 0;\nvar queue = {};\nvar ONREADYSTATECHANGE = 'onreadystatechange';\nvar defer, channel, port;\nvar run = function () {\n var id = +this;\n // eslint-disable-next-line no-prototype-builtins\n if (queue.hasOwnProperty(id)) {\n var fn = queue[id];\n delete queue[id];\n fn();\n }\n};\nvar listener = function (event) {\n run.call(event.data);\n};\n// Node.js 0.9+ & IE10+ has setImmediate, otherwise:\nif (!setTask || !clearTask) {\n setTask = function setImmediate(fn) {\n var args = [];\n var i = 1;\n while (arguments.length > i) args.push(arguments[i++]);\n queue[++counter] = function () {\n // eslint-disable-next-line no-new-func\n invoke(typeof fn == 'function' ? fn : Function(fn), args);\n };\n defer(counter);\n return counter;\n };\n clearTask = function clearImmediate(id) {\n delete queue[id];\n };\n // Node.js 0.8-\n if (require('./_cof')(process) == 'process') {\n defer = function (id) {\n process.nextTick(ctx(run, id, 1));\n };\n // Sphere (JS game engine) Dispatch API\n } else if (Dispatch && Dispatch.now) {\n defer = function (id) {\n Dispatch.now(ctx(run, id, 1));\n };\n // Browsers with MessageChannel, includes WebWorkers\n } else if (MessageChannel) {\n channel = new MessageChannel();\n port = channel.port2;\n channel.port1.onmessage = listener;\n defer = ctx(port.postMessage, port, 1);\n // Browsers with postMessage, skip WebWorkers\n // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'\n } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {\n defer = function (id) {\n global.postMessage(id + '', '*');\n };\n global.addEventListener('message', listener, false);\n // IE8-\n } else if (ONREADYSTATECHANGE in cel('script')) {\n defer = function (id) {\n html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {\n html.removeChild(this);\n run.call(id);\n };\n };\n // Rest old browsers\n } else {\n defer = function (id) {\n setTimeout(ctx(run, id, 1), 0);\n };\n }\n}\nmodule.exports = {\n set: setTask,\n clear: clearTask\n};\n","var global = require('./_global');\nvar macrotask = require('./_task').set;\nvar Observer = global.MutationObserver || global.WebKitMutationObserver;\nvar process = global.process;\nvar Promise = global.Promise;\nvar isNode = require('./_cof')(process) == 'process';\n\nmodule.exports = function () {\n var head, last, notify;\n\n var flush = function () {\n var parent, fn;\n if (isNode && (parent = process.domain)) parent.exit();\n while (head) {\n fn = head.fn;\n head = head.next;\n try {\n fn();\n } catch (e) {\n if (head) notify();\n else last = undefined;\n throw e;\n }\n } last = undefined;\n if (parent) parent.enter();\n };\n\n // Node.js\n if (isNode) {\n notify = function () {\n process.nextTick(flush);\n };\n // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339\n } else if (Observer && !(global.navigator && global.navigator.standalone)) {\n var toggle = true;\n var node = document.createTextNode('');\n new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new\n notify = function () {\n node.data = toggle = !toggle;\n };\n // environments with maybe non-completely correct, but existent Promise\n } else if (Promise && Promise.resolve) {\n // Promise.resolve without an argument throws an error in LG WebOS 2\n var promise = Promise.resolve(undefined);\n notify = function () {\n promise.then(flush);\n };\n // for other environments - macrotask based on:\n // - setImmediate\n // - MessageChannel\n // - window.postMessag\n // - onreadystatechange\n // - setTimeout\n } else {\n notify = function () {\n // strange IE + webpack dev server bug - use .call(global)\n macrotask.call(global, flush);\n };\n }\n\n return function (fn) {\n var task = { fn: fn, next: undefined };\n if (last) last.next = task;\n if (!head) {\n head = task;\n notify();\n } last = task;\n };\n};\n","'use strict';\n// 25.4.1.5 NewPromiseCapability(C)\nvar aFunction = require('./_a-function');\n\nfunction PromiseCapability(C) {\n var resolve, reject;\n this.promise = new C(function ($$resolve, $$reject) {\n if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');\n resolve = $$resolve;\n reject = $$reject;\n });\n this.resolve = aFunction(resolve);\n this.reject = aFunction(reject);\n}\n\nmodule.exports.f = function (C) {\n return new PromiseCapability(C);\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar global = require('./_global');\nvar ctx = require('./_ctx');\nvar classof = require('./_classof');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar aFunction = require('./_a-function');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar speciesConstructor = require('./_species-constructor');\nvar task = require('./_task').set;\nvar microtask = require('./_microtask')();\nvar newPromiseCapabilityModule = require('./_new-promise-capability');\nvar perform = require('./_perform');\nvar userAgent = require('./_user-agent');\nvar promiseResolve = require('./_promise-resolve');\nvar PROMISE = 'Promise';\nvar TypeError = global.TypeError;\nvar process = global.process;\nvar versions = process && process.versions;\nvar v8 = versions && versions.v8 || '';\nvar $Promise = global[PROMISE];\nvar isNode = classof(process) == 'process';\nvar empty = function () { /* empty */ };\nvar Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;\nvar newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;\n\nvar USE_NATIVE = !!function () {\n try {\n // correct subclassing with @@species support\n var promise = $Promise.resolve(1);\n var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) {\n exec(empty, empty);\n };\n // unhandled rejections tracking support, NodeJS Promise without it fails @@species test\n return (isNode || typeof PromiseRejectionEvent == 'function')\n && promise.then(empty) instanceof FakePromise\n // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables\n // https://bugs.chromium.org/p/chromium/issues/detail?id=830565\n // we can't detect it synchronously, so just check versions\n && v8.indexOf('6.6') !== 0\n && userAgent.indexOf('Chrome/66') === -1;\n } catch (e) { /* empty */ }\n}();\n\n// helpers\nvar isThenable = function (it) {\n var then;\n return isObject(it) && typeof (then = it.then) == 'function' ? then : false;\n};\nvar notify = function (promise, isReject) {\n if (promise._n) return;\n promise._n = true;\n var chain = promise._c;\n microtask(function () {\n var value = promise._v;\n var ok = promise._s == 1;\n var i = 0;\n var run = function (reaction) {\n var handler = ok ? reaction.ok : reaction.fail;\n var resolve = reaction.resolve;\n var reject = reaction.reject;\n var domain = reaction.domain;\n var result, then, exited;\n try {\n if (handler) {\n if (!ok) {\n if (promise._h == 2) onHandleUnhandled(promise);\n promise._h = 1;\n }\n if (handler === true) result = value;\n else {\n if (domain) domain.enter();\n result = handler(value); // may throw\n if (domain) {\n domain.exit();\n exited = true;\n }\n }\n if (result === reaction.promise) {\n reject(TypeError('Promise-chain cycle'));\n } else if (then = isThenable(result)) {\n then.call(result, resolve, reject);\n } else resolve(result);\n } else reject(value);\n } catch (e) {\n if (domain && !exited) domain.exit();\n reject(e);\n }\n };\n while (chain.length > i) run(chain[i++]); // variable length - can't use forEach\n promise._c = [];\n promise._n = false;\n if (isReject && !promise._h) onUnhandled(promise);\n });\n};\nvar onUnhandled = function (promise) {\n task.call(global, function () {\n var value = promise._v;\n var unhandled = isUnhandled(promise);\n var result, handler, console;\n if (unhandled) {\n result = perform(function () {\n if (isNode) {\n process.emit('unhandledRejection', value, promise);\n } else if (handler = global.onunhandledrejection) {\n handler({ promise: promise, reason: value });\n } else if ((console = global.console) && console.error) {\n console.error('Unhandled promise rejection', value);\n }\n });\n // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should\n promise._h = isNode || isUnhandled(promise) ? 2 : 1;\n } promise._a = undefined;\n if (unhandled && result.e) throw result.v;\n });\n};\nvar isUnhandled = function (promise) {\n return promise._h !== 1 && (promise._a || promise._c).length === 0;\n};\nvar onHandleUnhandled = function (promise) {\n task.call(global, function () {\n var handler;\n if (isNode) {\n process.emit('rejectionHandled', promise);\n } else if (handler = global.onrejectionhandled) {\n handler({ promise: promise, reason: promise._v });\n }\n });\n};\nvar $reject = function (value) {\n var promise = this;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n promise._v = value;\n promise._s = 2;\n if (!promise._a) promise._a = promise._c.slice();\n notify(promise, true);\n};\nvar $resolve = function (value) {\n var promise = this;\n var then;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n try {\n if (promise === value) throw TypeError(\"Promise can't be resolved itself\");\n if (then = isThenable(value)) {\n microtask(function () {\n var wrapper = { _w: promise, _d: false }; // wrap\n try {\n then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));\n } catch (e) {\n $reject.call(wrapper, e);\n }\n });\n } else {\n promise._v = value;\n promise._s = 1;\n notify(promise, false);\n }\n } catch (e) {\n $reject.call({ _w: promise, _d: false }, e); // wrap\n }\n};\n\n// constructor polyfill\nif (!USE_NATIVE) {\n // 25.4.3.1 Promise(executor)\n $Promise = function Promise(executor) {\n anInstance(this, $Promise, PROMISE, '_h');\n aFunction(executor);\n Internal.call(this);\n try {\n executor(ctx($resolve, this, 1), ctx($reject, this, 1));\n } catch (err) {\n $reject.call(this, err);\n }\n };\n // eslint-disable-next-line no-unused-vars\n Internal = function Promise(executor) {\n this._c = []; // <- awaiting reactions\n this._a = undefined; // <- checked in isUnhandled reactions\n this._s = 0; // <- state\n this._d = false; // <- done\n this._v = undefined; // <- value\n this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled\n this._n = false; // <- notify\n };\n Internal.prototype = require('./_redefine-all')($Promise.prototype, {\n // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)\n then: function then(onFulfilled, onRejected) {\n var reaction = newPromiseCapability(speciesConstructor(this, $Promise));\n reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;\n reaction.fail = typeof onRejected == 'function' && onRejected;\n reaction.domain = isNode ? process.domain : undefined;\n this._c.push(reaction);\n if (this._a) this._a.push(reaction);\n if (this._s) notify(this, false);\n return reaction.promise;\n },\n // 25.4.5.1 Promise.prototype.catch(onRejected)\n 'catch': function (onRejected) {\n return this.then(undefined, onRejected);\n }\n });\n OwnPromiseCapability = function () {\n var promise = new Internal();\n this.promise = promise;\n this.resolve = ctx($resolve, promise, 1);\n this.reject = ctx($reject, promise, 1);\n };\n newPromiseCapabilityModule.f = newPromiseCapability = function (C) {\n return C === $Promise || C === Wrapper\n ? new OwnPromiseCapability(C)\n : newGenericPromiseCapability(C);\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });\nrequire('./_set-to-string-tag')($Promise, PROMISE);\nrequire('./_set-species')(PROMISE);\nWrapper = require('./_core')[PROMISE];\n\n// statics\n$export($export.S + $export.F * !USE_NATIVE, PROMISE, {\n // 25.4.4.5 Promise.reject(r)\n reject: function reject(r) {\n var capability = newPromiseCapability(this);\n var $$reject = capability.reject;\n $$reject(r);\n return capability.promise;\n }\n});\n$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {\n // 25.4.4.6 Promise.resolve(x)\n resolve: function resolve(x) {\n return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);\n }\n});\n$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) {\n $Promise.all(iter)['catch'](empty);\n})), PROMISE, {\n // 25.4.4.1 Promise.all(iterable)\n all: function all(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var resolve = capability.resolve;\n var reject = capability.reject;\n var result = perform(function () {\n var values = [];\n var index = 0;\n var remaining = 1;\n forOf(iterable, false, function (promise) {\n var $index = index++;\n var alreadyCalled = false;\n values.push(undefined);\n remaining++;\n C.resolve(promise).then(function (value) {\n if (alreadyCalled) return;\n alreadyCalled = true;\n values[$index] = value;\n --remaining || resolve(values);\n }, reject);\n });\n --remaining || resolve(values);\n });\n if (result.e) reject(result.v);\n return capability.promise;\n },\n // 25.4.4.4 Promise.race(iterable)\n race: function race(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var reject = capability.reject;\n var result = perform(function () {\n forOf(iterable, false, function (promise) {\n C.resolve(promise).then(capability.resolve, reject);\n });\n });\n if (result.e) reject(result.v);\n return capability.promise;\n }\n});\n","module.exports = function (exec) {\n try {\n return { e: false, v: exec() };\n } catch (e) {\n return { e: true, v: e };\n }\n};\n","var global = require('./_global');\nvar navigator = global.navigator;\n\nmodule.exports = navigator && navigator.userAgent || '';\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","var anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar newPromiseCapability = require('./_new-promise-capability');\n\nmodule.exports = function (C, x) {\n anObject(C);\n if (isObject(x) && x.constructor === C) return x;\n var promiseCapability = newPromiseCapability.f(C);\n var resolve = promiseCapability.resolve;\n resolve(x);\n return promiseCapability.promise;\n};\n","// 21.1.3.18 String.prototype.startsWith(searchString [, position ])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar STARTS_WITH = 'startsWith';\nvar $startsWith = ''[STARTS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(STARTS_WITH), 'String', {\n startsWith: function startsWith(searchString /* , position = 0 */) {\n var that = context(this, searchString, STARTS_WITH);\n var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));\n var search = String(searchString);\n return $startsWith\n ? $startsWith.call(that, search, index)\n : that.slice(index, index + search.length) === search;\n }\n});\n","// 20.1.2.4 Number.isNaN(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', {\n isNaN: function isNaN(number) {\n // eslint-disable-next-line no-self-compare\n return number != number;\n }\n});\n","// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isWeakMap = input => instanceOf(input, WeakMap);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isTextNode = input => getConstructor(input) === Text;\nconst isEvent = input => instanceOf(input, Event);\nconst isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\nconst isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\n\nconst isEmpty = input =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (e) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: this,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise(resolve =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport { toggleListener } from './events';\nimport is from './is';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) {\n return;\n }\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) {\n return;\n }\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) {\n return;\n }\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) {\n return;\n }\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.object(existing) && is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Trap focus inside container\nexport function trapFocus(element = null, toggle = false) {\n if (!is.element(element)) {\n return;\n }\n\n const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = document.activeElement;\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n if (!is.element(element)) {\n return;\n }\n\n // Set regular focus\n element.focus({ preventScroll: true });\n\n // If we want to mimic keyboard focus via tab\n if (tabFocus) {\n toggleClass(element, this.config.classNames.tabFocus);\n }\n}\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport { toggleHidden } from './elements';\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element) {\n setTimeout(() => {\n try {\n toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n toggleHidden(element, false);\n } catch (e) {\n // Do nothing\n }\n }, 0);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isEdge: window.navigator.userAgent.includes('Edge'),\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (e) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map(source => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(source => source.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n // Get first match for requested size\n const source = sources.find(source => Number(source.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n player.play();\n }\n });\n\n // Load new source\n player.media.load();\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","var global = require('./_global');\nvar inheritIfRequired = require('./_inherit-if-required');\nvar dP = require('./_object-dp').f;\nvar gOPN = require('./_object-gopn').f;\nvar isRegExp = require('./_is-regexp');\nvar $flags = require('./_flags');\nvar $RegExp = global.RegExp;\nvar Base = $RegExp;\nvar proto = $RegExp.prototype;\nvar re1 = /a/g;\nvar re2 = /a/g;\n// \"new\" creates a new object, old webkit buggy here\nvar CORRECT_NEW = new $RegExp(re1) !== re1;\n\nif (require('./_descriptors') && (!CORRECT_NEW || require('./_fails')(function () {\n re2[require('./_wks')('match')] = false;\n // RegExp constructor can alter flags and IsRegExp works correct with @@match\n return $RegExp(re1) != re1 || $RegExp(re2) == re2 || $RegExp(re1, 'i') != '/a/i';\n}))) {\n $RegExp = function RegExp(p, f) {\n var tiRE = this instanceof $RegExp;\n var piRE = isRegExp(p);\n var fiU = f === undefined;\n return !tiRE && piRE && p.constructor === $RegExp && fiU ? p\n : inheritIfRequired(CORRECT_NEW\n ? new Base(piRE && !fiU ? p.source : p, f)\n : Base((piRE = p instanceof $RegExp) ? p.source : p, piRE && fiU ? $flags.call(p) : f)\n , tiRE ? this : proto, $RegExp);\n };\n var proxy = function (key) {\n key in $RegExp || dP($RegExp, key, {\n configurable: true,\n get: function () { return Base[key]; },\n set: function (it) { Base[key] = it; }\n });\n };\n for (var keys = gOPN(Base), i = 0; keys.length > i;) proxy(keys[i++]);\n proto.constructor = $RegExp;\n $RegExp.prototype = proto;\n require('./_redefine')(global, 'RegExp', $RegExp);\n}\n\nrequire('./_set-species')('RegExp');\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport function replaceAll(input = '', find = '', replace = '') {\n return input.replace(\n new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'),\n replace.toString(),\n );\n}\n\n// Convert to title case\nexport function toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n}\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([key, value]) => {\n string = replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(result => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// 20.2.2.34 Math.trunc(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n trunc: function trunc(it) {\n return (it > 0 ? Math.floor : Math.ceil)(it);\n }\n});\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = value => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = value => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`,\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n\n const attributes = Object.assign({}, attr, {\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),\n });\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = Object.assign({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-label': i18n.get(type, this.config),\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on(\n menuItem,\n 'keydown keyup',\n event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![32, 38, 39, 40].includes(event.which)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [32, 39].includes(event.which)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.which !== 32) {\n if (event.which === 40 || (isRadioButton && event.which === 39)) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on(menuItem, 'keyup', event => {\n if (event.which !== 13) {\n return;\n }\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behaviour\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(checked) {\n // Ensure exclusivity\n if (checked) {\n Array.from(menuItem.parentNode.children)\n .filter(node => matches(node, '[role=\"menuitemradio\"]'))\n .forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n event => {\n if (is.keyboardEvent(event) && event.which !== 32) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const value = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Set the speed options\n if (is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, tabFocus = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, tabFocus);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.which === 27) {\n show = false;\n } else if (is.event(input)) {\n const isMenuItem = popup.contains(input.target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', tabFocus = false) {\n const target = document.getElementById(`plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, tabFocus);\n },\n\n // Set the download link\n setDownloadLink() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set download link\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Volume controls\n if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {\n const volume = createElement('div', {\n class: 'plyr__volume',\n });\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n volume.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n controls.createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n\n this.elements.volume = volume;\n }\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n const control = createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n control.appendChild(\n controls.createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on(menuItem, 'click', () => {\n controls.showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on(\n pane,\n 'keydown',\n event => {\n // We only care about <-\n if (event.which !== 37) {\n return;\n }\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n controls.showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on(backButton, 'click', () => {\n controls.showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n control.appendChild(popup);\n container.appendChild(control);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = control;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Download button\n if (this.config.controls.includes('download')) {\n const attributes = {\n element: 'a',\n href: this.download,\n target: '_blank',\n };\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(controls.createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n // Set available quality levels\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n } else if (is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n Object.defineProperty(button, 'pressed', {\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button)\n .filter(Boolean)\n .forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {string} input - the URL to be parsed\n * @param {boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (e) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n track.mode = 'hidden';\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n\n // Update available languages in list\n if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter(track => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(track => track.language === language);\n return !track; // Break iteration if there is a match\n });\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || [])\n .map(cue => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api:\n 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n },\n\n // YouTube plugin\n youtube: {\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { hasClass, toggleClass, trapFocus } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Trigger an event\n triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n\n if (!hasProperty) {\n viewport.content += `,${property}`;\n }\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter(part => part.trim() !== property)\n .join(',');\n }\n\n // Force a repaint as sometimes Safari doesn't want to fill the screen\n setTimeout(() => repaint(this.target), 100);\n }\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n onChange.call(this);\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get usingNative() {\n return Fullscreen.native && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n let mode;\n\n if (this.forceFallback) {\n mode = 'Fallback (forced)';\n } else if (Fullscreen.native) {\n mode = 'Native';\n } else {\n mode = 'Fallback';\n }\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitEnterFullscreen();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// 20.2.2.28 Math.sign(x)\nmodule.exports = Math.sign || function sign(x) {\n // eslint-disable-next-line no-self-compare\n return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;\n};\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// 20.2.2.28 Math.sign(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { sign: require('./_math-sign') });\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/loadImage';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('poster', poster);\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch(err => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw err;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n ui.togglePoster.call(this, true);\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n target.pressed = this.playing;\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls } = this.elements;\n\n if (controls && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now());\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport is from './is';\n\n/* function reduceAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n} */\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n let ratio = input;\n\n if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) {\n ({ ratio } = this.embed);\n }\n\n if (!is.string(ratio)) {\n ({ ratio } = this.config);\n }\n\n const [x, y] = ratio.split(':').map(Number);\n const padding = (100 / x) * y;\n\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n\n return { padding, ratio };\n}\n\nexport default { setAspectRatio };\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { setAspectRatio } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.setTabFocus = this.setTabFocus.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keycodes should we prevent default\n const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n player.forward();\n break;\n\n case 37:\n // Arrow back\n player.rewind();\n break;\n\n case 70:\n // F key\n player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n player.loop = !player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n }\n\n setTabFocus(event) {\n const { player } = this;\n const { elements } = player;\n\n clearTimeout(this.focusTimer);\n\n // Ignore any key other than tab\n if (event.type === 'keydown' && event.which !== 9) {\n return;\n }\n\n // Store reference to event timeStamp\n if (event.type === 'keydown') {\n this.lastKeyDown = event.timeStamp;\n }\n\n // Remove current classes\n const removeCurrent = () => {\n const className = player.config.classNames.tabFocus;\n const current = getElements.call(player, `.${className}`);\n toggleClass(current, className, false);\n };\n\n // Determine if a key was pressed to trigger this event\n const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n // Ignore focus events if a key was pressed prior\n if (event.type === 'focus' && !wasKeyDown) {\n return;\n }\n\n // Remove all current\n removeCurrent();\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n this.focusTimer = setTimeout(() => {\n const focused = document.activeElement;\n\n // Ignore if current focus element isn't inside the player\n if (!elements.container.contains(focused)) {\n return;\n }\n\n toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n }, 10);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n\n // Tab focus detection\n toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);\n }\n\n // Container listeners\n container() {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n event => {\n const { controls } = elements;\n\n // Remove button states for fullscreen\n if (controls && event.type === 'enterfullscreen') {\n controls.pressed = false;\n controls.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Force edge to repaint on exit fullscreen\n // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen\n /* if (browser.isEdge) {\n on.call(player, elements.container, 'exitfullscreen', () => {\n setTimeout(() => repaint(elements.container), 100);\n });\n } */\n\n // Set a gutter for Vimeo\n const setGutter = (ratio, padding, toggle) => {\n if (!player.isVimeo) {\n return;\n }\n\n const target = player.elements.wrapper.firstChild;\n const [, height] = ratio.split(':').map(Number);\n const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number);\n\n target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null;\n target.style.margin = toggle ? '0 auto' : null;\n };\n\n // Resize on fullscreen change\n const setPlayerSize = measure => {\n // If we don't need to measure the viewport\n if (!measure) {\n return setAspectRatio.call(player);\n }\n\n const rect = elements.container.getBoundingClientRect();\n const { width, height } = rect;\n\n return setAspectRatio.call(player, `${width}:${height}`);\n };\n\n const resized = () => {\n window.clearTimeout(timers.resized);\n timers.resized = window.setTimeout(setPlayerSize, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const { target, usingNative } = player.fullscreen;\n\n // Ignore for iOS native\n if (!player.isEmbed || target !== elements.container) {\n return;\n }\n\n const isEnter = event.type === 'enterfullscreen';\n\n // Set the player size when entering fullscreen to viewport size\n const { padding, ratio } = setPlayerSize(isEnter);\n\n // Set Vimeo gutter\n setGutter(ratio, padding, isEnter);\n\n // If not using native fullscreen, we need to check for resizes of viewport\n if (!usingNative) {\n if (isEnter) {\n on.call(player, window, 'resize', resized);\n } else {\n off.call(player, window, 'resize', resized);\n }\n }\n });\n }\n\n // Listen for media events\n media() {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event =>\n controls.durationUpdate.call(player, event),\n );\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n on.call(player, player.media, 'canplay loadeddata', () => {\n toggleHidden(elements.volume, !player.hasAudio);\n toggleHidden(elements.buttons.mute, !player.hasAudio);\n });\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n on.call(player, player.media, 'playing', () => {\n if (!player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (player.ads.enabled && !player.ads.initialized) {\n // Wait for manager response\n player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play());\n }\n });\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, player.play, 'play');\n } else {\n this.proxy(event, player.togglePlay, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadLink.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, event => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n }\n\n // Run default and custom handlers\n proxy(event, defaultHandler, customHandlerKey) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n }\n\n // Trigger custom and default handlers\n bind(element, type, defaultHandler, customHandlerKey, passive = true) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n event => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n }\n\n // Listen for control events\n controls() {\n const { player } = this;\n const { elements } = player;\n\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', player.togglePlay, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward');\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n\n controls.toggleMenu.call(player, event);\n });\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n event => {\n const code = event.which;\n\n // We only care about space and return\n if (![13, 32].includes(code)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (code === 13) {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.which === 27) {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const code = event.keyCode ? event.keyCode : event.which;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n player.play();\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n event => {\n const seek = event.currentTarget;\n\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n event => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, elements, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));\n\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n}\n\nexport default Listeners;\n","var dP = require('./_object-dp').f;\nvar FProto = Function.prototype;\nvar nameRE = /^\\s*function ([^ (]*)/;\nvar NAME = 'name';\n\n// 19.2.4.2 name\nNAME in FProto || require('./_descriptors') && dP(FProto, NAME, {\n configurable: true,\n get: function () {\n try {\n return ('' + this).match(nameRE)[1];\n } catch (e) {\n return '';\n }\n }\n});\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar advanceStringIndex = require('./_advance-string-index');\nvar regExpExec = require('./_regexp-exec-abstract');\n\n// @@match logic\nrequire('./_fix-re-wks')('match', 1, function (defined, MATCH, $match, maybeCallNative) {\n return [\n // `String.prototype.match` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.match\n function match(regexp) {\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[MATCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));\n },\n // `RegExp.prototype[@@match]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match\n function (regexp) {\n var res = maybeCallNative($match, regexp, this);\n if (res.done) return res.value;\n var rx = anObject(regexp);\n var S = String(this);\n if (!rx.global) return regExpExec(rx, S);\n var fullUnicode = rx.unicode;\n rx.lastIndex = 0;\n var A = [];\n var n = 0;\n var result;\n while ((result = regExpExec(rx, S)) !== null) {\n var matchStr = String(result[0]);\n A[n] = matchStr;\n if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);\n n++;\n }\n return n === 0 ? null : A;\n }\n ];\n});\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, stripHTML } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n setAspectRatio.call(this);\n\n // Load the API if not already\n if (!is.object(window.Vimeo)) {\n loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams(\n extend(\n {},\n {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n },\n config,\n ),\n );\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = parseId(source);\n\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Get poster, if already set\n const { poster } = player;\n\n // Inject the package\n const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n\n // Get poster image\n fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set and show poster\n ui.setPoster.call(player, url.href).catch(() => {});\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n controls.setDownloadLink.call(player);\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = `${width}:${height}`;\n setAspectRatio.call(this, player.embed.ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/loadImage';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n setAspectRatio.call(this);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (is.string(key) && !is.empty(key)) {\n const url = format(this.config.urls.youtube.api, videoId, key);\n\n fetch(url)\n .then(result => {\n if (is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n\n // Get poster, if already set\n const { poster } = player;\n\n // Replace media element\n const container = createElement('div', { id, poster });\n player.media = replaceElement(container, player.media);\n\n // Id to poster wrapper\n const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src))\n .then(posterSrc => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!posterSrc.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n\n const config = player.config.youtube;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined,\n playerVars: extend(\n {},\n {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n hl: player.config.hl, // iframe interface language\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occured';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.extend.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n event => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n triggerEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","'use strict';\n// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(6);\nvar KEY = 'findIndex';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n findIndex: function findIndex(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1]) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6]) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load() {\n // Togglethe regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) {\n return;\n }\n\n this.getThumbnails().then(() => {\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n this.loaded = true;\n });\n }\n\n // Download VTT files and parse them\n getThumbnails() {\n return new Promise(resolve => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n\n Promise.all(promises).then(() => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n });\n });\n }\n\n // Process individual VTT file\n getThumbnail(url) {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n if (!thumbnail.frames[0].text.startsWith('/')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n }\n\n startMove(event) {\n if (!this.loaded) {\n return;\n }\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n return;\n }\n\n // Wait until media has a duration\n if (!this.player.media.duration) {\n return;\n }\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n\n endMove() {\n this.toggleThumbContainer(false, true);\n }\n\n startScrubbing(event) {\n // Only act on left mouse button (0), or touch device (event.button is false)\n if (event.button === false || event.button === 0) {\n this.mouseDown = true;\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n }\n\n finishScrubbing() {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n }\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners() {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n }\n\n /**\n * Create HTML elements for image containers\n */\n render() {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.container.appendChild(timeContainer);\n\n // Inject the whole thumb\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n }\n\n showImageAtCurrentTime() {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.toggleThumbContainer(true);\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n this.toggleThumbContainer(hasThumb);\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumbnum or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n }\n\n // Show the image that's currently specified in this.showingThumb\n loadImage(qualityIndex = 0) {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () =>\n this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n }\n\n showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n }\n\n // Remove all preview images that aren't the designated current image\n removeOldImages(currentImage) {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n image.dataset.deleting = true;\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n }\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby(thumbNum, forward = true) {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename))\n this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n }\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n }\n\n get currentImageContainer() {\n if (this.mouseDown) {\n return this.elements.scrubbing.container;\n }\n\n return this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n if (this.mouseDown) {\n return this.currentScrubbingImageElement;\n }\n\n return this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer(toggle = false, clearShowing = false) {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n toggleScrubbingContainer(toggle = false) {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n determineContainerAutoSizing() {\n if (this.elements.thumb.imageContainer.clientHeight > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n }\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos() {\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n }\n\n this.setThumbContainerPos();\n }\n\n setThumbContainerPos() {\n const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n const plyrRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const minVal = plyrRect.left - seekbarRect.left + 10;\n const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n if (previewPos < minVal) {\n previewPos = minVal;\n }\n\n if (previewPos > maxVal) {\n previewPos = maxVal;\n }\n\n container.style.left = `${previewPos}px`;\n }\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize() {\n this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`;\n // Can't use media.clientHeight - html5 video goes big and does black bars above and below\n this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`;\n }\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset(previewImage, frame) {\n if (!this.usingSprites) {\n return;\n }\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;\n previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;\n previewImage.style.left = `-${frame.x * multiplier}px`;\n previewImage.style.top = `-${frame.y * multiplier}px`;\n }\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Reload thumbnails\n if (this.previewThumbnails) {\n this.previewThumbnails.load();\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.4.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/previewThumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { cloneDeep, extend } from './utils/objects';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div', { tabindex: 0 });\n wrap(this.media, this.elements.container);\n }\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n this.increaseVolume(-step);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {number} - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} [toggle] - Whether to show the controls\n */\n toggleControls(toggle) {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n on.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Add event listeners once\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n once(event, callback) {\n once.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.polyfilled.min.mjs b/dist/plyr.polyfilled.min.mjs new file mode 100644 index 00000000..64587e3e --- /dev/null +++ b/dist/plyr.polyfilled.min.mjs @@ -0,0 +1 @@ +"object"==typeof navigator&&function(){if("undefined"!=typeof window)try{var e=new window.CustomEvent("test",{cancelable:!0});if(e.preventDefault(),!0!==e.defaultPrevented)throw new Error("Could not prevent default")}catch(e){var t=function(e,t){var n,i;return t=t||{bubbles:!1,cancelable:!1,detail:void 0},(n=document.createEvent("CustomEvent")).initCustomEvent(e,t.bubbles,t.cancelable,t.detail),i=n.preventDefault,n.preventDefault=function(){i.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(e){this.defaultPrevented=!0}},n};t.prototype=window.Event.prototype,window.CustomEvent=t}}();var commonjsGlobal="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function createCommonjsModule(e,t){return e(t={exports:{}},t.exports),t.exports}!function(e){var t=function(){try{return!!Symbol.iterator}catch(e){return!1}}(),n=function(e){var n={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return t&&(n[Symbol.iterator]=function(){return n}),n},i=function(e){return encodeURIComponent(e).replace(/%20/g,"+")},r=function(e){return decodeURIComponent(e).replace(/\+/g," ")};"URLSearchParams"in e&&"a=1"===new URLSearchParams("?a=1").toString()||function(){var r=function(e){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var t=typeof e;if("undefined"===t);else if("string"===t)""!==e&&this._fromString(e);else if(e instanceof r){var n=this;e.forEach(function(e,t){n.append(t,e)})}else{if(null===e||"object"!==t)throw new TypeError("Unsupported input's type for URLSearchParams");if("[object Array]"===Object.prototype.toString.call(e))for(var i=0;i<e.length;i++){var o=e[i];if("[object Array]"!==Object.prototype.toString.call(o)&&2===o.length)throw new TypeError("Expected [string, any] as entry at index "+i+" of URLSearchParams's input");this.append(o[0],o[1])}else for(var s in e)e.hasOwnProperty(s)&&this.append(s,e[s])}},o=r.prototype;o.append=function(e,t){e in this._entries?this._entries[e].push(String(t)):this._entries[e]=[String(t)]},o.delete=function(e){delete this._entries[e]},o.get=function(e){return e in this._entries?this._entries[e][0]:null},o.getAll=function(e){return e in this._entries?this._entries[e].slice(0):[]},o.has=function(e){return e in this._entries},o.set=function(e,t){this._entries[e]=[String(t)]},o.forEach=function(e,t){var n;for(var i in this._entries)if(this._entries.hasOwnProperty(i)){n=this._entries[i];for(var r=0;r<n.length;r++)e.call(t,n[r],i,this)}},o.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),n(e)},o.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),n(e)},o.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),n(e)},t&&(o[Symbol.iterator]=o.entries),o.toString=function(){var e=[];return this.forEach(function(t,n){e.push(i(n)+"="+i(t))}),e.join("&")},e.URLSearchParams=r}();var o=URLSearchParams.prototype;"function"!=typeof o.sort&&(o.sort=function(){var e=this,t=[];this.forEach(function(n,i){t.push([i,n]),e._entries||e.delete(i)}),t.sort(function(e,t){return e[0]<t[0]?-1:e[0]>t[0]?1:0}),e._entries&&(e._entries={});for(var n=0;n<t.length;n++)this.append(t[n][0],t[n][1])}),"function"!=typeof o._fromString&&Object.defineProperty(o,"_fromString",{enumerable:!1,configurable:!1,writable:!1,value:function(e){if(this._entries)this._entries={};else{var t=[];this.forEach(function(e,n){t.push(n)});for(var n=0;n<t.length;n++)this.delete(t[n])}var i,o=(e=e.replace(/^\?/,"")).split("&");for(n=0;n<o.length;n++)i=o[n].split("="),this.append(r(i[0]),i.length>1?r(i[1]):"")}})}(void 0!==commonjsGlobal?commonjsGlobal:"undefined"!=typeof window?window:"undefined"!=typeof self?self:commonjsGlobal),function(e){if(function(){try{var e=new URL("b","http://a");return e.pathname="c%20d","http://a/c%20d"===e.href&&e.searchParams}catch(e){return!1}}()||function(){var t=e.URL,n=function(t,n){"string"!=typeof t&&(t=String(t));var i,r=document;if(n&&(void 0===e.location||n!==e.location.href)){(i=(r=document.implementation.createHTMLDocument("")).createElement("base")).href=n,r.head.appendChild(i);try{if(0!==i.href.indexOf(n))throw new Error(i.href)}catch(e){throw new Error("URL unable to set base "+n+" due to "+e)}}var o=r.createElement("a");if(o.href=t,i&&(r.body.appendChild(o),o.href=o.href),":"===o.protocol||!/:/.test(o.href))throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:o});var s=new URLSearchParams(this.search),a=!0,l=!0,c=this;["append","delete","set"].forEach(function(e){var t=s[e];s[e]=function(){t.apply(s,arguments),a&&(l=!1,c.search=s.toString(),l=!0)}}),Object.defineProperty(this,"searchParams",{value:s,enumerable:!0});var u=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==u&&(u=this.search,l&&(a=!1,this.searchParams._fromString(this.search),a=!0))}})},i=n.prototype;["hash","host","hostname","port","protocol"].forEach(function(e){!function(e){Object.defineProperty(i,e,{get:function(){return this._anchorElement[e]},set:function(t){this._anchorElement[e]=t},enumerable:!0})}(e)}),Object.defineProperty(i,"search",{get:function(){return this._anchorElement.search},set:function(e){this._anchorElement.search=e,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(i,{toString:{get:function(){var e=this;return function(){return e.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(e){this._anchorElement.href=e,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(e){this._anchorElement.pathname=e},enumerable:!0},origin:{get:function(){var e={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],t=this._anchorElement.port!=e&&""!==this._anchorElement.port;return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(t?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(e){},enumerable:!0},username:{get:function(){return""},set:function(e){},enumerable:!0}}),n.createObjectURL=function(e){return t.createObjectURL.apply(t,arguments)},n.revokeObjectURL=function(e){return t.revokeObjectURL.apply(t,arguments)},e.URL=n}(),void 0!==e.location&&!("origin"in e.location)){var t=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:t,enumerable:!0})}catch(n){setInterval(function(){e.location.origin=t()},100)}}}(void 0!==commonjsGlobal?commonjsGlobal:"undefined"!=typeof window?window:"undefined"!=typeof self?self:commonjsGlobal);var _aFunction=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e},_ctx=function(e,t,n){if(_aFunction(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,i){return e.call(t,n,i)};case 3:return function(n,i,r){return e.call(t,n,i,r)}}return function(){return e.apply(t,arguments)}},_global=createCommonjsModule(function(e){var t=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)}),_core=createCommonjsModule(function(e){var t=e.exports={version:"2.6.3"};"number"==typeof __e&&(__e=t)}),_core_1=_core.version,_isObject=function(e){return"object"==typeof e?null!==e:"function"==typeof e},_anObject=function(e){if(!_isObject(e))throw TypeError(e+" is not an object!");return e},_fails=function(e){try{return!!e()}catch(e){return!0}},_descriptors=!_fails(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}),document$1=_global.document,is=_isObject(document$1)&&_isObject(document$1.createElement),_domCreate=function(e){return is?document$1.createElement(e):{}},_ie8DomDefine=!_descriptors&&!_fails(function(){return 7!=Object.defineProperty(_domCreate("div"),"a",{get:function(){return 7}}).a}),_toPrimitive=function(e,t){if(!_isObject(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!_isObject(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!_isObject(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!_isObject(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")},dP=Object.defineProperty,f=_descriptors?Object.defineProperty:function(e,t,n){if(_anObject(e),t=_toPrimitive(t,!0),_anObject(n),_ie8DomDefine)try{return dP(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e},_objectDp={f:f},_propertyDesc=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}},_hide=_descriptors?function(e,t,n){return _objectDp.f(e,t,_propertyDesc(1,n))}:function(e,t,n){return e[t]=n,e},hasOwnProperty={}.hasOwnProperty,_has=function(e,t){return hasOwnProperty.call(e,t)},id=0,px=Math.random(),_uid=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++id+px).toString(36))},_redefine=createCommonjsModule(function(e){var t=_uid("src"),n=Function.toString,i=(""+n).split("toString");_core.inspectSource=function(e){return n.call(e)},(e.exports=function(e,n,r,o){var s="function"==typeof r;s&&(_has(r,"name")||_hide(r,"name",n)),e[n]!==r&&(s&&(_has(r,t)||_hide(r,t,e[n]?""+e[n]:i.join(String(n)))),e===_global?e[n]=r:o?e[n]?e[n]=r:_hide(e,n,r):(delete e[n],_hide(e,n,r)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[t]||n.call(this)})}),PROTOTYPE="prototype",$export=function(e,t,n){var i,r,o,s,a=e&$export.F,l=e&$export.G,c=e&$export.S,u=e&$export.P,d=e&$export.B,h=l?_global:c?_global[t]||(_global[t]={}):(_global[t]||{})[PROTOTYPE],p=l?_core:_core[t]||(_core[t]={}),f=p[PROTOTYPE]||(p[PROTOTYPE]={});for(i in l&&(n=t),n)o=((r=!a&&h&&void 0!==h[i])?h:n)[i],s=d&&r?_ctx(o,_global):u&&"function"==typeof o?_ctx(Function.call,o):o,h&&_redefine(h,i,o,e&$export.U),p[i]!=o&&_hide(p,i,s),u&&f[i]!=o&&(f[i]=o)};_global.core=_core,$export.F=1,$export.G=2,$export.S=4,$export.P=8,$export.B=16,$export.W=32,$export.U=64,$export.R=128;var _export=$export,_defined=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e},_toObject=function(e){return Object(_defined(e))},_iterCall=function(e,t,n,i){try{return i?t(_anObject(n)[0],n[1]):t(n)}catch(t){var r=e.return;throw void 0!==r&&_anObject(r.call(e)),t}},_iterators={},_library=!1,_shared=createCommonjsModule(function(e){var t=_global["__core-js_shared__"]||(_global["__core-js_shared__"]={});(e.exports=function(e,n){return t[e]||(t[e]=void 0!==n?n:{})})("versions",[]).push({version:_core.version,mode:"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})}),_wks=createCommonjsModule(function(e){var t=_shared("wks"),n=_global.Symbol,i="function"==typeof n;(e.exports=function(e){return t[e]||(t[e]=i&&n[e]||(i?n:_uid)("Symbol."+e))}).store=t}),ITERATOR=_wks("iterator"),ArrayProto=Array.prototype,_isArrayIter=function(e){return void 0!==e&&(_iterators.Array===e||ArrayProto[ITERATOR]===e)},ceil=Math.ceil,floor=Math.floor,_toInteger=function(e){return isNaN(e=+e)?0:(e>0?floor:ceil)(e)},min=Math.min,_toLength=function(e){return e>0?min(_toInteger(e),9007199254740991):0},_createProperty=function(e,t,n){t in e?_objectDp.f(e,t,_propertyDesc(0,n)):e[t]=n},toString={}.toString,_cof=function(e){return toString.call(e).slice(8,-1)},TAG=_wks("toStringTag"),ARG="Arguments"==_cof(function(){return arguments}()),tryGet=function(e,t){try{return e[t]}catch(e){}},_classof=function(e){var t,n,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=tryGet(t=Object(e),TAG))?n:ARG?_cof(t):"Object"==(i=_cof(t))&&"function"==typeof t.callee?"Arguments":i},ITERATOR$1=_wks("iterator"),core_getIteratorMethod=_core.getIteratorMethod=function(e){if(null!=e)return e[ITERATOR$1]||e["@@iterator"]||_iterators[_classof(e)]},ITERATOR$2=_wks("iterator"),SAFE_CLOSING=!1;try{var riter=[7][ITERATOR$2]();riter.return=function(){SAFE_CLOSING=!0}}catch(e){}var _iterDetect=function(e,t){if(!t&&!SAFE_CLOSING)return!1;var n=!1;try{var i=[7],r=i[ITERATOR$2]();r.next=function(){return{done:n=!0}},i[ITERATOR$2]=function(){return r},e(i)}catch(e){}return n};_export(_export.S+_export.F*!_iterDetect(function(e){}),"Array",{from:function(e){var t,n,i,r,o=_toObject(e),s="function"==typeof this?this:Array,a=arguments.length,l=a>1?arguments[1]:void 0,c=void 0!==l,u=0,d=core_getIteratorMethod(o);if(c&&(l=_ctx(l,a>2?arguments[2]:void 0,2)),null==d||s==Array&&_isArrayIter(d))for(n=new s(t=_toLength(o.length));t>u;u++)_createProperty(n,u,c?l(o[u],u):o[u]);else for(r=d.call(o),n=new s;!(i=r.next()).done;u++)_createProperty(n,u,c?_iterCall(r,l,[i.value,u],!0):i.value);return n.length=u,n}});var _iobject=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==_cof(e)?e.split(""):Object(e)},_isArray=Array.isArray||function(e){return"Array"==_cof(e)},SPECIES=_wks("species"),_arraySpeciesConstructor=function(e){var t;return _isArray(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!_isArray(t.prototype)||(t=void 0),_isObject(t)&&null===(t=t[SPECIES])&&(t=void 0)),void 0===t?Array:t},_arraySpeciesCreate=function(e,t){return new(_arraySpeciesConstructor(e))(t)},_arrayMethods=function(e,t){var n=1==e,i=2==e,r=3==e,o=4==e,s=6==e,a=5==e||s,l=t||_arraySpeciesCreate;return function(t,c,u){for(var d,h,p=_toObject(t),f=_iobject(p),m=_ctx(c,u,3),g=_toLength(f.length),y=0,v=n?l(t,g):i?l(t,0):void 0;g>y;y++)if((a||y in f)&&(h=m(d=f[y],y,p),e))if(n)v[y]=h;else if(h)switch(e){case 3:return!0;case 5:return d;case 6:return y;case 2:v.push(d)}else if(o)return!1;return s?-1:r||o?o:v}},UNSCOPABLES=_wks("unscopables"),ArrayProto$1=Array.prototype;null==ArrayProto$1[UNSCOPABLES]&&_hide(ArrayProto$1,UNSCOPABLES,{});var _addToUnscopables=function(e){ArrayProto$1[UNSCOPABLES][e]=!0},$find=_arrayMethods(5),KEY="find",forced=!0;KEY in[]&&Array(1)[KEY](function(){forced=!1}),_export(_export.P+_export.F*forced,"Array",{find:function(e){return $find(this,e,arguments.length>1?arguments[1]:void 0)}}),_addToUnscopables(KEY);var f$1={}.propertyIsEnumerable,_objectPie={f:f$1},_toIobject=function(e){return _iobject(_defined(e))},gOPD=Object.getOwnPropertyDescriptor,f$2=_descriptors?gOPD:function(e,t){if(e=_toIobject(e),t=_toPrimitive(t,!0),_ie8DomDefine)try{return gOPD(e,t)}catch(e){}if(_has(e,t))return _propertyDesc(!_objectPie.f.call(e,t),e[t])},_objectGopd={f:f$2},check=function(e,t){if(_anObject(e),!_isObject(t)&&null!==t)throw TypeError(t+": can't set as prototype!")},_setProto={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,n){try{(n=_ctx(Function.call,_objectGopd.f(Object.prototype,"__proto__").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,i){return check(e,i),t?e.__proto__=i:n(e,i),e}}({},!1):void 0),check:check},setPrototypeOf=_setProto.set,_inheritIfRequired=function(e,t,n){var i,r=t.constructor;return r!==n&&"function"==typeof r&&(i=r.prototype)!==n.prototype&&_isObject(i)&&setPrototypeOf&&setPrototypeOf(e,i),e},max=Math.max,min$1=Math.min,_toAbsoluteIndex=function(e,t){return(e=_toInteger(e))<0?max(e+t,0):min$1(e,t)},_arrayIncludes=function(e){return function(t,n,i){var r,o=_toIobject(t),s=_toLength(o.length),a=_toAbsoluteIndex(i,s);if(e&&n!=n){for(;s>a;)if((r=o[a++])!=r)return!0}else for(;s>a;a++)if((e||a in o)&&o[a]===n)return e||a||0;return!e&&-1}},shared=_shared("keys"),_sharedKey=function(e){return shared[e]||(shared[e]=_uid(e))},arrayIndexOf=_arrayIncludes(!1),IE_PROTO=_sharedKey("IE_PROTO"),_objectKeysInternal=function(e,t){var n,i=_toIobject(e),r=0,o=[];for(n in i)n!=IE_PROTO&&_has(i,n)&&o.push(n);for(;t.length>r;)_has(i,n=t[r++])&&(~arrayIndexOf(o,n)||o.push(n));return o},_enumBugKeys="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),hiddenKeys=_enumBugKeys.concat("length","prototype"),f$3=Object.getOwnPropertyNames||function(e){return _objectKeysInternal(e,hiddenKeys)},_objectGopn={f:f$3},_stringWs="\t\n\v\f\r \u2028\u2029\ufeff",space="["+_stringWs+"]",non="
",ltrim=RegExp("^"+space+space+"*"),rtrim=RegExp(space+space+"*$"),exporter=function(e,t,n){var i={},r=_fails(function(){return!!_stringWs[e]()||non[e]()!=non}),o=i[e]=r?t(trim):_stringWs[e];n&&(i[n]=o),_export(_export.P+_export.F*r,"String",i)},trim=exporter.trim=function(e,t){return e=String(_defined(e)),1&t&&(e=e.replace(ltrim,"")),2&t&&(e=e.replace(rtrim,"")),e},_stringTrim=exporter,_objectKeys=Object.keys||function(e){return _objectKeysInternal(e,_enumBugKeys)},_objectDps=_descriptors?Object.defineProperties:function(e,t){_anObject(e);for(var n,i=_objectKeys(t),r=i.length,o=0;r>o;)_objectDp.f(e,n=i[o++],t[n]);return e},document$2=_global.document,_html=document$2&&document$2.documentElement,IE_PROTO$1=_sharedKey("IE_PROTO"),Empty=function(){},PROTOTYPE$1="prototype",createDict=function(){var e,t=_domCreate("iframe"),n=_enumBugKeys.length;for(t.style.display="none",_html.appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),createDict=e.F;n--;)delete createDict[PROTOTYPE$1][_enumBugKeys[n]];return createDict()},_objectCreate=Object.create||function(e,t){var n;return null!==e?(Empty[PROTOTYPE$1]=_anObject(e),n=new Empty,Empty[PROTOTYPE$1]=null,n[IE_PROTO$1]=e):n=createDict(),void 0===t?n:_objectDps(n,t)},gOPN=_objectGopn.f,gOPD$1=_objectGopd.f,dP$1=_objectDp.f,$trim=_stringTrim.trim,NUMBER="Number",$Number=_global[NUMBER],Base=$Number,proto=$Number.prototype,BROKEN_COF=_cof(_objectCreate(proto))==NUMBER,TRIM="trim"in String.prototype,toNumber=function(e){var t=_toPrimitive(e,!1);if("string"==typeof t&&t.length>2){var n,i,r,o=(t=TRIM?t.trim():$trim(t,3)).charCodeAt(0);if(43===o||45===o){if(88===(n=t.charCodeAt(2))||120===n)return NaN}else if(48===o){switch(t.charCodeAt(1)){case 66:case 98:i=2,r=49;break;case 79:case 111:i=8,r=55;break;default:return+t}for(var s,a=t.slice(2),l=0,c=a.length;l<c;l++)if((s=a.charCodeAt(l))<48||s>r)return NaN;return parseInt(a,i)}}return+t};if(!$Number(" 0o1")||!$Number("0b1")||$Number("+0x1")){$Number=function(e){var t=arguments.length<1?0:e,n=this;return n instanceof $Number&&(BROKEN_COF?_fails(function(){proto.valueOf.call(n)}):_cof(n)!=NUMBER)?_inheritIfRequired(new Base(toNumber(t)),n,$Number):toNumber(t)};for(var key,keys=_descriptors?gOPN(Base):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),j=0;keys.length>j;j++)_has(Base,key=keys[j])&&!_has($Number,key)&&dP$1($Number,key,gOPD$1(Base,key));$Number.prototype=proto,proto.constructor=$Number,_redefine(_global,NUMBER,$Number)}var _objectSap=function(e,t){var n=(_core.Object||{})[e]||Object[e],i={};i[e]=t(n),_export(_export.S+_export.F*_fails(function(){n(1)}),"Object",i)};_objectSap("keys",function(){return function(e){return _objectKeys(_toObject(e))}});var MATCH=_wks("match"),_isRegexp=function(e){var t;return _isObject(e)&&(void 0!==(t=e[MATCH])?!!t:"RegExp"==_cof(e))},_stringContext=function(e,t,n){if(_isRegexp(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(_defined(e))},MATCH$1=_wks("match"),_failsIsRegexp=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[MATCH$1]=!1,!"/./"[e](t)}catch(e){}}return!0},INCLUDES="includes";_export(_export.P+_export.F*_failsIsRegexp(INCLUDES),"String",{includes:function(e){return!!~_stringContext(this,e,INCLUDES).indexOf(e,arguments.length>1?arguments[1]:void 0)}});var $includes=_arrayIncludes(!0);_export(_export.P,"Array",{includes:function(e){return $includes(this,e,arguments.length>1?arguments[1]:void 0)}}),_addToUnscopables("includes");var _sameValue=Object.is||function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t},builtinExec=RegExp.prototype.exec,_regexpExecAbstract=function(e,t){var n=e.exec;if("function"==typeof n){var i=n.call(e,t);if("object"!=typeof i)throw new TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==_classof(e))throw new TypeError("RegExp#exec called on incompatible receiver");return builtinExec.call(e,t)},_flags=function(){var e=_anObject(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t},nativeExec=RegExp.prototype.exec,nativeReplace=String.prototype.replace,patchedExec=nativeExec,LAST_INDEX="lastIndex",UPDATES_LAST_INDEX_WRONG=function(){var e=/a/,t=/b*/g;return nativeExec.call(e,"a"),nativeExec.call(t,"a"),0!==e[LAST_INDEX]||0!==t[LAST_INDEX]}(),NPCG_INCLUDED=void 0!==/()??/.exec("")[1],PATCH=UPDATES_LAST_INDEX_WRONG||NPCG_INCLUDED;PATCH&&(patchedExec=function(e){var t,n,i,r,o=this;return NPCG_INCLUDED&&(n=new RegExp("^"+o.source+"$(?!\\s)",_flags.call(o))),UPDATES_LAST_INDEX_WRONG&&(t=o[LAST_INDEX]),i=nativeExec.call(o,e),UPDATES_LAST_INDEX_WRONG&&i&&(o[LAST_INDEX]=o.global?i.index+i[0].length:t),NPCG_INCLUDED&&i&&i.length>1&&nativeReplace.call(i[0],n,function(){for(r=1;r<arguments.length-2;r++)void 0===arguments[r]&&(i[r]=void 0)}),i});var _regexpExec=patchedExec;_export({target:"RegExp",proto:!0,forced:_regexpExec!==/./.exec},{exec:_regexpExec});var SPECIES$1=_wks("species"),REPLACE_SUPPORTS_NAMED_GROUPS=!_fails(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$<a>")}),SPLIT_WORKS_WITH_OVERWRITTEN_EXEC=function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2===n.length&&"a"===n[0]&&"b"===n[1]}(),_fixReWks=function(e,t,n){var i=_wks(e),r=!_fails(function(){var t={};return t[i]=function(){return 7},7!=""[e](t)}),o=r?!_fails(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===e&&(n.constructor={},n.constructor[SPECIES$1]=function(){return n}),n[i](""),!t}):void 0;if(!r||!o||"replace"===e&&!REPLACE_SUPPORTS_NAMED_GROUPS||"split"===e&&!SPLIT_WORKS_WITH_OVERWRITTEN_EXEC){var s=/./[i],a=n(_defined,i,""[e],function(e,t,n,i,o){return t.exec===_regexpExec?r&&!o?{done:!0,value:s.call(t,n,i)}:{done:!0,value:e.call(n,t,i)}:{done:!1}}),l=a[0],c=a[1];_redefine(String.prototype,e,l),_hide(RegExp.prototype,i,2==t?function(e,t){return c.call(e,this,t)}:function(e){return c.call(e,this)})}};_fixReWks("search",1,function(e,t,n,i){return[function(n){var i=e(this),r=null==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},function(e){var t=i(n,e,this);if(t.done)return t.value;var r=_anObject(e),o=String(this),s=r.lastIndex;_sameValue(s,0)||(r.lastIndex=0);var a=_regexpExecAbstract(r,o);return _sameValue(r.lastIndex,s)||(r.lastIndex=s),null===a?-1:a.index}]}),_descriptors&&"g"!=/./g.flags&&_objectDp.f(RegExp.prototype,"flags",{configurable:!0,get:_flags});var TO_STRING="toString",$toString=/./[TO_STRING],define=function(e){_redefine(RegExp.prototype,TO_STRING,e,!0)};_fails(function(){return"/a/b"!=$toString.call({source:"a",flags:"b"})})?define(function(){var e=_anObject(this);return"/".concat(e.source,"/","flags"in e?e.flags:!_descriptors&&e instanceof RegExp?_flags.call(e):void 0)}):$toString.name!=TO_STRING&&define(function(){return $toString.call(this)});var _iterStep=function(e,t){return{value:t,done:!!e}},def=_objectDp.f,TAG$1=_wks("toStringTag"),_setToStringTag=function(e,t,n){e&&!_has(e=n?e:e.prototype,TAG$1)&&def(e,TAG$1,{configurable:!0,value:t})},IteratorPrototype={};_hide(IteratorPrototype,_wks("iterator"),function(){return this});var _iterCreate=function(e,t,n){e.prototype=_objectCreate(IteratorPrototype,{next:_propertyDesc(1,n)}),_setToStringTag(e,t+" Iterator")},IE_PROTO$2=_sharedKey("IE_PROTO"),ObjectProto=Object.prototype,_objectGpo=Object.getPrototypeOf||function(e){return e=_toObject(e),_has(e,IE_PROTO$2)?e[IE_PROTO$2]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?ObjectProto:null},ITERATOR$3=_wks("iterator"),BUGGY=!([].keys&&"next"in[].keys()),FF_ITERATOR="@@iterator",KEYS="keys",VALUES="values",returnThis=function(){return this},_iterDefine=function(e,t,n,i,r,o,s){_iterCreate(n,t,i);var a,l,c,u=function(e){if(!BUGGY&&e in f)return f[e];switch(e){case KEYS:case VALUES:return function(){return new n(this,e)}}return function(){return new n(this,e)}},d=t+" Iterator",h=r==VALUES,p=!1,f=e.prototype,m=f[ITERATOR$3]||f[FF_ITERATOR]||r&&f[r],g=m||u(r),y=r?h?u("entries"):g:void 0,v="Array"==t&&f.entries||m;if(v&&(c=_objectGpo(v.call(new e)))!==Object.prototype&&c.next&&(_setToStringTag(c,d,!0),_library||"function"==typeof c[ITERATOR$3]||_hide(c,ITERATOR$3,returnThis)),h&&m&&m.name!==VALUES&&(p=!0,g=function(){return m.call(this)}),_library&&!s||!BUGGY&&!p&&f[ITERATOR$3]||_hide(f,ITERATOR$3,g),_iterators[t]=g,_iterators[d]=returnThis,r)if(a={values:h?g:u(VALUES),keys:o?g:u(KEYS),entries:y},s)for(l in a)l in f||_redefine(f,l,a[l]);else _export(_export.P+_export.F*(BUGGY||p),t,a);return a},es6_array_iterator=_iterDefine(Array,"Array",function(e,t){this._t=_toIobject(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,_iterStep(1)):_iterStep(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values");_iterators.Arguments=_iterators.Array,_addToUnscopables("keys"),_addToUnscopables("values"),_addToUnscopables("entries");for(var ITERATOR$4=_wks("iterator"),TO_STRING_TAG=_wks("toStringTag"),ArrayValues=_iterators.Array,DOMIterables={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},collections=_objectKeys(DOMIterables),i=0;i<collections.length;i++){var key$1,NAME=collections[i],explicit=DOMIterables[NAME],Collection=_global[NAME],proto$1=Collection&&Collection.prototype;if(proto$1&&(proto$1[ITERATOR$4]||_hide(proto$1,ITERATOR$4,ArrayValues),proto$1[TO_STRING_TAG]||_hide(proto$1,TO_STRING_TAG,NAME),_iterators[NAME]=ArrayValues,explicit))for(key$1 in es6_array_iterator)proto$1[key$1]||_redefine(proto$1,key$1,es6_array_iterator[key$1],!0)}var _stringAt=function(e){return function(t,n){var i,r,o=String(_defined(t)),s=_toInteger(n),a=o.length;return s<0||s>=a?e?"":void 0:(i=o.charCodeAt(s))<55296||i>56319||s+1===a||(r=o.charCodeAt(s+1))<56320||r>57343?e?o.charAt(s):i:e?o.slice(s,s+2):r-56320+(i-55296<<10)+65536}},$at=_stringAt(!0);_iterDefine(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=$at(t,n),this._i+=e.length,{value:e,done:!1})});var _meta=createCommonjsModule(function(e){var t=_uid("meta"),n=_objectDp.f,i=0,r=Object.isExtensible||function(){return!0},o=!_fails(function(){return r(Object.preventExtensions({}))}),s=function(e){n(e,t,{value:{i:"O"+ ++i,w:{}}})},a=e.exports={KEY:t,NEED:!1,fastKey:function(e,n){if(!_isObject(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!_has(e,t)){if(!r(e))return"F";if(!n)return"E";s(e)}return e[t].i},getWeak:function(e,n){if(!_has(e,t)){if(!r(e))return!0;if(!n)return!1;s(e)}return e[t].w},onFreeze:function(e){return o&&a.NEED&&r(e)&&!_has(e,t)&&s(e),e}}}),_meta_1=_meta.KEY,_meta_2=_meta.NEED,_meta_3=_meta.fastKey,_meta_4=_meta.getWeak,_meta_5=_meta.onFreeze,f$4=Object.getOwnPropertySymbols,_objectGops={f:f$4},$assign=Object.assign,_objectAssign=!$assign||_fails(function(){var e={},t={},n=Symbol(),i="abcdefghijklmnopqrst";return e[n]=7,i.split("").forEach(function(e){t[e]=e}),7!=$assign({},e)[n]||Object.keys($assign({},t)).join("")!=i})?function(e,t){for(var n=_toObject(e),i=arguments.length,r=1,o=_objectGops.f,s=_objectPie.f;i>r;)for(var a,l=_iobject(arguments[r++]),c=o?_objectKeys(l).concat(o(l)):_objectKeys(l),u=c.length,d=0;u>d;)s.call(l,a=c[d++])&&(n[a]=l[a]);return n}:$assign,_redefineAll=function(e,t,n){for(var i in t)_redefine(e,i,t[i],n);return e},_anInstance=function(e,t,n,i){if(!(e instanceof t)||void 0!==i&&i in e)throw TypeError(n+": incorrect invocation!");return e},_forOf=createCommonjsModule(function(e){var t={},n={},i=e.exports=function(e,i,r,o,s){var a,l,c,u,d=s?function(){return e}:core_getIteratorMethod(e),h=_ctx(r,o,i?2:1),p=0;if("function"!=typeof d)throw TypeError(e+" is not iterable!");if(_isArrayIter(d)){for(a=_toLength(e.length);a>p;p++)if((u=i?h(_anObject(l=e[p])[0],l[1]):h(e[p]))===t||u===n)return u}else for(c=d.call(e);!(l=c.next()).done;)if((u=_iterCall(c,h,l.value,i))===t||u===n)return u};i.BREAK=t,i.RETURN=n}),_validateCollection=function(e,t){if(!_isObject(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e},getWeak=_meta.getWeak,arrayFind=_arrayMethods(5),arrayFindIndex=_arrayMethods(6),id$1=0,uncaughtFrozenStore=function(e){return e._l||(e._l=new UncaughtFrozenStore)},UncaughtFrozenStore=function(){this.a=[]},findUncaughtFrozen=function(e,t){return arrayFind(e.a,function(e){return e[0]===t})};UncaughtFrozenStore.prototype={get:function(e){var t=findUncaughtFrozen(this,e);if(t)return t[1]},has:function(e){return!!findUncaughtFrozen(this,e)},set:function(e,t){var n=findUncaughtFrozen(this,e);n?n[1]=t:this.a.push([e,t])},delete:function(e){var t=arrayFindIndex(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}};var _collectionWeak={getConstructor:function(e,t,n,i){var r=e(function(e,o){_anInstance(e,r,t,"_i"),e._t=t,e._i=id$1++,e._l=void 0,null!=o&&_forOf(o,n,e[i],e)});return _redefineAll(r.prototype,{delete:function(e){if(!_isObject(e))return!1;var n=getWeak(e);return!0===n?uncaughtFrozenStore(_validateCollection(this,t)).delete(e):n&&_has(n,this._i)&&delete n[this._i]},has:function(e){if(!_isObject(e))return!1;var n=getWeak(e);return!0===n?uncaughtFrozenStore(_validateCollection(this,t)).has(e):n&&_has(n,this._i)}}),r},def:function(e,t,n){var i=getWeak(_anObject(t),!0);return!0===i?uncaughtFrozenStore(e).set(t,n):i[e._i]=n,e},ufstore:uncaughtFrozenStore},_collection=function(e,t,n,i,r,o){var s=_global[e],a=s,l=r?"set":"add",c=a&&a.prototype,u={},d=function(e){var t=c[e];_redefine(c,e,"delete"==e?function(e){return!(o&&!_isObject(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(o&&!_isObject(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return o&&!_isObject(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,n){return t.call(this,0===e?0:e,n),this})};if("function"==typeof a&&(o||c.forEach&&!_fails(function(){(new a).entries().next()}))){var h=new a,p=h[l](o?{}:-0,1)!=h,f=_fails(function(){h.has(1)}),m=_iterDetect(function(e){new a(e)}),g=!o&&_fails(function(){for(var e=new a,t=5;t--;)e[l](t,t);return!e.has(-0)});m||((a=t(function(t,n){_anInstance(t,a,e);var i=_inheritIfRequired(new s,t,a);return null!=n&&_forOf(n,r,i[l],i),i})).prototype=c,c.constructor=a),(f||g)&&(d("delete"),d("has"),r&&d("get")),(g||p)&&d(l),o&&c.clear&&delete c.clear}else a=i.getConstructor(t,e,r,l),_redefineAll(a.prototype,n),_meta.NEED=!0;return _setToStringTag(a,e),u[e]=a,_export(_export.G+_export.W+_export.F*(a!=s),u),o||i.setStrong(a,e,r),a},es6_weakMap=createCommonjsModule(function(e){var t,n=_arrayMethods(0),i=_meta.getWeak,r=Object.isExtensible,o=_collectionWeak.ufstore,s={},a=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},l={get:function(e){if(_isObject(e)){var t=i(e);return!0===t?o(_validateCollection(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return _collectionWeak.def(_validateCollection(this,"WeakMap"),e,t)}},c=e.exports=_collection("WeakMap",a,l,_collectionWeak,!0,!0);_fails(function(){return 7!=(new c).set((Object.freeze||Object)(s),7).get(s)})&&(t=_collectionWeak.getConstructor(a,"WeakMap"),_objectAssign(t.prototype,l),_meta.NEED=!0,n(["delete","has","get","set"],function(e){var n=c.prototype,i=n[e];_redefine(n,e,function(n,o){if(_isObject(n)&&!r(n)){this._f||(this._f=new t);var s=this._f[e](n,o);return"set"==e?this:s}return i.call(this,n,o)})}))});function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function _slicedToArray(e,t){return _arrayWithHoles(e)||_iterableToArrayLimit(e,t)||_nonIterableRest()}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_nonIterableSpread()}function _arrayWithoutHoles(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}function _arrayWithHoles(e){if(Array.isArray(e))return e}function _iterableToArray(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function _iterableToArrayLimit(e,t){var n=[],i=!0,r=!1,o=void 0;try{for(var s,a=e[Symbol.iterator]();!(i=(s=a.next()).done)&&(n.push(s.value),!t||n.length!==t);i=!0);}catch(e){r=!0,o=e}finally{try{i||null==a.return||a.return()}finally{if(r)throw o}}return n}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}var _strictMethod=function(e,t){return!!e&&_fails(function(){t?e.call(null,function(){},1):e.call(null)})},$sort=[].sort,test=[1,2,3];_export(_export.P+_export.F*(_fails(function(){test.sort(void 0)})||!_fails(function(){test.sort(null)})||!_strictMethod($sort)),"Array",{sort:function(e){return void 0===e?$sort.call(_toObject(this)):$sort.call(_toObject(this),_aFunction(e))}}),_export(_export.S+_export.F,"Object",{assign:_objectAssign});var SPECIES$2=_wks("species"),_speciesConstructor=function(e,t){var n,i=_anObject(e).constructor;return void 0===i||null==(n=_anObject(i)[SPECIES$2])?t:_aFunction(n)},at=_stringAt(!0),_advanceStringIndex=function(e,t,n){return t+(n?at(e,t).length:1)},$min=Math.min,$push=[].push,$SPLIT="split",LENGTH="length",LAST_INDEX$1="lastIndex",MAX_UINT32=4294967295,SUPPORTS_Y=!_fails(function(){});_fixReWks("split",2,function(e,t,n,i){var r;return r="c"=="abbc"[$SPLIT](/(b)*/)[1]||4!="test"[$SPLIT](/(?:)/,-1)[LENGTH]||2!="ab"[$SPLIT](/(?:ab)*/)[LENGTH]||4!="."[$SPLIT](/(.?)(.?)/)[LENGTH]||"."[$SPLIT](/()()/)[LENGTH]>1||""[$SPLIT](/.?/)[LENGTH]?function(e,t){var i=String(this);if(void 0===e&&0===t)return[];if(!_isRegexp(e))return n.call(i,e,t);for(var r,o,s,a=[],l=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),c=0,u=void 0===t?MAX_UINT32:t>>>0,d=new RegExp(e.source,l+"g");(r=_regexpExec.call(d,i))&&!((o=d[LAST_INDEX$1])>c&&(a.push(i.slice(c,r.index)),r[LENGTH]>1&&r.index<i[LENGTH]&&$push.apply(a,r.slice(1)),s=r[0][LENGTH],c=o,a[LENGTH]>=u));)d[LAST_INDEX$1]===r.index&&d[LAST_INDEX$1]++;return c===i[LENGTH]?!s&&d.test("")||a.push(""):a.push(i.slice(c)),a[LENGTH]>u?a.slice(0,u):a}:"0"[$SPLIT](void 0,0)[LENGTH]?function(e,t){return void 0===e&&0===t?[]:n.call(this,e,t)}:n,[function(n,i){var o=e(this),s=null==n?void 0:n[t];return void 0!==s?s.call(n,o,i):r.call(String(o),n,i)},function(e,t){var o=i(r,e,this,t,r!==n);if(o.done)return o.value;var s=_anObject(e),a=String(this),l=_speciesConstructor(s,RegExp),c=s.unicode,u=(s.ignoreCase?"i":"")+(s.multiline?"m":"")+(s.unicode?"u":"")+(SUPPORTS_Y?"y":"g"),d=new l(SUPPORTS_Y?s:"^(?:"+s.source+")",u),h=void 0===t?MAX_UINT32:t>>>0;if(0===h)return[];if(0===a.length)return null===_regexpExecAbstract(d,a)?[a]:[];for(var p=0,f=0,m=[];f<a.length;){d.lastIndex=SUPPORTS_Y?f:0;var g,y=_regexpExecAbstract(d,SUPPORTS_Y?a:a.slice(f));if(null===y||(g=$min(_toLength(d.lastIndex+(SUPPORTS_Y?0:f)),a.length))===p)f=_advanceStringIndex(a,f,c);else{if(m.push(a.slice(p,f)),m.length===h)return m;for(var v=1;v<=y.length-1;v++)if(m.push(y[v]),m.length===h)return m;f=p=g}}return m.push(a.slice(p)),m}]});var isEnum=_objectPie.f,_objectToArray=function(e){return function(t){for(var n,i=_toIobject(t),r=_objectKeys(i),o=r.length,s=0,a=[];o>s;)isEnum.call(i,n=r[s++])&&a.push(e?[n,i[n]]:i[n]);return a}},$entries=_objectToArray(!0);_export(_export.S,"Object",{entries:function(e){return $entries(e)}});var $values=_objectToArray(!1);_export(_export.S,"Object",{values:function(e){return $values(e)}});var max$1=Math.max,min$2=Math.min,floor$1=Math.floor,SUBSTITUTION_SYMBOLS=/\$([$&`']|\d\d?|<[^>]*>)/g,SUBSTITUTION_SYMBOLS_NO_NAMED=/\$([$&`']|\d\d?)/g,maybeToString=function(e){return void 0===e?e:String(e)};_fixReWks("replace",2,function(e,t,n,i){return[function(i,r){var o=e(this),s=null==i?void 0:i[t];return void 0!==s?s.call(i,o,r):n.call(String(o),i,r)},function(e,t){var o=i(n,e,this,t);if(o.done)return o.value;var s=_anObject(e),a=String(this),l="function"==typeof t;l||(t=String(t));var c=s.global;if(c){var u=s.unicode;s.lastIndex=0}for(var d=[];;){var h=_regexpExecAbstract(s,a);if(null===h)break;if(d.push(h),!c)break;""===String(h[0])&&(s.lastIndex=_advanceStringIndex(a,_toLength(s.lastIndex),u))}for(var p="",f=0,m=0;m<d.length;m++){h=d[m];for(var g=String(h[0]),y=max$1(min$2(_toInteger(h.index),a.length),0),v=[],b=1;b<h.length;b++)v.push(maybeToString(h[b]));var _=h.groups;if(l){var E=[g].concat(v,y,a);void 0!==_&&E.push(_);var T=String(t.apply(void 0,E))}else T=r(g,a,y,v,_,t);y>=f&&(p+=a.slice(f,y)+T,f=y+g.length)}return p+a.slice(f)}];function r(e,t,i,r,o,s){var a=i+e.length,l=r.length,c=SUBSTITUTION_SYMBOLS_NO_NAMED;return void 0!==o&&(o=_toObject(o),c=SUBSTITUTION_SYMBOLS),n.call(s,c,function(n,s){var c;switch(s.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,i);case"'":return t.slice(a);case"<":c=o[s.slice(1,-1)];break;default:var u=+s;if(0===u)return n;if(u>l){var d=floor$1(u/10);return 0===d?n:d<=l?void 0===r[d-1]?s.charAt(1):r[d-1]+s.charAt(1):n}c=r[u-1]}return void 0===c?"":c})}});var defer,channel,port,_invoke=function(e,t,n){var i=void 0===n;switch(t.length){case 0:return i?e():e.call(n);case 1:return i?e(t[0]):e.call(n,t[0]);case 2:return i?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return i?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return i?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}return e.apply(n,t)},process=_global.process,setTask=_global.setImmediate,clearTask=_global.clearImmediate,MessageChannel=_global.MessageChannel,Dispatch=_global.Dispatch,counter=0,queue={},ONREADYSTATECHANGE="onreadystatechange",run=function(){var e=+this;if(queue.hasOwnProperty(e)){var t=queue[e];delete queue[e],t()}},listener=function(e){run.call(e.data)};setTask&&clearTask||(setTask=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return queue[++counter]=function(){_invoke("function"==typeof e?e:Function(e),t)},defer(counter),counter},clearTask=function(e){delete queue[e]},"process"==_cof(process)?defer=function(e){process.nextTick(_ctx(run,e,1))}:Dispatch&&Dispatch.now?defer=function(e){Dispatch.now(_ctx(run,e,1))}:MessageChannel?(port=(channel=new MessageChannel).port2,channel.port1.onmessage=listener,defer=_ctx(port.postMessage,port,1)):_global.addEventListener&&"function"==typeof postMessage&&!_global.importScripts?(defer=function(e){_global.postMessage(e+"","*")},_global.addEventListener("message",listener,!1)):defer=ONREADYSTATECHANGE in _domCreate("script")?function(e){_html.appendChild(_domCreate("script"))[ONREADYSTATECHANGE]=function(){_html.removeChild(this),run.call(e)}}:function(e){setTimeout(_ctx(run,e,1),0)});var _task={set:setTask,clear:clearTask},macrotask=_task.set,Observer=_global.MutationObserver||_global.WebKitMutationObserver,process$1=_global.process,Promise$1=_global.Promise,isNode="process"==_cof(process$1),_microtask=function(){var e,t,n,i=function(){var i,r;for(isNode&&(i=process$1.domain)&&i.exit();e;){r=e.fn,e=e.next;try{r()}catch(i){throw e?n():t=void 0,i}}t=void 0,i&&i.enter()};if(isNode)n=function(){process$1.nextTick(i)};else if(!Observer||_global.navigator&&_global.navigator.standalone)if(Promise$1&&Promise$1.resolve){var r=Promise$1.resolve(void 0);n=function(){r.then(i)}}else n=function(){macrotask.call(_global,i)};else{var o=!0,s=document.createTextNode("");new Observer(i).observe(s,{characterData:!0}),n=function(){s.data=o=!o}}return function(i){var r={fn:i,next:void 0};t&&(t.next=r),e||(e=r,n()),t=r}};function PromiseCapability(e){var t,n;this.promise=new e(function(e,i){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=i}),this.resolve=_aFunction(t),this.reject=_aFunction(n)}var Internal,newGenericPromiseCapability,OwnPromiseCapability,Wrapper,f$5=function(e){return new PromiseCapability(e)},_newPromiseCapability={f:f$5},_perform=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}},navigator$1=_global.navigator,_userAgent=navigator$1&&navigator$1.userAgent||"",_promiseResolve=function(e,t){if(_anObject(e),_isObject(t)&&t.constructor===e)return t;var n=_newPromiseCapability.f(e);return(0,n.resolve)(t),n.promise},SPECIES$3=_wks("species"),_setSpecies=function(e){var t=_global[e];_descriptors&&t&&!t[SPECIES$3]&&_objectDp.f(t,SPECIES$3,{configurable:!0,get:function(){return this}})},task=_task.set,microtask=_microtask(),PROMISE="Promise",TypeError$1=_global.TypeError,process$2=_global.process,versions=process$2&&process$2.versions,v8=versions&&versions.v8||"",$Promise=_global[PROMISE],isNode$1="process"==_classof(process$2),empty=function(){},newPromiseCapability=newGenericPromiseCapability=_newPromiseCapability.f,USE_NATIVE=!!function(){try{var e=$Promise.resolve(1),t=(e.constructor={})[_wks("species")]=function(e){e(empty,empty)};return(isNode$1||"function"==typeof PromiseRejectionEvent)&&e.then(empty)instanceof t&&0!==v8.indexOf("6.6")&&-1===_userAgent.indexOf("Chrome/66")}catch(e){}}(),isThenable=function(e){var t;return!(!_isObject(e)||"function"!=typeof(t=e.then))&&t},notify=function(e,t){if(!e._n){e._n=!0;var n=e._c;microtask(function(){for(var i=e._v,r=1==e._s,o=0,s=function(t){var n,o,s,a=r?t.ok:t.fail,l=t.resolve,c=t.reject,u=t.domain;try{a?(r||(2==e._h&&onHandleUnhandled(e),e._h=1),!0===a?n=i:(u&&u.enter(),n=a(i),u&&(u.exit(),s=!0)),n===t.promise?c(TypeError$1("Promise-chain cycle")):(o=isThenable(n))?o.call(n,l,c):l(n)):c(i)}catch(e){u&&!s&&u.exit(),c(e)}};n.length>o;)s(n[o++]);e._c=[],e._n=!1,t&&!e._h&&onUnhandled(e)})}},onUnhandled=function(e){task.call(_global,function(){var t,n,i,r=e._v,o=isUnhandled(e);if(o&&(t=_perform(function(){isNode$1?process$2.emit("unhandledRejection",r,e):(n=_global.onunhandledrejection)?n({promise:e,reason:r}):(i=_global.console)&&i.error&&i.error("Unhandled promise rejection",r)}),e._h=isNode$1||isUnhandled(e)?2:1),e._a=void 0,o&&t.e)throw t.v})},isUnhandled=function(e){return 1!==e._h&&0===(e._a||e._c).length},onHandleUnhandled=function(e){task.call(_global,function(){var t;isNode$1?process$2.emit("rejectionHandled",e):(t=_global.onrejectionhandled)&&t({promise:e,reason:e._v})})},$reject=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),notify(t,!0))},$resolve=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw TypeError$1("Promise can't be resolved itself");(t=isThenable(e))?microtask(function(){var i={_w:n,_d:!1};try{t.call(e,_ctx($resolve,i,1),_ctx($reject,i,1))}catch(e){$reject.call(i,e)}}):(n._v=e,n._s=1,notify(n,!1))}catch(e){$reject.call({_w:n,_d:!1},e)}}};USE_NATIVE||($Promise=function(e){_anInstance(this,$Promise,PROMISE,"_h"),_aFunction(e),Internal.call(this);try{e(_ctx($resolve,this,1),_ctx($reject,this,1))}catch(e){$reject.call(this,e)}},(Internal=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=_redefineAll($Promise.prototype,{then:function(e,t){var n=newPromiseCapability(_speciesConstructor(this,$Promise));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=isNode$1?process$2.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&¬ify(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),OwnPromiseCapability=function(){var e=new Internal;this.promise=e,this.resolve=_ctx($resolve,e,1),this.reject=_ctx($reject,e,1)},_newPromiseCapability.f=newPromiseCapability=function(e){return e===$Promise||e===Wrapper?new OwnPromiseCapability(e):newGenericPromiseCapability(e)}),_export(_export.G+_export.W+_export.F*!USE_NATIVE,{Promise:$Promise}),_setToStringTag($Promise,PROMISE),_setSpecies(PROMISE),Wrapper=_core[PROMISE],_export(_export.S+_export.F*!USE_NATIVE,PROMISE,{reject:function(e){var t=newPromiseCapability(this);return(0,t.reject)(e),t.promise}}),_export(_export.S+_export.F*(_library||!USE_NATIVE),PROMISE,{resolve:function(e){return _promiseResolve(_library&&this===Wrapper?$Promise:this,e)}}),_export(_export.S+_export.F*!(USE_NATIVE&&_iterDetect(function(e){$Promise.all(e).catch(empty)})),PROMISE,{all:function(e){var t=this,n=newPromiseCapability(t),i=n.resolve,r=n.reject,o=_perform(function(){var n=[],o=0,s=1;_forOf(e,!1,function(e){var a=o++,l=!1;n.push(void 0),s++,t.resolve(e).then(function(e){l||(l=!0,n[a]=e,--s||i(n))},r)}),--s||i(n)});return o.e&&r(o.v),n.promise},race:function(e){var t=this,n=newPromiseCapability(t),i=n.reject,r=_perform(function(){_forOf(e,!1,function(e){t.resolve(e).then(n.resolve,i)})});return r.e&&i(r.v),n.promise}});var STARTS_WITH="startsWith",$startsWith=""[STARTS_WITH];_export(_export.P+_export.F*_failsIsRegexp(STARTS_WITH),"String",{startsWith:function(e){var t=_stringContext(this,e,STARTS_WITH),n=_toLength(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),i=String(e);return $startsWith?$startsWith.call(t,i,n):t.slice(n,n+i.length)===i}}),_export(_export.S,"Number",{isNaN:function(e){return e!=e}});var getConstructor=function(e){return null!=e?e.constructor:null},instanceOf=function(e,t){return Boolean(e&&t&&e instanceof t)},isNullOrUndefined=function(e){return null==e},isObject=function(e){return getConstructor(e)===Object},isNumber=function(e){return getConstructor(e)===Number&&!Number.isNaN(e)},isString=function(e){return getConstructor(e)===String},isBoolean=function(e){return getConstructor(e)===Boolean},isFunction=function(e){return getConstructor(e)===Function},isArray=function(e){return Array.isArray(e)},isWeakMap=function(e){return instanceOf(e,WeakMap)},isNodeList=function(e){return instanceOf(e,NodeList)},isElement=function(e){return instanceOf(e,Element)},isTextNode=function(e){return getConstructor(e)===Text},isEvent=function(e){return instanceOf(e,Event)},isKeyboardEvent=function(e){return instanceOf(e,KeyboardEvent)},isCue=function(e){return instanceOf(e,window.TextTrackCue)||instanceOf(e,window.VTTCue)},isTrack=function(e){return instanceOf(e,TextTrack)||!isNullOrUndefined(e)&&isString(e.kind)},isEmpty=function(e){return isNullOrUndefined(e)||(isString(e)||isArray(e)||isNodeList(e))&&!e.length||isObject(e)&&!Object.keys(e).length},isUrl=function(e){if(instanceOf(e,window.URL))return!0;if(!isString(e))return!1;var t=e;e.startsWith("http://")&&e.startsWith("https://")||(t="http://".concat(e));try{return!isEmpty(new URL(t).hostname)}catch(e){return!1}},is$1={nullOrUndefined:isNullOrUndefined,object:isObject,number:isNumber,string:isString,boolean:isBoolean,function:isFunction,array:isArray,weakMap:isWeakMap,nodeList:isNodeList,element:isElement,textNode:isTextNode,event:isEvent,keyboardEvent:isKeyboardEvent,cue:isCue,track:isTrack,url:isUrl,empty:isEmpty},supportsPassiveListeners=function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){return e=!0,null}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(e){}return e}();function toggleListener(e,t,n){var i=this,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(e&&"addEventListener"in e&&!is$1.empty(t)&&is$1.function(n)){var a=t.split(" "),l=s;supportsPassiveListeners&&(l={passive:o,capture:s}),a.forEach(function(t){i&&i.eventListeners&&r&&i.eventListeners.push({element:e,type:t,callback:n,options:l}),e[r?"addEventListener":"removeEventListener"](t,n,l)})}}function on(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,t,n,!0,i,r)}function off(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,t,n,!1,i,r)}function once(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2?arguments[2]:void 0,r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];toggleListener.call(this,e,n,function s(){off(e,n,s,r,o);for(var a=arguments.length,l=new Array(a),c=0;c<a;c++)l[c]=arguments[c];i.apply(t,l)},!0,r,o)}function triggerEvent(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(is$1.element(e)&&!is$1.empty(t)){var r=new CustomEvent(t,{bubbles:n,detail:Object.assign({},i,{plyr:this})});e.dispatchEvent(r)}}function unbindListeners(){this&&this.eventListeners&&(this.eventListeners.forEach(function(e){var t=e.element,n=e.type,i=e.callback,r=e.options;t.removeEventListener(n,i,r)}),this.eventListeners=[])}function ready(){var e=this;return new Promise(function(t){return e.ready?setTimeout(t,0):on.call(e,e.elements.container,"ready",t)}).then(function(){})}function wrap(e,t){var n=e.length?e:[e];Array.from(n).reverse().forEach(function(e,n){var i=n>0?t.cloneNode(!0):t,r=e.parentNode,o=e.nextSibling;i.appendChild(e),o?r.insertBefore(i,o):r.appendChild(i)})}function setAttributes(e,t){is$1.element(e)&&!is$1.empty(t)&&Object.entries(t).filter(function(e){var t=_slicedToArray(e,2)[1];return!is$1.nullOrUndefined(t)}).forEach(function(t){var n=_slicedToArray(t,2),i=n[0],r=n[1];return e.setAttribute(i,r)})}function createElement(e,t,n){var i=document.createElement(e);return is$1.object(t)&&setAttributes(i,t),is$1.string(n)&&(i.innerText=n),i}function insertAfter(e,t){is$1.element(e)&&is$1.element(t)&&t.parentNode.insertBefore(e,t.nextSibling)}function insertElement(e,t,n,i){is$1.element(t)&&t.appendChild(createElement(e,n,i))}function removeElement(e){is$1.nodeList(e)||is$1.array(e)?Array.from(e).forEach(removeElement):is$1.element(e)&&is$1.element(e.parentNode)&&e.parentNode.removeChild(e)}function emptyElement(e){if(is$1.element(e))for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1}function replaceElement(e,t){return is$1.element(t)&&is$1.element(t.parentNode)&&is$1.element(e)?(t.parentNode.replaceChild(e,t),e):null}function getAttributesFromSelector(e,t){if(!is$1.string(e)||is$1.empty(e))return{};var n={},i=t;return e.split(",").forEach(function(e){var t=e.trim(),r=t.replace(".",""),o=t.replace(/[[\]]/g,"").split("="),s=o[0],a=o.length>1?o[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":is$1.object(i)&&is$1.string(i.class)&&(i.class+=" ".concat(r)),n.class=r;break;case"#":n.id=t.replace("#","");break;case"[":n[s]=a}}),n}function toggleHidden(e,t){if(is$1.element(e)){var n=t;is$1.boolean(n)||(n=!e.hidden),n?e.setAttribute("hidden",""):e.removeAttribute("hidden")}}function toggleClass(e,t,n){if(is$1.nodeList(e))return Array.from(e).map(function(e){return toggleClass(e,t,n)});if(is$1.element(e)){var i="toggle";return void 0!==n&&(i=n?"add":"remove"),e.classList[i](t),e.classList.contains(t)}return!1}function hasClass(e,t){return is$1.element(e)&&e.classList.contains(t)}function matches(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function getElements(e){return this.elements.container.querySelectorAll(e)}function getElement(e){return this.elements.container.querySelector(e)}function trapFocus(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(is$1.element(e)){var n=getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=n[0],r=n[n.length-1];toggleListener.call(this,this.elements.container,"keydown",function(e){if("Tab"===e.key&&9===e.keyCode){var t=document.activeElement;t!==r||e.shiftKey?t===i&&e.shiftKey&&(r.focus(),e.preventDefault()):(i.focus(),e.preventDefault())}},t,!1)}}function setFocus(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];is$1.element(e)&&(e.focus({preventScroll:!0}),t&&toggleClass(e,this.config.classNames.tabFocus))}var transitionEndEvent=function(){var e=document.createElement("span"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n=Object.keys(t).find(function(t){return void 0!==e.style[t]});return!!is$1.string(n)&&t[n]}();function repaint(e){setTimeout(function(){try{toggleHidden(e,!0),e.offsetHeight,toggleHidden(e,!1)}catch(e){}},0)}var browser={isIE:!!document.documentMode,isEdge:window.navigator.userAgent.includes("Edge"),isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)},defaultCodecs={"audio/ogg":"vorbis","audio/wav":"1","video/webm":"vp8, vorbis","video/mp4":"avc1.42E01E, mp4a.40.2","video/ogg":"theora"},support={audio:"canPlayType"in document.createElement("audio"),video:"canPlayType"in document.createElement("video"),check:function(e,t,n){var i=browser.isIPhone&&n&&support.playsinline,r=support[e]||"html5"!==t;return{api:r,ui:r&&support.rangeInput&&("video"!==e||!browser.isIPhone||i)}},pip:!(browser.isIPhone||!is$1.function(createElement("video").webkitSetPresentationMode)&&(!document.pictureInPictureEnabled||createElement("video").disablePictureInPicture)),airplay:is$1.function(window.WebKitPlaybackTargetAvailabilityEvent),playsinline:"playsInline"in document.createElement("video"),mime:function(e){if(is$1.empty(e))return!1;var t=_slicedToArray(e.split("/"),1)[0],n=e;if(!this.isHTML5||t!==this.type)return!1;Object.keys(defaultCodecs).includes(n)&&(n+='; codecs="'.concat(defaultCodecs[e],'"'));try{return Boolean(n&&this.media.canPlayType(n).replace(/no/,""))}catch(e){return!1}},textTracks:"textTracks"in document.createElement("video"),rangeInput:function(){var e=document.createElement("input");return e.type="range","range"===e.type}(),touch:"ontouchstart"in document.documentElement,transitions:!1!==transitionEndEvent,reducedMotion:"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches},html5={getSources:function(){var e=this;return this.isHTML5?Array.from(this.media.querySelectorAll("source")).filter(function(t){var n=t.getAttribute("type");return!!is$1.empty(n)||support.mime.call(e,n)}):[]},getQualityOptions:function(){return html5.getSources.call(this).map(function(e){return Number(e.getAttribute("size"))}).filter(Boolean)},extend:function(){if(this.isHTML5){var e=this;Object.defineProperty(e.media,"quality",{get:function(){var t=html5.getSources.call(e).find(function(t){return t.getAttribute("src")===e.source});return t&&Number(t.getAttribute("size"))},set:function(t){var n=html5.getSources.call(e).find(function(e){return Number(e.getAttribute("size"))===t});if(n){var i=e.media,r=i.currentTime,o=i.paused,s=i.preload,a=i.readyState;e.media.src=n.getAttribute("src"),("none"!==s||a)&&(e.once("loadedmetadata",function(){e.currentTime=r,o||e.play()}),e.media.load()),triggerEvent.call(e,e.media,"qualitychange",!1,{quality:t})}}})}},cancelRequests:function(){this.isHTML5&&(removeElement(html5.getSources.call(this)),this.media.setAttribute("src",this.config.blankVideo),this.media.load(),this.debug.log("Cancelled network requests"))}};function dedupe(e){return is$1.array(e)?e.filter(function(t,n){return e.indexOf(t)===n}):e}function closest(e,t){return is$1.array(e)&&e.length?e.reduce(function(e,n){return Math.abs(n-t)<Math.abs(e-t)?n:e}):null}function cloneDeep(e){return JSON.parse(JSON.stringify(e))}function getDeep(e,t){return t.split(".").reduce(function(e,t){return e&&e[t]},e)}function extend(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];if(!n.length)return e;var r=n.shift();return is$1.object(r)?(Object.keys(r).forEach(function(t){is$1.object(r[t])?(Object.keys(e).includes(t)||Object.assign(e,_defineProperty({},t,{})),extend(e[t],r[t])):Object.assign(e,_defineProperty({},t,r[t]))}),extend.apply(void 0,[e].concat(n))):e}var dP$2=_objectDp.f,gOPN$1=_objectGopn.f,$RegExp=_global.RegExp,Base$1=$RegExp,proto$2=$RegExp.prototype,re1=/a/g,re2=/a/g,CORRECT_NEW=new $RegExp(re1)!==re1;if(_descriptors&&(!CORRECT_NEW||_fails(function(){return re2[_wks("match")]=!1,$RegExp(re1)!=re1||$RegExp(re2)==re2||"/a/i"!=$RegExp(re1,"i")}))){$RegExp=function(e,t){var n=this instanceof $RegExp,i=_isRegexp(e),r=void 0===t;return!n&&i&&e.constructor===$RegExp&&r?e:_inheritIfRequired(CORRECT_NEW?new Base$1(i&&!r?e.source:e,t):Base$1((i=e instanceof $RegExp)?e.source:e,i&&r?_flags.call(e):t),n?this:proto$2,$RegExp)};for(var proxy=function(e){e in $RegExp||dP$2($RegExp,e,{configurable:!0,get:function(){return Base$1[e]},set:function(t){Base$1[e]=t}})},keys$1=gOPN$1(Base$1),i$1=0;keys$1.length>i$1;)proxy(keys$1[i$1++]);proto$2.constructor=$RegExp,$RegExp.prototype=proto$2,_redefine(_global,"RegExp",$RegExp)}function generateId(e){return"".concat(e,"-").concat(Math.floor(1e4*Math.random()))}function format(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];return is$1.empty(e)?e:e.toString().replace(/{(\d+)}/g,function(e,t){return n[t].toString()})}function getPercentage(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)}function replaceAll(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1"),"g"),n.toString())}function toTitleCase(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}function toPascalCase(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return e=replaceAll(e,"-"," "),e=replaceAll(e,"_"," "),replaceAll(e=toTitleCase(e)," ","")}function toCamelCase(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString();return(e=toPascalCase(e)).charAt(0).toLowerCase()+e.slice(1)}function stripHTML(e){var t=document.createDocumentFragment(),n=document.createElement("div");return t.appendChild(n),n.innerHTML=e,t.firstChild.innerText}function getHTML(e){var t=document.createElement("div");return t.appendChild(e),t.innerHTML}_setSpecies("RegExp");var resources={pip:"PIP",airplay:"AirPlay",html5:"HTML5",vimeo:"Vimeo",youtube:"YouTube"},i18n={get:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(is$1.empty(e)||is$1.empty(t))return"";var n=getDeep(t.i18n,e);if(is$1.empty(n))return Object.keys(resources).includes(e)?resources[e]:"";var i={"{seektime}":t.seekTime,"{title}":t.title};return Object.entries(i).forEach(function(e){var t=_slicedToArray(e,2),i=t[0],r=t[1];n=replaceAll(n,i,r)}),n}},Storage=function(){function e(t){_classCallCheck(this,e),this.enabled=t.config.storage.enabled,this.key=t.config.storage.key}return _createClass(e,[{key:"get",value:function(t){if(!e.supported||!this.enabled)return null;var n=window.localStorage.getItem(this.key);if(is$1.empty(n))return null;var i=JSON.parse(n);return is$1.string(t)&&t.length?i[t]:i}},{key:"set",value:function(t){if(e.supported&&this.enabled&&is$1.object(t)){var n=this.get();is$1.empty(n)&&(n={}),extend(n,t),window.localStorage.setItem(this.key,JSON.stringify(n))}}}],[{key:"supported",get:function(){try{if(!("localStorage"in window))return!1;return window.localStorage.setItem("___test","___test"),window.localStorage.removeItem("___test"),!0}catch(e){return!1}}}]),e}();function fetch(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";return new Promise(function(n,i){try{var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.addEventListener("load",function(){if("text"===t)try{n(JSON.parse(r.responseText))}catch(e){n(r.responseText)}else n(r.response)}),r.addEventListener("error",function(){throw new Error(r.status)}),r.open("GET",e,!0),r.responseType=t,r.send()}catch(e){i(e)}})}function loadSprite(e,t){if(is$1.string(e)){var n=is$1.string(t),i=function(){return null!==document.getElementById(t)},r=function(e,t){e.innerHTML=t,n&&i()||document.body.insertAdjacentElement("afterbegin",e)};if(!n||!i()){var o=Storage.supported,s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),o){var a=window.localStorage.getItem("".concat("cache","-").concat(t));if(null!==a){var l=JSON.parse(a);r(s,l.content)}}fetch(e).then(function(e){is$1.empty(e)||(o&&window.localStorage.setItem("".concat("cache","-").concat(t),JSON.stringify({content:e})),r(s,e))}).catch(function(){})}}}_export(_export.S,"Math",{trunc:function(e){return(e>0?Math.floor:Math.ceil)(e)}});var getHours=function(e){return Math.trunc(e/60/60%60,10)},getMinutes=function(e){return Math.trunc(e/60%60,10)},getSeconds=function(e){return Math.trunc(e%60,10)};function formatTime(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!is$1.number(e))return formatTime(null,t,n);var i=function(e){return"0".concat(e).slice(-2)},r=getHours(e),o=getMinutes(e),s=getSeconds(e);return r=t||r>0?"".concat(r,":"):"","".concat(n&&e>0?"-":"").concat(r).concat(i(o),":").concat(i(s))}var controls={getIconUrl:function(){var e=new URL(this.config.iconUrl,window.location).host!==window.location.host||browser.isIE&&!window.svg4everybody;return{url:this.config.iconUrl,cors:e}},findElements:function(){try{return this.elements.controls=getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:getElements.call(this,this.config.selectors.buttons.play),pause:getElement.call(this,this.config.selectors.buttons.pause),restart:getElement.call(this,this.config.selectors.buttons.restart),rewind:getElement.call(this,this.config.selectors.buttons.rewind),fastForward:getElement.call(this,this.config.selectors.buttons.fastForward),mute:getElement.call(this,this.config.selectors.buttons.mute),pip:getElement.call(this,this.config.selectors.buttons.pip),airplay:getElement.call(this,this.config.selectors.buttons.airplay),settings:getElement.call(this,this.config.selectors.buttons.settings),captions:getElement.call(this,this.config.selectors.buttons.captions),fullscreen:getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:getElement.call(this,this.config.selectors.inputs.seek),volume:getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:getElement.call(this,this.config.selectors.display.buffer),currentTime:getElement.call(this,this.config.selectors.display.currentTime),duration:getElement.call(this,this.config.selectors.display.duration)},is$1.element(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip))),!0}catch(e){return this.debug.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},createIcon:function(e,t){var n=controls.getIconUrl.call(this),i="".concat(n.cors?"":n.url,"#").concat(this.config.iconPrefix),r=document.createElementNS("http://www.w3.org/2000/svg","svg");setAttributes(r,extend(t,{role:"presentation",focusable:"false"}));var o=document.createElementNS("http://www.w3.org/2000/svg","use"),s="".concat(i,"-").concat(e);return"href"in o&&o.setAttributeNS("http://www.w3.org/1999/xlink","href",s),o.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",s),r.appendChild(o),r},createLabel:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=i18n.get(e,this.config);return createElement("span",Object.assign({},t,{class:[t.class,this.config.classNames.hidden].filter(Boolean).join(" ")}),n)},createBadge:function(e){if(is$1.empty(e))return null;var t=createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var n=Object.assign({},t),i=toCamelCase(e),r={element:"button",toggle:!1,label:null,icon:null,labelPressed:null,iconPressed:null};switch(["element","icon","label"].forEach(function(e){Object.keys(n).includes(e)&&(r[e]=n[e],delete n[e])}),"button"!==r.element||Object.keys(n).includes("type")||(n.type="button"),Object.keys(n).includes("class")?n.class.includes(this.config.classNames.control)||(n.class+=" ".concat(this.config.classNames.control)):n.class=this.config.classNames.control,e){case"play":r.toggle=!0,r.label="play",r.labelPressed="pause",r.icon="play",r.iconPressed="pause";break;case"mute":r.toggle=!0,r.label="mute",r.labelPressed="unmute",r.icon="volume",r.iconPressed="muted";break;case"captions":r.toggle=!0,r.label="enableCaptions",r.labelPressed="disableCaptions",r.icon="captions-off",r.iconPressed="captions-on";break;case"fullscreen":r.toggle=!0,r.label="enterFullscreen",r.labelPressed="exitFullscreen",r.icon="enter-fullscreen",r.iconPressed="exit-fullscreen";break;case"play-large":n.class+=" ".concat(this.config.classNames.control,"--overlaid"),i="play",r.label="play",r.icon="play";break;default:is$1.empty(r.label)&&(r.label=i),is$1.empty(r.icon)&&(r.icon=e)}var o=createElement(r.element);return r.toggle?(o.appendChild(controls.createIcon.call(this,r.iconPressed,{class:"icon--pressed"})),o.appendChild(controls.createIcon.call(this,r.icon,{class:"icon--not-pressed"})),o.appendChild(controls.createLabel.call(this,r.labelPressed,{class:"label--pressed"})),o.appendChild(controls.createLabel.call(this,r.label,{class:"label--not-pressed"}))):(o.appendChild(controls.createIcon.call(this,r.icon)),o.appendChild(controls.createLabel.call(this,r.label))),extend(n,getAttributesFromSelector(this.config.selectors.buttons[i],n)),setAttributes(o,n),"play"===i?(is$1.array(this.elements.buttons[i])||(this.elements.buttons[i]=[]),this.elements.buttons[i].push(o)):this.elements.buttons[i]=o,o},createRange:function(e,t){var n=createElement("input",extend(getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off",role:"slider","aria-label":i18n.get(e,this.config),"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":0},t));return this.elements.inputs[e]=n,controls.updateRangeFill.call(this,n),n},createProgress:function(e,t){var n=createElement("progress",extend(getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0,role:"presentation","aria-hidden":!0},t));if("volume"!==e){n.appendChild(createElement("span",null,"0"));var i={played:"played",buffer:"buffered"}[e],r=i?i18n.get(i,this.config):"";n.innerText="% ".concat(r.toLowerCase())}return this.elements.display[e]=n,n},createTime:function(e){var t=getAttributesFromSelector(this.config.selectors.display[e]),n=createElement("div",extend(t,{class:"".concat(this.config.classNames.display.time," ").concat(t.class?t.class:"").trim(),"aria-label":i18n.get(e,this.config)}),"00:00");return this.elements.display[e]=n,n},bindMenuItemShortcuts:function(e,t){var n=this;on(e,"keydown keyup",function(i){if([32,38,39,40].includes(i.which)&&(i.preventDefault(),i.stopPropagation(),"keydown"!==i.type)){var r,o=matches(e,'[role="menuitemradio"]');if(!o&&[32,39].includes(i.which))controls.showMenuPanel.call(n,t,!0);else 32!==i.which&&(40===i.which||o&&39===i.which?(r=e.nextElementSibling,is$1.element(r)||(r=e.parentNode.firstElementChild)):(r=e.previousElementSibling,is$1.element(r)||(r=e.parentNode.lastElementChild)),setFocus.call(n,r,!0))}},!1),on(e,"keyup",function(e){13===e.which&&controls.focusFirstMenuItem.call(n,null,!0)})},createMenuItem:function(e){var t=this,n=e.value,i=e.list,r=e.type,o=e.title,s=e.badge,a=void 0===s?null:s,l=e.checked,c=void 0!==l&&l,u=getAttributesFromSelector(this.config.selectors.inputs[r]),d=createElement("button",extend(u,{type:"button",role:"menuitemradio",class:"".concat(this.config.classNames.control," ").concat(u.class?u.class:"").trim(),"aria-checked":c,value:n})),h=createElement("span");h.innerHTML=o,is$1.element(a)&&h.appendChild(a),d.appendChild(h),Object.defineProperty(d,"checked",{enumerable:!0,get:function(){return"true"===d.getAttribute("aria-checked")},set:function(e){e&&Array.from(d.parentNode.children).filter(function(e){return matches(e,'[role="menuitemradio"]')}).forEach(function(e){return e.setAttribute("aria-checked","false")}),d.setAttribute("aria-checked",e?"true":"false")}}),this.listeners.bind(d,"click keyup",function(e){if(!is$1.keyboardEvent(e)||32===e.which){switch(e.preventDefault(),e.stopPropagation(),d.checked=!0,r){case"language":t.currentTrack=Number(n);break;case"quality":t.quality=n;break;case"speed":t.speed=parseFloat(n)}controls.showMenuPanel.call(t,"home",is$1.keyboardEvent(e))}},r,!1),controls.bindMenuItemShortcuts.call(this,d,r),i.appendChild(d)},formatTime:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return is$1.number(e)?formatTime(e,getHours(this.duration)>0,t):e},updateTimeDisplay:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];is$1.element(e)&&is$1.number(t)&&(e.innerText=controls.formatTime(t,n))},updateVolume:function(){this.supported.ui&&(is$1.element(this.elements.inputs.volume)&&controls.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),is$1.element(this.elements.buttons.mute)&&(this.elements.buttons.mute.pressed=this.muted||0===this.volume))},setRange:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;is$1.element(e)&&(e.value=t,controls.updateRangeFill.call(this,e))},updateProgress:function(e){var t=this;if(this.supported.ui&&is$1.event(e)){var n=0;if(e)switch(e.type){case"timeupdate":case"seeking":case"seeked":n=getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&controls.setRange.call(this,this.elements.inputs.seek,n);break;case"playing":case"progress":!function(e,n){var i=is$1.number(n)?n:0,r=is$1.element(e)?e:t.elements.display.buffer;if(is$1.element(r)){r.value=i;var o=r.getElementsByTagName("span")[0];is$1.element(o)&&(o.childNodes[0].nodeValue=i)}}(this.elements.display.buffer,100*this.buffered)}}},updateRangeFill:function(e){var t=is$1.event(e)?e.target:e;if(is$1.element(t)&&"range"===t.getAttribute("type")){if(matches(t,this.config.selectors.inputs.seek)){t.setAttribute("aria-valuenow",this.currentTime);var n=controls.formatTime(this.currentTime),i=controls.formatTime(this.duration),r=i18n.get("seekLabel",this.config);t.setAttribute("aria-valuetext",r.replace("{currentTime}",n).replace("{duration}",i))}else if(matches(t,this.config.selectors.inputs.volume)){var o=100*t.value;t.setAttribute("aria-valuenow",o),t.setAttribute("aria-valuetext","".concat(o.toFixed(1),"%"))}else t.setAttribute("aria-valuenow",t.value);browser.isWebkit&&t.style.setProperty("--value","".concat(t.value/t.max*100,"%"))}},updateSeekTooltip:function(e){var t=this;if(this.config.tooltips.seek&&is$1.element(this.elements.inputs.seek)&&is$1.element(this.elements.display.seekTooltip)&&0!==this.duration){var n=0,i=this.elements.progress.getBoundingClientRect(),r="".concat(this.config.classNames.tooltip,"--visible"),o=function(e){toggleClass(t.elements.display.seekTooltip,r,e)};if(this.touch)o(!1);else{if(is$1.event(e))n=100/i.width*(e.pageX-i.left);else{if(!hasClass(this.elements.display.seekTooltip,r))return;n=parseFloat(this.elements.display.seekTooltip.style.left,10)}n<0?n=0:n>100&&(n=100),controls.updateTimeDisplay.call(this,this.elements.display.seekTooltip,this.duration/100*n),this.elements.display.seekTooltip.style.left="".concat(n,"%"),is$1.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&o("mouseenter"===e.type)}}},timeUpdate:function(e){var t=!is$1.element(this.elements.display.duration)&&this.config.invertTime;controls.updateTimeDisplay.call(this,this.elements.display.currentTime,t?this.duration-this.currentTime:this.currentTime,t),e&&"timeupdate"===e.type&&this.media.seeking||controls.updateProgress.call(this,e)},durationUpdate:function(){if(this.supported.ui&&(this.config.invertTime||!this.currentTime)){if(this.duration>=Math.pow(2,32))return toggleHidden(this.elements.display.currentTime,!0),void toggleHidden(this.elements.progress,!0);is$1.element(this.elements.inputs.seek)&&this.elements.inputs.seek.setAttribute("aria-valuemax",this.duration);var e=is$1.element(this.elements.display.duration);!e&&this.config.displayDuration&&this.paused&&controls.updateTimeDisplay.call(this,this.elements.display.currentTime,this.duration),e&&controls.updateTimeDisplay.call(this,this.elements.display.duration,this.duration),controls.updateSeekTooltip.call(this)}},toggleMenuButton:function(e,t){toggleHidden(this.elements.settings.buttons[e],!t)},updateSetting:function(e,t,n){var i=this.elements.settings.panels[e],r=null,o=t;if("captions"===e)r=this.currentTrack;else{if(r=is$1.empty(n)?this[e]:n,is$1.empty(r)&&(r=this.config[e].default),!is$1.empty(this.options[e])&&!this.options[e].includes(r))return void this.debug.warn("Unsupported value of '".concat(r,"' for ").concat(e));if(!this.config[e].options.includes(r))return void this.debug.warn("Disabled value of '".concat(r,"' for ").concat(e))}if(is$1.element(o)||(o=i&&i.querySelector('[role="menu"]')),is$1.element(o)){this.elements.settings.buttons[e].querySelector(".".concat(this.config.classNames.menu.value)).innerHTML=controls.getLabel.call(this,e,r);var s=o&&o.querySelector('[value="'.concat(r,'"]'));is$1.element(s)&&(s.checked=!0)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?i18n.get("normal",this.config):"".concat(t,"×");case"quality":if(is$1.number(t)){var n=i18n.get("qualityLabel.".concat(t),this.config);return n.length?n:"".concat(t,"p")}return toTitleCase(t);case"captions":return captions.getLabel.call(this);default:return null}},setQualityMenu:function(e){var t=this;if(is$1.element(this.elements.settings.panels.quality)){var n=this.elements.settings.panels.quality.querySelector('[role="menu"]');is$1.array(e)&&(this.options.quality=dedupe(e).filter(function(e){return t.config.quality.options.includes(e)}));var i=!is$1.empty(this.options.quality)&&this.options.quality.length>1;if(controls.toggleMenuButton.call(this,"quality",i),emptyElement(n),controls.checkMenu.call(this),i){var r=function(e){var n=i18n.get("qualityBadge.".concat(e),t.config);return n.length?controls.createBadge.call(t,n):null};this.options.quality.sort(function(e,n){var i=t.config.quality.options;return i.indexOf(e)>i.indexOf(n)?1:-1}).forEach(function(e){controls.createMenuItem.call(t,{value:e,list:n,type:"quality",title:controls.getLabel.call(t,"quality",e),badge:r(e)})}),controls.updateSetting.call(this,"quality",n)}}},setCaptionsMenu:function(){var e=this;if(is$1.element(this.elements.settings.panels.captions)){var t=this.elements.settings.panels.captions.querySelector('[role="menu"]'),n=captions.getTracks.call(this),i=Boolean(n.length);if(controls.toggleMenuButton.call(this,"captions",i),emptyElement(t),controls.checkMenu.call(this),i){var r=n.map(function(n,i){return{value:i,checked:e.captions.toggled&&e.currentTrack===i,title:captions.getLabel.call(e,n),badge:n.language&&controls.createBadge.call(e,n.language.toUpperCase()),list:t,type:"language"}});r.unshift({value:-1,checked:!this.captions.toggled,title:i18n.get("disabled",this.config),list:t,type:"language"}),r.forEach(controls.createMenuItem.bind(this)),controls.updateSetting.call(this,"captions",t)}}},setSpeedMenu:function(e){var t=this;if(is$1.element(this.elements.settings.panels.speed)){var n=this.elements.settings.panels.speed.querySelector('[role="menu"]');is$1.array(e)?this.options.speed=e:(this.isHTML5||this.isVimeo)&&(this.options.speed=[.5,.75,1,1.25,1.5,1.75,2]),this.options.speed=this.options.speed.filter(function(e){return t.config.speed.options.includes(e)});var i=!is$1.empty(this.options.speed)&&this.options.speed.length>1;controls.toggleMenuButton.call(this,"speed",i),emptyElement(n),controls.checkMenu.call(this),i&&(this.options.speed.forEach(function(e){controls.createMenuItem.call(t,{value:e,list:n,type:"speed",title:controls.getLabel.call(t,"speed",e)})}),controls.updateSetting.call(this,"speed",n))}},checkMenu:function(){var e=this.elements.settings.buttons,t=!is$1.empty(e)&&Object.values(e).some(function(e){return!e.hidden});toggleHidden(this.elements.settings.menu,!t)},focusFirstMenuItem:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!this.elements.settings.popup.hidden){var n=e;is$1.element(n)||(n=Object.values(this.elements.settings.panels).find(function(e){return!e.hidden}));var i=n.querySelector('[role^="menuitem"]');setFocus.call(this,i,t)}},toggleMenu:function(e){var t=this.elements.settings.popup,n=this.elements.buttons.settings;if(is$1.element(t)&&is$1.element(n)){var i=t.hidden,r=i;if(is$1.boolean(e))r=e;else if(is$1.keyboardEvent(e)&&27===e.which)r=!1;else if(is$1.event(e)){var o=t.contains(e.target);if(o||!o&&e.target!==n&&r)return}n.setAttribute("aria-expanded",r),toggleHidden(t,!r),toggleClass(this.elements.container,this.config.classNames.menu.open,r),r&&is$1.keyboardEvent(e)?controls.focusFirstMenuItem.call(this,null,!0):r||i||setFocus.call(this,n,is$1.keyboardEvent(e))}},getMenuSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.removeAttribute("hidden"),e.parentNode.appendChild(t);var n=t.scrollWidth,i=t.scrollHeight;return removeElement(t),{width:n,height:i}},showMenuPanel:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=document.getElementById("plyr-settings-".concat(this.id,"-").concat(t));if(is$1.element(i)){var r=i.parentNode,o=Array.from(r.children).find(function(e){return!e.hidden});if(support.transitions&&!support.reducedMotion){r.style.width="".concat(o.scrollWidth,"px"),r.style.height="".concat(o.scrollHeight,"px");var s=controls.getMenuSize.call(this,i);on.call(this,r,transitionEndEvent,function t(n){n.target===r&&["width","height"].includes(n.propertyName)&&(r.style.width="",r.style.height="",off.call(e,r,transitionEndEvent,t))}),r.style.width="".concat(s.width,"px"),r.style.height="".concat(s.height,"px")}toggleHidden(o,!0),toggleHidden(i,!1),controls.focusFirstMenuItem.call(this,i,n)}},setDownloadLink:function(){var e=this.elements.buttons.download;is$1.element(e)&&e.setAttribute("href",this.download)},create:function(e){var t=this,n=createElement("div",getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&n.appendChild(controls.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&n.appendChild(controls.createButton.call(this,"rewind")),this.config.controls.includes("play")&&n.appendChild(controls.createButton.call(this,"play")),this.config.controls.includes("fast-forward")&&n.appendChild(controls.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var i=createElement("div",getAttributesFromSelector(this.config.selectors.progress));if(i.appendChild(controls.createRange.call(this,"seek",{id:"plyr-seek-".concat(e.id)})),i.appendChild(controls.createProgress.call(this,"buffer")),this.config.tooltips.seek){var r=createElement("span",{class:this.config.classNames.tooltip},"00:00");i.appendChild(r),this.elements.display.seekTooltip=r}this.elements.progress=i,n.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&n.appendChild(controls.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&n.appendChild(controls.createTime.call(this,"duration")),this.config.controls.includes("mute")||this.config.controls.includes("volume")){var o=createElement("div",{class:"plyr__volume"});if(this.config.controls.includes("mute")&&o.appendChild(controls.createButton.call(this,"mute")),this.config.controls.includes("volume")){var s={max:1,step:.05,value:this.config.volume};o.appendChild(controls.createRange.call(this,"volume",extend(s,{id:"plyr-volume-".concat(e.id)}))),this.elements.volume=o}n.appendChild(o)}if(this.config.controls.includes("captions")&&n.appendChild(controls.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!is$1.empty(this.config.settings)){var a=createElement("div",{class:"plyr__menu",hidden:""});a.appendChild(controls.createButton.call(this,"settings",{"aria-haspopup":!0,"aria-controls":"plyr-settings-".concat(e.id),"aria-expanded":!1}));var l=createElement("div",{class:"plyr__menu__container",id:"plyr-settings-".concat(e.id),hidden:""}),c=createElement("div"),u=createElement("div",{id:"plyr-settings-".concat(e.id,"-home")}),d=createElement("div",{role:"menu"});u.appendChild(d),c.appendChild(u),this.elements.settings.panels.home=u,this.config.settings.forEach(function(n){var i=createElement("button",extend(getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--forward"),role:"menuitem","aria-haspopup":!0,hidden:""}));controls.bindMenuItemShortcuts.call(t,i,n),on(i,"click",function(){controls.showMenuPanel.call(t,n,!1)});var r=createElement("span",null,i18n.get(n,t.config)),o=createElement("span",{class:t.config.classNames.menu.value});o.innerHTML=e[n],r.appendChild(o),i.appendChild(r),d.appendChild(i);var s=createElement("div",{id:"plyr-settings-".concat(e.id,"-").concat(n),hidden:""}),a=createElement("button",{type:"button",class:"".concat(t.config.classNames.control," ").concat(t.config.classNames.control,"--back")});a.appendChild(createElement("span",{"aria-hidden":!0},i18n.get(n,t.config))),a.appendChild(createElement("span",{class:t.config.classNames.hidden},i18n.get("menuBack",t.config))),on(s,"keydown",function(e){37===e.which&&(e.preventDefault(),e.stopPropagation(),controls.showMenuPanel.call(t,"home",!0))},!1),on(a,"click",function(){controls.showMenuPanel.call(t,"home",!1)}),s.appendChild(a),s.appendChild(createElement("div",{role:"menu"})),c.appendChild(s),t.elements.settings.buttons[n]=i,t.elements.settings.panels[n]=s}),l.appendChild(c),a.appendChild(l),n.appendChild(a),this.elements.settings.popup=l,this.elements.settings.menu=a}if(this.config.controls.includes("pip")&&support.pip&&n.appendChild(controls.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&support.airplay&&n.appendChild(controls.createButton.call(this,"airplay")),this.config.controls.includes("download")){var h={element:"a",href:this.download,target:"_blank"},p=this.config.urls.download;!is$1.url(p)&&this.isEmbed&&extend(h,{icon:"logo-".concat(this.provider),label:this.provider}),n.appendChild(controls.createButton.call(this,"download",h))}return this.config.controls.includes("fullscreen")&&n.appendChild(controls.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(controls.createButton.call(this,"play-large")),this.elements.controls=n,this.isHTML5&&controls.setQualityMenu.call(this,html5.getQualityOptions.call(this)),controls.setSpeedMenu.call(this),n},inject:function(){var e=this;if(this.config.loadSprite){var t=controls.getIconUrl.call(this);t.cors&&loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var n=null;this.elements.controls=null;var i={id:this.id,seektime:this.config.seekTime,title:this.config.title},r=!0;is$1.function(this.config.controls)&&(this.config.controls=this.config.controls.call(this,i)),this.config.controls||(this.config.controls=[]),is$1.element(this.config.controls)||is$1.string(this.config.controls)?n=this.config.controls:(n=controls.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:captions.getLabel.call(this)}),r=!1);var o,s=function(e){var t=e;return Object.entries(i).forEach(function(e){var n=_slicedToArray(e,2),i=n[0],r=n[1];t=replaceAll(t,"{".concat(i,"}"),r)}),t};if(r&&(is$1.string(this.config.controls)?n=s(n):is$1.element(n)&&(n.innerHTML=s(n.innerHTML))),is$1.string(this.config.selectors.controls.container)&&(o=document.querySelector(this.config.selectors.controls.container)),is$1.element(o)||(o=this.elements.container),o[is$1.element(n)?"insertAdjacentElement":"insertAdjacentHTML"]("afterbegin",n),is$1.element(this.elements.controls)||controls.findElements.call(this),!is$1.empty(this.elements.buttons)){var a=function(t){var n=e.config.classNames.controlPressed;Object.defineProperty(t,"pressed",{enumerable:!0,get:function(){return hasClass(t,n)},set:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];toggleClass(t,n,e)}})};Object.values(this.elements.buttons).filter(Boolean).forEach(function(e){is$1.array(e)||is$1.nodeList(e)?Array.from(e).filter(Boolean).forEach(a):a(e)})}if(browser.isEdge&&repaint(o),this.config.tooltips.controls){var l=this.config,c=l.classNames,u=l.selectors,d="".concat(u.controls.wrapper," ").concat(u.labels," .").concat(c.hidden),h=getElements.call(this,d);Array.from(h).forEach(function(t){toggleClass(t,e.config.classNames.hidden,!1),toggleClass(t,e.config.classNames.tooltip,!0)})}}};function parseUrl(e){var t=e;if(!(arguments.length>1&&void 0!==arguments[1])||arguments[1]){var n=document.createElement("a");n.href=t,t=n.href}try{return new URL(t)}catch(e){return null}}function buildUrlParams(e){var t=new URLSearchParams;return is$1.object(e)&&Object.entries(e).forEach(function(e){var n=_slicedToArray(e,2),i=n[0],r=n[1];t.set(i,r)}),t}var captions={setup:function(){if(this.supported.ui)if(!this.isVideo||this.isYouTube||this.isHTML5&&!support.textTracks)is$1.array(this.config.controls)&&this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&controls.setCaptionsMenu.call(this);else{if(is$1.element(this.elements.captions)||(this.elements.captions=createElement("div",getAttributesFromSelector(this.config.selectors.captions)),insertAfter(this.elements.captions,this.elements.wrapper)),browser.isIE&&window.URL){var e=this.media.querySelectorAll("track");Array.from(e).forEach(function(e){var t=e.getAttribute("src"),n=parseUrl(t);null!==n&&n.hostname!==window.location.href.hostname&&["http:","https:"].includes(n.protocol)&&fetch(t,"blob").then(function(t){e.setAttribute("src",window.URL.createObjectURL(t))}).catch(function(){removeElement(e)})})}var t=dedupe((navigator.languages||[navigator.language||navigator.userLanguage||"en"]).map(function(e){return e.split("-")[0]})),n=(this.storage.get("language")||this.config.captions.language||"auto").toLowerCase();if("auto"===n)n=_slicedToArray(t,1)[0];var i=this.storage.get("captions");if(is$1.boolean(i)||(i=this.config.captions.active),Object.assign(this.captions,{toggled:!1,active:i,language:n,languages:t}),this.isHTML5){var r=this.config.captions.update?"addtrack removetrack":"removetrack";on.call(this,this.media.textTracks,r,captions.update.bind(this))}setTimeout(captions.update.bind(this),0)}},update:function(){var e=this,t=captions.getTracks.call(this,!0),n=this.captions,i=n.active,r=n.language,o=n.meta,s=n.currentTrackNode,a=Boolean(t.find(function(e){return e.language===r}));this.isHTML5&&this.isVideo&&t.filter(function(e){return!o.get(e)}).forEach(function(t){e.debug.log("Track added",t),o.set(t,{default:"showing"===t.mode}),t.mode="hidden",on.call(e,t,"cuechange",function(){return captions.updateCues.call(e)})}),(a&&this.language!==r||!t.includes(s))&&(captions.setLanguage.call(this,r),captions.toggle.call(this,i&&a)),toggleClass(this.elements.container,this.config.classNames.captions.enabled,!is$1.empty(t)),(this.config.controls||[]).includes("settings")&&this.config.settings.includes("captions")&&controls.setCaptionsMenu.call(this)},toggle:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.supported.ui){var n=this.captions.toggled,i=this.config.classNames.captions.active,r=is$1.nullOrUndefined(e)?!n:e;if(r!==n){if(t||(this.captions.active=r,this.storage.set({captions:r})),!this.language&&r&&!t){var o=captions.getTracks.call(this),s=captions.findTrack.call(this,[this.captions.language].concat(_toConsumableArray(this.captions.languages)),!0);return this.captions.language=s.language,void captions.set.call(this,o.indexOf(s))}this.elements.buttons.captions&&(this.elements.buttons.captions.pressed=r),toggleClass(this.elements.container,i,r),this.captions.toggled=r,controls.updateSetting.call(this,"captions"),triggerEvent.call(this,this.media,r?"captionsenabled":"captionsdisabled")}}},set:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=captions.getTracks.call(this);if(-1!==e)if(is$1.number(e))if(e in n){if(this.captions.currentTrack!==e){this.captions.currentTrack=e;var i=n[e],r=(i||{}).language;this.captions.currentTrackNode=i,controls.updateSetting.call(this,"captions"),t||(this.captions.language=r,this.storage.set({language:r})),this.isVimeo&&this.embed.enableTextTrack(r),triggerEvent.call(this,this.media,"languagechange")}captions.toggle.call(this,!0,t),this.isHTML5&&this.isVideo&&captions.updateCues.call(this)}else this.debug.warn("Track not found",e);else this.debug.warn("Invalid caption argument",e);else captions.toggle.call(this,!1,t)},setLanguage:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(is$1.string(e)){var n=e.toLowerCase();this.captions.language=n;var i=captions.getTracks.call(this),r=captions.findTrack.call(this,[n]);captions.set.call(this,i.indexOf(r),t)}else this.debug.warn("Invalid language argument",e)},getTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Array.from((this.media||{}).textTracks||[]).filter(function(n){return!e.isHTML5||t||e.captions.meta.has(n)}).filter(function(e){return["captions","subtitles"].includes(e.kind)})},findTrack:function(e){var t,n=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=captions.getTracks.call(this),o=function(e){return Number((n.captions.meta.get(e)||{}).default)},s=Array.from(r).sort(function(e,t){return o(t)-o(e)});return e.every(function(e){return!(t=s.find(function(t){return t.language===e}))}),t||(i?s[0]:void 0)},getCurrentTrack:function(){return captions.getTracks.call(this)[this.currentTrack]},getLabel:function(e){var t=e;return!is$1.track(t)&&support.textTracks&&this.captions.toggled&&(t=captions.getCurrentTrack.call(this)),is$1.track(t)?is$1.empty(t.label)?is$1.empty(t.language)?i18n.get("enabled",this.config):e.language.toUpperCase():t.label:i18n.get("disabled",this.config)},updateCues:function(e){if(this.supported.ui)if(is$1.element(this.elements.captions))if(is$1.nullOrUndefined(e)||Array.isArray(e)){var t=e;if(!t){var n=captions.getCurrentTrack.call(this);t=Array.from((n||{}).activeCues||[]).map(function(e){return e.getCueAsHTML()}).map(getHTML)}var i=t.map(function(e){return e.trim()}).join("\n");if(i!==this.elements.captions.innerHTML){emptyElement(this.elements.captions);var r=createElement("span",getAttributesFromSelector(this.config.selectors.caption));r.innerHTML=i,this.elements.captions.appendChild(r),triggerEvent.call(this,this.media,"cuechange")}}else this.debug.warn("updateCues: Invalid input",e);else this.debug.warn("No captions element to render to")}},defaults={enabled:!0,title:"",debug:!1,autoplay:!1,autopause:!0,playsinline:!0,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,invertTime:!0,toggleInvert:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,resetOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/3.4.8/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:576,options:[4320,2880,2160,1440,1080,720,576,480,360,240]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:"auto",update:!1},fullscreen:{enabled:!0,fallback:!0,iosNative:!1},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed"],i18n:{restart:"Restart",rewind:"Rewind {seektime}s",play:"Play",pause:"Pause",fastForward:"Forward {seektime}s",seek:"Seek",seekLabel:"{currentTime} of {duration}",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",mute:"Mute",unmute:"Unmute",enableCaptions:"Enable captions",disableCaptions:"Disable captions",download:"Download",enterFullscreen:"Enter fullscreen",exitFullscreen:"Exit fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",menuBack:"Go back to previous menu",speed:"Speed",normal:"Normal",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",disabled:"Disabled",enabled:"Enabled",advertisement:"Ad",qualityBadge:{2160:"4K",1440:"HD",1080:"HD",720:"HD",576:"SD",480:"SD"}},urls:{download:null,vimeo:{sdk:"https://player.vimeo.com/api/player.js",iframe:"https://player.vimeo.com/video/{0}?{1}",api:"https://vimeo.com/api/v2/video/{0}.json"},youtube:{sdk:"https://www.youtube.com/iframe_api",api:"https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet"},googleIMA:{sdk:"https://imasdk.googleapis.com/js/sdkloader/ima3.js"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,fastForward:null,mute:null,volume:null,captions:null,download:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","download","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","adsloaded","adscontentpause","adscontentresume","adstarted","adsmidpoint","adscomplete","adsallcomplete","adsimpression","adsclick"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',fastForward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',download:'[data-plyr="download"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress__buffer",loop:".plyr__progress__loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",caption:".plyr__caption",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{type:"plyr--{0}",provider:"plyr--{0}",video:"plyr__video-wrapper",embed:"plyr__video-embed",embedContainer:"plyr__video-embed__container",poster:"plyr__poster",posterEnabled:"plyr__poster-enabled",ads:"plyr__ads",control:"plyr__control",controlPressed:"plyr__control--pressed",playing:"plyr--playing",paused:"plyr--paused",stopped:"plyr--stopped",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",cues:"plyr__cues",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",noTransition:"plyr--no-transition",display:{time:"plyr__time"},menu:{value:"plyr__menu__value",badge:"plyr__badge",open:"plyr--menu-open"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus",previewThumbnails:{thumbContainer:"plyr__preview-thumb",thumbContainerShown:"plyr__preview-thumb--is-shown",imageContainer:"plyr__preview-thumb__image-container",timeContainer:"plyr__preview-thumb__time-container",scrubbingContainer:"plyr__preview-scrubbing",scrubbingContainerShown:"plyr__preview-scrubbing--is-shown"}},attributes:{embed:{provider:"data-plyr-provider",id:"data-plyr-embed-id"}},keys:{google:null},ads:{enabled:!1,publisherId:"",tagUrl:""},previewThumbnails:{enabled:!1,src:""},vimeo:{byline:!1,portrait:!1,title:!1,speed:!0,transparent:!1},youtube:{noCookie:!1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1}},pip={active:"picture-in-picture",inactive:"inline"},providers={html5:"html5",youtube:"youtube",vimeo:"vimeo"},types={audio:"audio",video:"video"};function getProviderByUrl(e){return/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e)?providers.youtube:/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e)?providers.vimeo:null}var noop=function(){},Console=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];_classCallCheck(this,e),this.enabled=window.console&&t,this.enabled&&this.log("Debugging enabled")}return _createClass(e,[{key:"log",get:function(){return this.enabled?Function.prototype.bind.call(console.log,console):noop}},{key:"warn",get:function(){return this.enabled?Function.prototype.bind.call(console.warn,console):noop}},{key:"error",get:function(){return this.enabled?Function.prototype.bind.call(console.error,console):noop}}]),e}();function onChange(){if(this.enabled){var e=this.player.elements.buttons.fullscreen;is$1.element(e)&&(e.pressed=this.active),triggerEvent.call(this.player,this.target,this.active?"enterfullscreen":"exitfullscreen",!0),browser.isIos||trapFocus.call(this.player,this.target,this.active)}}function toggleFallback(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(t?this.scrollPosition={x:window.scrollX||0,y:window.scrollY||0}:window.scrollTo(this.scrollPosition.x,this.scrollPosition.y),document.body.style.overflow=t?"hidden":"",toggleClass(this.target,this.player.config.classNames.fullscreen.fallback,t),browser.isIos){var n=document.head.querySelector('meta[name="viewport"]'),i="viewport-fit=cover";n||(n=document.createElement("meta")).setAttribute("name","viewport");var r=is$1.string(n.content)&&n.content.includes(i);t?(this.cleanupViewport=!r,r||(n.content+=",".concat(i))):this.cleanupViewport&&(n.content=n.content.split(",").filter(function(e){return e.trim()!==i}).join(",")),setTimeout(function(){return repaint(e.target)},100)}onChange.call(this)}var Fullscreen=function(){function e(t){var n=this;_classCallCheck(this,e),this.player=t,this.prefix=e.prefix,this.property=e.property,this.scrollPosition={x:0,y:0},this.forceFallback="force"===t.config.fullscreen.fallback,on.call(this.player,document,"ms"===this.prefix?"MSFullscreenChange":"".concat(this.prefix,"fullscreenchange"),function(){onChange.call(n)}),on.call(this.player,this.player.elements.container,"dblclick",function(e){is$1.element(n.player.elements.controls)&&n.player.elements.controls.contains(e.target)||n.toggle()}),this.update()}return _createClass(e,[{key:"update",value:function(){var t;this.enabled?(t=this.forceFallback?"Fallback (forced)":e.native?"Native":"Fallback",this.player.debug.log("".concat(t," fullscreen enabled"))):this.player.debug.log("Fullscreen not supported and fallback disabled");toggleClass(this.player.elements.container,this.player.config.classNames.fullscreen.enabled,this.enabled)}},{key:"enter",value:function(){this.enabled&&(browser.isIos&&this.player.config.fullscreen.iosNative?this.target.webkitEnterFullscreen():!e.native||this.forceFallback?toggleFallback.call(this,!0):this.prefix?is$1.empty(this.prefix)||this.target["".concat(this.prefix,"Request").concat(this.property)]():this.target.requestFullscreen())}},{key:"exit",value:function(){if(this.enabled)if(browser.isIos&&this.player.config.fullscreen.iosNative)this.target.webkitExitFullscreen(),this.player.play();else if(!e.native||this.forceFallback)toggleFallback.call(this,!1);else if(this.prefix){if(!is$1.empty(this.prefix)){var t="moz"===this.prefix?"Cancel":"Exit";document["".concat(this.prefix).concat(t).concat(this.property)]()}}else(document.cancelFullScreen||document.exitFullscreen).call(document)}},{key:"toggle",value:function(){this.active?this.exit():this.enter()}},{key:"usingNative",get:function(){return e.native&&!this.forceFallback}},{key:"enabled",get:function(){return(e.native||this.player.config.fullscreen.fallback)&&this.player.config.fullscreen.enabled&&this.player.supported.ui&&this.player.isVideo}},{key:"active",get:function(){return!!this.enabled&&(!e.native||this.forceFallback?hasClass(this.target,this.player.config.classNames.fullscreen.fallback):(this.prefix?document["".concat(this.prefix).concat(this.property,"Element")]:document.fullscreenElement)===this.target)}},{key:"target",get:function(){return browser.isIos&&this.player.config.fullscreen.iosNative?this.player.media:this.player.elements.container}}],[{key:"native",get:function(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)}},{key:"prefix",get:function(){if(is$1.function(document.exitFullscreen))return"";var e="";return["webkit","moz","ms"].some(function(t){return!(!is$1.function(document["".concat(t,"ExitFullscreen")])&&!is$1.function(document["".concat(t,"CancelFullScreen")]))&&(e=t,!0)}),e}},{key:"property",get:function(){return"moz"===this.prefix?"FullScreen":"Fullscreen"}}]),e}(),_mathSign=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1};function loadImage(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return new Promise(function(n,i){var r=new Image,o=function(){delete r.onload,delete r.onerror,(r.naturalWidth>=t?n:i)(r)};Object.assign(r,{onload:o,onerror:o,src:e})})}_export(_export.S,"Math",{sign:_mathSign});var ui={addStyleHook:function(){toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){var e=this;if(this.listeners.media(),!this.supported.ui)return this.debug.warn("Basic support only for ".concat(this.provider," ").concat(this.type)),void ui.toggleNativeControls.call(this,!0);is$1.element(this.elements.controls)||(controls.inject.call(this),this.listeners.controls()),ui.toggleNativeControls.call(this),this.isHTML5&&captions.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.quality=null,controls.updateVolume.call(this),controls.timeUpdate.call(this),ui.checkPlaying.call(this),toggleClass(this.elements.container,this.config.classNames.pip.supported,support.pip&&this.isHTML5&&this.isVideo),toggleClass(this.elements.container,this.config.classNames.airplay.supported,support.airplay&&this.isHTML5),toggleClass(this.elements.container,this.config.classNames.isIos,browser.isIos),toggleClass(this.elements.container,this.config.classNames.isTouch,this.touch),this.ready=!0,setTimeout(function(){triggerEvent.call(e,e.media,"ready")},0),ui.setTitle.call(this),this.poster&&ui.setPoster.call(this,this.poster,!1).catch(function(){}),this.config.duration&&controls.durationUpdate.call(this)},setTitle:function(){var e=i18n.get("play",this.config);if(is$1.string(this.config.title)&&!is$1.empty(this.config.title)&&(e+=", ".concat(this.config.title)),Array.from(this.elements.buttons.play||[]).forEach(function(t){t.setAttribute("aria-label",e)}),this.isEmbed){var t=getElement.call(this,"iframe");if(!is$1.element(t))return;var n=is$1.empty(this.config.title)?"video":this.config.title,i=i18n.get("frameTitle",this.config);t.setAttribute("title",i.replace("{title}",n))}},togglePoster:function(e){toggleClass(this.elements.container,this.config.classNames.posterEnabled,e)},setPoster:function(e){var t=this;return arguments.length>1&&void 0!==arguments[1]&&!arguments[1]||!this.poster?(this.media.setAttribute("poster",e),ready.call(this).then(function(){return loadImage(e)}).catch(function(n){throw e===t.poster&&ui.togglePoster.call(t,!1),n}).then(function(){if(e!==t.poster)throw new Error("setPoster cancelled by later call to setPoster")}).then(function(){return Object.assign(t.elements.poster.style,{backgroundImage:"url('".concat(e,"')"),backgroundSize:""}),ui.togglePoster.call(t,!0),e})):Promise.reject(new Error("Poster already set"))},checkPlaying:function(e){var t=this;toggleClass(this.elements.container,this.config.classNames.playing,this.playing),toggleClass(this.elements.container,this.config.classNames.paused,this.paused),toggleClass(this.elements.container,this.config.classNames.stopped,this.stopped),Array.from(this.elements.buttons.play||[]).forEach(function(e){e.pressed=t.playing}),is$1.event(e)&&"timeupdate"===e.type||ui.toggleControls.call(this)},checkLoading:function(e){var t=this;this.loading=["stalled","waiting"].includes(e.type),clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){toggleClass(t.elements.container,t.config.classNames.loading,t.loading),ui.toggleControls.call(t)},this.loading?250:0)},toggleControls:function(e){var t=this.elements.controls;if(t&&this.config.hideControls){var n=this.touch&&this.lastSeekTime+2e3>Date.now();this.toggleControls(Boolean(e||this.loading||this.paused||t.pressed||t.hover||n))}}};function setAspectRatio(e){var t=e;is$1.string(t)||is$1.nullOrUndefined(this.embed)||(t=this.embed.ratio),is$1.string(t)||(t=this.config.ratio);var n=_slicedToArray(t.split(":").map(Number),2),i=100/n[0]*n[1];if(this.elements.wrapper.style.paddingBottom="".concat(i,"%"),this.isVimeo&&this.supported.ui){var r=(240-i)/4.8;this.media.style.transform="translateY(-".concat(r,"%)")}return{padding:i,ratio:t}}var Listeners=function(){function e(t){_classCallCheck(this,e),this.player=t,this.lastKey=null,this.focusTimer=null,this.lastKeyDown=null,this.handleKey=this.handleKey.bind(this),this.toggleMenu=this.toggleMenu.bind(this),this.setTabFocus=this.setTabFocus.bind(this),this.firstTouch=this.firstTouch.bind(this)}return _createClass(e,[{key:"handleKey",value:function(e){var t=this.player,n=t.elements,i=e.keyCode?e.keyCode:e.which,r="keydown"===e.type,o=r&&i===this.lastKey;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)&&is$1.number(i)){if(r){var s=document.activeElement;if(is$1.element(s)){var a=t.config.selectors.editable;if(s!==n.inputs.seek&&matches(s,a))return;if(32===e.which&&matches(s,'button, [role^="menuitem"]'))return}switch([32,37,38,39,40,48,49,50,51,52,53,54,56,57,67,70,73,75,76,77,79].includes(i)&&(e.preventDefault(),e.stopPropagation()),i){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:o||(t.currentTime=t.duration/10*(i-48));break;case 32:case 75:o||t.togglePlay();break;case 38:t.increaseVolume(.1);break;case 40:t.decreaseVolume(.1);break;case 77:o||(t.muted=!t.muted);break;case 39:t.forward();break;case 37:t.rewind();break;case 70:t.fullscreen.toggle();break;case 67:o||t.toggleCaptions();break;case 76:t.loop=!t.loop}27===i&&!t.fullscreen.usingNative&&t.fullscreen.active&&t.fullscreen.toggle(),this.lastKey=i}else this.lastKey=null}}},{key:"toggleMenu",value:function(e){controls.toggleMenu.call(this.player,e)}},{key:"firstTouch",value:function(){var e=this.player,t=e.elements;e.touch=!0,toggleClass(t.container,e.config.classNames.isTouch,!0)}},{key:"setTabFocus",value:function(e){var t=this.player,n=t.elements;if(clearTimeout(this.focusTimer),"keydown"!==e.type||9===e.which){"keydown"===e.type&&(this.lastKeyDown=e.timeStamp);var i,r=e.timeStamp-this.lastKeyDown<=20;if("focus"!==e.type||r)i=t.config.classNames.tabFocus,toggleClass(getElements.call(t,".".concat(i)),i,!1),this.focusTimer=setTimeout(function(){var e=document.activeElement;n.container.contains(e)&&toggleClass(document.activeElement,t.config.classNames.tabFocus,!0)},10)}}},{key:"global",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.player;t.config.keyboard.global&&toggleListener.call(t,window,"keydown keyup",this.handleKey,e,!1),toggleListener.call(t,document.body,"click",this.toggleMenu,e),once.call(t,document.body,"touchstart",this.firstTouch),toggleListener.call(t,document.body,"keydown focus blur",this.setTabFocus,e,!1,!0)}},{key:"container",value:function(){var e=this.player,t=e.config,n=e.elements,i=e.timers;!t.keyboard.global&&t.keyboard.focused&&on.call(e,n.container,"keydown keyup",this.handleKey,!1),on.call(e,n.container,"mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",function(t){var r=n.controls;r&&"enterfullscreen"===t.type&&(r.pressed=!1,r.hover=!1);var o=0;["touchstart","touchmove","mousemove"].includes(t.type)&&(ui.toggleControls.call(e,!0),o=e.touch?3e3:2e3),clearTimeout(i.controls),i.controls=setTimeout(function(){return ui.toggleControls.call(e,!1)},o)});var r=function(t){if(!t)return setAspectRatio.call(e);var i=n.container.getBoundingClientRect(),r=i.width,o=i.height;return setAspectRatio.call(e,"".concat(r,":").concat(o))},o=function(){window.clearTimeout(i.resized),i.resized=window.setTimeout(r,50)};on.call(e,n.container,"enterfullscreen exitfullscreen",function(t){var i=e.fullscreen,s=i.target,a=i.usingNative;if(e.isEmbed&&s===n.container){var l="enterfullscreen"===t.type,c=r(l);c.padding;!function(t,n,i){if(e.isVimeo){var r=e.elements.wrapper.firstChild,o=_slicedToArray(t.split(":").map(Number),2)[1],s=_slicedToArray(e.embed.ratio.split(":").map(Number),2),a=s[0],l=s[1];r.style.maxWidth=i?"".concat(o/l*a,"px"):null,r.style.margin=i?"0 auto":null}}(c.ratio,0,l),a||(l?on.call(e,window,"resize",o):off.call(e,window,"resize",o))}})}},{key:"media",value:function(){var e=this,t=this.player,n=t.elements;if(on.call(t,t.media,"timeupdate seeking seeked",function(e){return controls.timeUpdate.call(t,e)}),on.call(t,t.media,"durationchange loadeddata loadedmetadata",function(e){return controls.durationUpdate.call(t,e)}),on.call(t,t.media,"canplay loadeddata",function(){toggleHidden(n.volume,!t.hasAudio),toggleHidden(n.buttons.mute,!t.hasAudio)}),on.call(t,t.media,"ended",function(){t.isHTML5&&t.isVideo&&t.config.resetOnEnd&&t.restart()}),on.call(t,t.media,"progress playing seeking seeked",function(e){return controls.updateProgress.call(t,e)}),on.call(t,t.media,"volumechange",function(e){return controls.updateVolume.call(t,e)}),on.call(t,t.media,"playing play pause ended emptied timeupdate",function(e){return ui.checkPlaying.call(t,e)}),on.call(t,t.media,"waiting canplay seeked playing",function(e){return ui.checkLoading.call(t,e)}),on.call(t,t.media,"playing",function(){t.ads&&t.ads.enabled&&!t.ads.initialized&&t.ads.managerPromise.then(function(){return t.ads.play()}).catch(function(){return t.play()})}),t.supported.ui&&t.config.clickToPlay&&!t.isAudio){var i=getElement.call(t,".".concat(t.config.classNames.video));if(!is$1.element(i))return;on.call(t,n.container,"click",function(r){([n.container,i].includes(r.target)||i.contains(r.target))&&(t.touch&&t.config.hideControls||(t.ended?(e.proxy(r,t.restart,"restart"),e.proxy(r,t.play,"play")):e.proxy(r,t.togglePlay,"play")))})}t.supported.ui&&t.config.disableContextMenu&&on.call(t,n.wrapper,"contextmenu",function(e){e.preventDefault()},!1),on.call(t,t.media,"volumechange",function(){t.storage.set({volume:t.volume,muted:t.muted})}),on.call(t,t.media,"ratechange",function(){controls.updateSetting.call(t,"speed"),t.storage.set({speed:t.speed})}),on.call(t,t.media,"qualitychange",function(e){controls.updateSetting.call(t,"quality",null,e.detail.quality)}),on.call(t,t.media,"ready qualitychange",function(){controls.setDownloadLink.call(t)});var r=t.config.events.concat(["keyup","keydown"]).join(" ");on.call(t,t.media,r,function(e){var i=e.detail,r=void 0===i?{}:i;"error"===e.type&&(r=t.media.error),triggerEvent.call(t,n.container,e.type,!0,r)})}},{key:"proxy",value:function(e,t,n){var i=this.player,r=i.config.listeners[n],o=!0;is$1.function(r)&&(o=r.call(i,e)),o&&is$1.function(t)&&t.call(i,e)}},{key:"bind",value:function(e,t,n,i){var r=this,o=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=this.player,a=s.config.listeners[i],l=is$1.function(a);on.call(s,e,t,function(e){return r.proxy(e,n,i)},o&&!l)}},{key:"controls",value:function(){var e=this,t=this.player,n=t.elements,i=browser.isIE?"change":"input";if(n.buttons.play&&Array.from(n.buttons.play).forEach(function(n){e.bind(n,"click",t.togglePlay,"play")}),this.bind(n.buttons.restart,"click",t.restart,"restart"),this.bind(n.buttons.rewind,"click",t.rewind,"rewind"),this.bind(n.buttons.fastForward,"click",t.forward,"fastForward"),this.bind(n.buttons.mute,"click",function(){t.muted=!t.muted},"mute"),this.bind(n.buttons.captions,"click",function(){return t.toggleCaptions()}),this.bind(n.buttons.download,"click",function(){triggerEvent.call(t,t.media,"download")},"download"),this.bind(n.buttons.fullscreen,"click",function(){t.fullscreen.toggle()},"fullscreen"),this.bind(n.buttons.pip,"click",function(){t.pip="toggle"},"pip"),this.bind(n.buttons.airplay,"click",t.airplay,"airplay"),this.bind(n.buttons.settings,"click",function(e){e.stopPropagation(),controls.toggleMenu.call(t,e)}),this.bind(n.buttons.settings,"keyup",function(e){var n=e.which;[13,32].includes(n)&&(13!==n?(e.preventDefault(),e.stopPropagation(),controls.toggleMenu.call(t,e)):controls.focusFirstMenuItem.call(t,null,!0))},null,!1),this.bind(n.settings.menu,"keydown",function(e){27===e.which&&controls.toggleMenu.call(t,e)}),this.bind(n.inputs.seek,"mousedown mousemove",function(e){var t=n.progress.getBoundingClientRect(),i=100/t.width*(e.pageX-t.left);e.currentTarget.setAttribute("seek-value",i)}),this.bind(n.inputs.seek,"mousedown mouseup keydown keyup touchstart touchend",function(e){var n=e.currentTarget,i=e.keyCode?e.keyCode:e.which;if(!is$1.keyboardEvent(e)||39===i||37===i){t.lastSeekTime=Date.now();var r=n.hasAttribute("play-on-seeked"),o=["mouseup","touchend","keyup"].includes(e.type);r&&o?(n.removeAttribute("play-on-seeked"),t.play()):!o&&t.playing&&(n.setAttribute("play-on-seeked",""),t.pause())}}),browser.isIos){var r=getElements.call(t,'input[type="range"]');Array.from(r).forEach(function(t){return e.bind(t,i,function(e){return repaint(e.target)})})}this.bind(n.inputs.seek,i,function(e){var n=e.currentTarget,i=n.getAttribute("seek-value");is$1.empty(i)&&(i=n.value),n.removeAttribute("seek-value"),t.currentTime=i/n.max*t.duration},"seek"),this.bind(n.progress,"mouseenter mouseleave mousemove",function(e){return controls.updateSeekTooltip.call(t,e)}),this.bind(n.progress,"mousemove touchmove",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startMove(e)}),this.bind(n.progress,"mouseleave click",function(){var e=t.previewThumbnails;e&&e.loaded&&e.endMove(!1,!0)}),this.bind(n.progress,"mousedown touchstart",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.startScrubbing(e)}),this.bind(n.progress,"mouseup touchend",function(e){var n=t.previewThumbnails;n&&n.loaded&&n.endScrubbing(e)}),browser.isWebkit&&Array.from(getElements.call(t,'input[type="range"]')).forEach(function(n){e.bind(n,"input",function(e){return controls.updateRangeFill.call(t,e.target)})}),t.config.toggleInvert&&!is$1.element(n.display.duration)&&this.bind(n.display.currentTime,"click",function(){0!==t.currentTime&&(t.config.invertTime=!t.config.invertTime,controls.timeUpdate.call(t))}),this.bind(n.inputs.volume,i,function(e){t.volume=e.target.value},"volume"),this.bind(n.controls,"mouseenter mouseleave",function(e){n.controls.hover=!t.touch&&"mouseenter"===e.type}),this.bind(n.controls,"mousedown mouseup touchstart touchend touchcancel",function(e){n.controls.pressed=["mousedown","touchstart"].includes(e.type)}),this.bind(n.controls,"focusin",function(){var n=t.config,i=t.elements,r=t.timers;toggleClass(i.controls,n.classNames.noTransition,!0),ui.toggleControls.call(t,!0),setTimeout(function(){toggleClass(i.controls,n.classNames.noTransition,!1)},0);var o=e.touch?3e3:4e3;clearTimeout(r.controls),r.controls=setTimeout(function(){return ui.toggleControls.call(t,!1)},o)}),this.bind(n.inputs.volume,"wheel",function(e){var n=e.webkitDirectionInvertedFromDevice,i=_slicedToArray([e.deltaX,-e.deltaY].map(function(e){return n?-e:e}),2),r=i[0],o=i[1],s=Math.sign(Math.abs(r)>Math.abs(o)?r:o);t.increaseVolume(s/50);var a=t.media.volume;(1===s&&a<1||-1===s&&a>0)&&e.preventDefault()},"volume",!1)}}]),e}(),dP$3=_objectDp.f,FProto=Function.prototype,nameRE=/^\s*function ([^ (]*)/,NAME$1="name";NAME$1 in FProto||_descriptors&&dP$3(FProto,NAME$1,{configurable:!0,get:function(){try{return(""+this).match(nameRE)[1]}catch(e){return""}}}),_fixReWks("match",1,function(e,t,n,i){return[function(n){var i=e(this),r=null==n?void 0:n[t];return void 0!==r?r.call(n,i):new RegExp(n)[t](String(i))},function(e){var t=i(n,e,this);if(t.done)return t.value;var r=_anObject(e),o=String(this);if(!r.global)return _regexpExecAbstract(r,o);var s=r.unicode;r.lastIndex=0;for(var a,l=[],c=0;null!==(a=_regexpExecAbstract(r,o));){var u=String(a[0]);l[c]=u,""===u&&(r.lastIndex=_advanceStringIndex(o,_toLength(r.lastIndex),s)),c++}return 0===c?null:l}]});var loadjs_umd=createCommonjsModule(function(e,t){e.exports=function(){var e=function(){},t={},n={},i={};function r(e,t){if(e){var r=i[e];if(n[e]=t,r)for(;r.length;)r[0](e,t),r.splice(0,1)}}function o(t,n){t.call&&(t={success:t}),n.length?(t.error||e)(n):(t.success||e)(t)}function s(t,n,i,r){var o,a,l=document,c=i.async,u=(i.numRetries||0)+1,d=i.before||e,h=t.replace(/^(css|img)!/,"");r=r||0,/(^css!|\.css$)/.test(t)?(o=!0,(a=l.createElement("link")).rel="stylesheet",a.href=h):/(^img!|\.(png|gif|jpg|svg)$)/.test(t)?(a=l.createElement("img")).src=h:((a=l.createElement("script")).src=t,a.async=void 0===c||c),a.onload=a.onerror=a.onbeforeload=function(e){var l=e.type[0];if(o&&"hideFocus"in a)try{a.sheet.cssText.length||(l="e")}catch(e){18!=e.code&&(l="e")}if("e"==l&&(r+=1)<u)return s(t,n,i,r);n(t,l,e.defaultPrevented)},!1!==d(t,a)&&l.head.appendChild(a)}function a(e,n,i){var a,l;if(n&&n.trim&&(a=n),l=(a?i:n)||{},a){if(a in t)throw"LoadJS";t[a]=!0}!function(e,t,n){var i,r,o=(e=e.push?e:[e]).length,a=o,l=[];for(i=function(e,n,i){if("e"==n&&l.push(e),"b"==n){if(!i)return;l.push(e)}--o||t(l)},r=0;r<a;r++)s(e[r],i,n)}(e,function(e){o(l,e),r(a,e)},l)}return a.ready=function(e,t){return function(e,t){e=e.push?e:[e];var r,o,s,a=[],l=e.length,c=l;for(r=function(e,n){n.length&&a.push(e),--c||t(a)};l--;)o=e[l],(s=n[o])?r(o,s):(i[o]=i[o]||[]).push(r)}(e,function(e){o(t,e)}),a},a.done=function(e){r(e,[])},a.reset=function(){t={},n={},i={}},a.isDefined=function(e){return e in t},a}()});function loadScript(e){return new Promise(function(t,n){loadjs_umd(e,{success:t,error:n})})}function parseId(e){if(is$1.empty(e))return null;if(is$1.number(Number(e)))return e;return e.match(/^.*(vimeo.com\/|video\/)(\d+).*/)?RegExp.$2:e}function assurePlaybackState(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,triggerEvent.call(this,this.media,e?"play":"pause"))}var vimeo={setup:function(){var e=this;toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),setAspectRatio.call(this),is$1.object(window.Vimeo)?vimeo.ready.call(this):loadScript(this.config.urls.vimeo.sdk).then(function(){vimeo.ready.call(e)}).catch(function(t){e.debug.warn("Vimeo API failed to load",t)})},ready:function(){var e=this,t=this,n=t.config.vimeo,i=buildUrlParams(extend({},{loop:t.config.loop.active,autoplay:t.autoplay,muted:t.muted,gesture:"media",playsinline:!this.config.fullscreen.iosNative},n)),r=t.media.getAttribute("src");is$1.empty(r)&&(r=t.media.getAttribute(t.config.attributes.embed.id));var o=parseId(r),s=createElement("iframe"),a=format(t.config.urls.vimeo.iframe,o,i);s.setAttribute("src",a),s.setAttribute("allowfullscreen",""),s.setAttribute("allowtransparency",""),s.setAttribute("allow","autoplay");var l=createElement("div",{poster:t.poster,class:t.config.classNames.embedContainer});l.appendChild(s),t.media=replaceElement(l,t.media),fetch(format(t.config.urls.vimeo.api,o),"json").then(function(e){if(!is$1.empty(e)){var n=new URL(e[0].thumbnail_large);n.pathname="".concat(n.pathname.split("_")[0],".jpg"),ui.setPoster.call(t,n.href).catch(function(){})}}),t.embed=new window.Vimeo.Player(s,{autopause:t.config.autopause,muted:t.muted}),t.media.paused=!0,t.media.currentTime=0,t.supported.ui&&t.embed.disableTextTrack(),t.media.play=function(){return assurePlaybackState.call(t,!0),t.embed.play()},t.media.pause=function(){return assurePlaybackState.call(t,!1),t.embed.pause()},t.media.stop=function(){t.pause(),t.currentTime=0};var c=t.media.currentTime;Object.defineProperty(t.media,"currentTime",{get:function(){return c},set:function(e){var n=t.embed,i=t.media,r=t.paused,o=t.volume,s=r&&!n.hasPlayed;i.seeking=!0,triggerEvent.call(t,i,"seeking"),Promise.resolve(s&&n.setVolume(0)).then(function(){return n.setCurrentTime(e)}).then(function(){return s&&n.pause()}).then(function(){return s&&n.setVolume(o)}).catch(function(){})}});var u=t.config.speed.selected;Object.defineProperty(t.media,"playbackRate",{get:function(){return u},set:function(e){t.embed.setPlaybackRate(e).then(function(){u=e,triggerEvent.call(t,t.media,"ratechange")}).catch(function(e){"Error"===e.name&&controls.setSpeedMenu.call(t,[])})}});var d=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return d},set:function(e){t.embed.setVolume(e).then(function(){d=e,triggerEvent.call(t,t.media,"volumechange")})}});var h=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return h},set:function(e){var n=!!is$1.boolean(e)&&e;t.embed.setVolume(n?0:t.config.volume).then(function(){h=n,triggerEvent.call(t,t.media,"volumechange")})}});var p,f=t.config.loop;Object.defineProperty(t.media,"loop",{get:function(){return f},set:function(e){var n=is$1.boolean(e)?e:t.config.loop.active;t.embed.setLoop(n).then(function(){f=n})}}),t.embed.getVideoUrl().then(function(e){p=e,controls.setDownloadLink.call(t)}).catch(function(t){e.debug.warn(t)}),Object.defineProperty(t.media,"currentSrc",{get:function(){return p}}),Object.defineProperty(t.media,"ended",{get:function(){return t.currentTime===t.duration}}),Promise.all([t.embed.getVideoWidth(),t.embed.getVideoHeight()]).then(function(n){var i=_slicedToArray(n,2),r=i[0],o=i[1];t.embed.ratio="".concat(r,":").concat(o),setAspectRatio.call(e,t.embed.ratio)}),t.embed.setAutopause(t.config.autopause).then(function(e){t.config.autopause=e}),t.embed.getVideoTitle().then(function(n){t.config.title=n,ui.setTitle.call(e)}),t.embed.getCurrentTime().then(function(e){c=e,triggerEvent.call(t,t.media,"timeupdate")}),t.embed.getDuration().then(function(e){t.media.duration=e,triggerEvent.call(t,t.media,"durationchange")}),t.embed.getTextTracks().then(function(e){t.media.textTracks=e,captions.setup.call(t)}),t.embed.on("cuechange",function(e){var n=e.cues,i=(void 0===n?[]:n).map(function(e){return stripHTML(e.text)});captions.updateCues.call(t,i)}),t.embed.on("loaded",function(){(t.embed.getPaused().then(function(e){assurePlaybackState.call(t,!e),e||triggerEvent.call(t,t.media,"playing")}),is$1.element(t.embed.element)&&t.supported.ui)&&t.embed.element.setAttribute("tabindex",-1)}),t.embed.on("play",function(){assurePlaybackState.call(t,!0),triggerEvent.call(t,t.media,"playing")}),t.embed.on("pause",function(){assurePlaybackState.call(t,!1)}),t.embed.on("timeupdate",function(e){t.media.seeking=!1,c=e.seconds,triggerEvent.call(t,t.media,"timeupdate")}),t.embed.on("progress",function(e){t.media.buffered=e.percent,triggerEvent.call(t,t.media,"progress"),1===parseInt(e.percent,10)&&triggerEvent.call(t,t.media,"canplaythrough"),t.embed.getDuration().then(function(e){e!==t.media.duration&&(t.media.duration=e,triggerEvent.call(t,t.media,"durationchange"))})}),t.embed.on("seeked",function(){t.media.seeking=!1,triggerEvent.call(t,t.media,"seeked")}),t.embed.on("ended",function(){t.media.paused=!0,triggerEvent.call(t,t.media,"ended")}),t.embed.on("error",function(e){t.media.error=e,triggerEvent.call(t,t.media,"error")}),setTimeout(function(){return ui.build.call(t)},0)}};function parseId$1(e){if(is$1.empty(e))return null;return e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/)?RegExp.$2:e}function assurePlaybackState$1(e){e&&!this.embed.hasPlayed&&(this.embed.hasPlayed=!0),this.media.paused===e&&(this.media.paused=!e,triggerEvent.call(this,this.media,e?"play":"pause"))}var youtube={setup:function(){var e=this;toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),setAspectRatio.call(this),is$1.object(window.YT)&&is$1.function(window.YT.Player)?youtube.ready.call(this):(loadScript(this.config.urls.youtube.sdk).catch(function(t){e.debug.warn("YouTube API failed to load",t)}),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){youtube.ready.call(e)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},getTitle:function(e){var t=this;if(is$1.function(this.embed.getVideoData)){var n=this.embed.getVideoData().title;if(is$1.empty(n))return this.config.title=n,void ui.setTitle.call(this)}var i=this.config.keys.google;is$1.string(i)&&!is$1.empty(i)&&fetch(format(this.config.urls.youtube.api,e,i)).then(function(e){is$1.object(e)&&(t.config.title=e.items[0].snippet.title,ui.setTitle.call(t))}).catch(function(){})},ready:function(){var e=this,t=e.media.getAttribute("id");if(is$1.empty(t)||!t.startsWith("youtube-")){var n=e.media.getAttribute("src");is$1.empty(n)&&(n=e.media.getAttribute(this.config.attributes.embed.id));var i=parseId$1(n),r=generateId(e.provider),o=createElement("div",{id:r,poster:e.poster});e.media=replaceElement(o,e.media);var s=function(e){return"https://img.youtube.com/vi/".concat(i,"/").concat(e,"default.jpg")};loadImage(s("maxres"),121).catch(function(){return loadImage(s("sd"),121)}).catch(function(){return loadImage(s("hq"))}).then(function(t){return ui.setPoster.call(e,t.src)}).then(function(t){t.includes("maxres")||(e.elements.poster.style.backgroundSize="cover")}).catch(function(){});var a=e.config.youtube;e.embed=new window.YT.Player(r,{videoId:i,host:a.noCookie?"https://www.youtube-nocookie.com":void 0,playerVars:extend({},{autoplay:e.config.autoplay?1:0,hl:e.config.hl,controls:e.supported.ui?0:1,disablekb:1,playsinline:e.config.fullscreen.iosNative?0:1,cc_load_policy:e.captions.active?1:0,cc_lang_pref:e.config.captions.language,widget_referrer:window?window.location.href:null},a),events:{onError:function(t){if(!e.media.error){var n=t.data,i={2:"The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.",5:"The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",100:"The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.",101:"The owner of the requested video does not allow it to be played in embedded players.",150:"The owner of the requested video does not allow it to be played in embedded players."}[n]||"An unknown error occured";e.media.error={code:n,message:i},triggerEvent.call(e,e.media,"error")}},onPlaybackRateChange:function(t){var n=t.target;e.media.playbackRate=n.getPlaybackRate(),triggerEvent.call(e,e.media,"ratechange")},onReady:function(t){if(!is$1.function(e.media.play)){var n=t.target;youtube.getTitle.call(e,i),e.media.play=function(){assurePlaybackState$1.call(e,!0),n.playVideo()},e.media.pause=function(){assurePlaybackState$1.call(e,!1),n.pauseVideo()},e.media.stop=function(){n.stopVideo()},e.media.duration=n.getDuration(),e.media.paused=!0,e.media.currentTime=0,Object.defineProperty(e.media,"currentTime",{get:function(){return Number(n.getCurrentTime())},set:function(t){e.paused&&!e.embed.hasPlayed&&e.embed.mute(),e.media.seeking=!0,triggerEvent.call(e,e.media,"seeking"),n.seekTo(t)}}),Object.defineProperty(e.media,"playbackRate",{get:function(){return n.getPlaybackRate()},set:function(e){n.setPlaybackRate(e)}});var r=e.config.volume;Object.defineProperty(e.media,"volume",{get:function(){return r},set:function(t){r=t,n.setVolume(100*r),triggerEvent.call(e,e.media,"volumechange")}});var o=e.config.muted;Object.defineProperty(e.media,"muted",{get:function(){return o},set:function(t){var i=is$1.boolean(t)?t:o;o=i,n[i?"mute":"unMute"](),triggerEvent.call(e,e.media,"volumechange")}}),Object.defineProperty(e.media,"currentSrc",{get:function(){return n.getVideoUrl()}}),Object.defineProperty(e.media,"ended",{get:function(){return e.currentTime===e.duration}}),e.options.speed=n.getAvailablePlaybackRates(),e.supported.ui&&e.media.setAttribute("tabindex",-1),triggerEvent.call(e,e.media,"timeupdate"),triggerEvent.call(e,e.media,"durationchange"),clearInterval(e.timers.buffering),e.timers.buffering=setInterval(function(){e.media.buffered=n.getVideoLoadedFraction(),(null===e.media.lastBuffered||e.media.lastBuffered<e.media.buffered)&&triggerEvent.call(e,e.media,"progress"),e.media.lastBuffered=e.media.buffered,1===e.media.buffered&&(clearInterval(e.timers.buffering),triggerEvent.call(e,e.media,"canplaythrough"))},200),setTimeout(function(){return ui.build.call(e)},50)}},onStateChange:function(t){var n=t.target;switch(clearInterval(e.timers.playing),e.media.seeking&&[1,2].includes(t.data)&&(e.media.seeking=!1,triggerEvent.call(e,e.media,"seeked")),t.data){case-1:triggerEvent.call(e,e.media,"timeupdate"),e.media.buffered=n.getVideoLoadedFraction(),triggerEvent.call(e,e.media,"progress");break;case 0:assurePlaybackState$1.call(e,!1),e.media.loop?(n.stopVideo(),n.playVideo()):triggerEvent.call(e,e.media,"ended");break;case 1:e.media.paused&&!e.embed.hasPlayed?e.media.pause():(assurePlaybackState$1.call(e,!0),triggerEvent.call(e,e.media,"playing"),e.timers.playing=setInterval(function(){triggerEvent.call(e,e.media,"timeupdate")},50),e.media.duration!==n.getDuration()&&(e.media.duration=n.getDuration(),triggerEvent.call(e,e.media,"durationchange")));break;case 2:e.muted||e.embed.unMute(),assurePlaybackState$1.call(e,!1)}triggerEvent.call(e,e.elements.container,"statechange",!1,{code:t.data})}}})}}},media={setup:function(){this.media?(toggleClass(this.elements.container,this.config.classNames.type.replace("{0}",this.type),!0),toggleClass(this.elements.container,this.config.classNames.provider.replace("{0}",this.provider),!0),this.isEmbed&&toggleClass(this.elements.container,this.config.classNames.type.replace("{0}","video"),!0),this.isVideo&&(this.elements.wrapper=createElement("div",{class:this.config.classNames.video}),wrap(this.media,this.elements.wrapper),this.elements.poster=createElement("div",{class:this.config.classNames.poster}),this.elements.wrapper.appendChild(this.elements.poster)),this.isHTML5?html5.extend.call(this):this.isYouTube?youtube.setup.call(this):this.isVimeo&&vimeo.setup.call(this)):this.debug.warn("No media element found!")}},Ads=function(){function e(t){var n=this;_classCallCheck(this,e),this.player=t,this.config=t.config.ads,this.playing=!1,this.initialized=!1,this.elements={container:null,displayContainer:null},this.manager=null,this.loader=null,this.cuePoints=null,this.events={},this.safetyTimer=null,this.countdownTimer=null,this.managerPromise=new Promise(function(e,t){n.on("loaded",e),n.on("error",t)}),this.load()}return _createClass(e,[{key:"load",value:function(){var e=this;this.enabled&&(is$1.object(window.google)&&is$1.object(window.google.ima)?this.ready():loadScript(this.player.config.urls.googleIMA.sdk).then(function(){e.ready()}).catch(function(){e.trigger("error",new Error("Google IMA SDK failed to load"))}))}},{key:"ready",value:function(){var e=this;this.startSafetyTimer(12e3,"ready()"),this.managerPromise.then(function(){e.clearSafetyTimer("onAdsManagerLoaded()")}),this.listeners(),this.setupIMA()}},{key:"setupIMA",value:function(){this.elements.container=createElement("div",{class:this.player.config.classNames.ads}),this.player.elements.container.appendChild(this.elements.container),google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED),google.ima.settings.setLocale(this.player.config.ads.language),this.elements.displayContainer=new google.ima.AdDisplayContainer(this.elements.container),this.requestAds()}},{key:"requestAds",value:function(){var e=this,t=this.player.elements.container;try{this.loader=new google.ima.AdsLoader(this.elements.displayContainer),this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){return e.onAdsManagerLoaded(t)},!1),this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(t){return e.onAdError(t)},!1);var n=new google.ima.AdsRequest;n.adTagUrl=this.tagUrl,n.linearAdSlotWidth=t.offsetWidth,n.linearAdSlotHeight=t.offsetHeight,n.nonLinearAdSlotWidth=t.offsetWidth,n.nonLinearAdSlotHeight=t.offsetHeight,n.forceNonLinearFullSlot=!1,n.setAdWillPlayMuted(!this.player.muted),this.loader.requestAds(n)}catch(e){this.onAdError(e)}}},{key:"pollCountdown",value:function(){var e=this;if(!(arguments.length>0&&void 0!==arguments[0]&&arguments[0]))return clearInterval(this.countdownTimer),void this.elements.container.removeAttribute("data-badge-text");this.countdownTimer=setInterval(function(){var t=formatTime(Math.max(e.manager.getRemainingTime(),0)),n="".concat(i18n.get("advertisement",e.player.config)," - ").concat(t);e.elements.container.setAttribute("data-badge-text",n)},100)}},{key:"onAdsManagerLoaded",value:function(e){var t=this;if(this.enabled){var n=new google.ima.AdsRenderingSettings;n.restoreCustomPlaybackStateOnAdBreakComplete=!0,n.enablePreloading=!0,this.manager=e.getAdsManager(this.player,n),this.cuePoints=this.manager.getCuePoints(),is$1.empty(this.cuePoints)||this.cuePoints.forEach(function(e){if(0!==e&&-1!==e&&e<t.player.duration){var n=t.player.elements.progress;if(is$1.element(n)){var i=100/t.player.duration*e,r=createElement("span",{class:t.player.config.classNames.cues});r.style.left="".concat(i.toString(),"%"),n.appendChild(r)}}}),this.manager.setVolume(this.player.volume),this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR,function(e){return t.onAdError(e)}),Object.keys(google.ima.AdEvent.Type).forEach(function(e){t.manager.addEventListener(google.ima.AdEvent.Type[e],function(e){return t.onAdEvent(e)})}),this.trigger("loaded")}}},{key:"onAdEvent",value:function(e){var t=this,n=this.player.elements.container,i=e.getAd(),r=e.getAdData(),o=function(e){var n="ads".concat(e.replace(/_/g,"").toLowerCase());triggerEvent.call(t.player,t.player.media,n)};switch(e.type){case google.ima.AdEvent.Type.LOADED:this.trigger("loaded"),o(e.type),this.pollCountdown(!0),i.isLinear()||(i.width=n.offsetWidth,i.height=n.offsetHeight);break;case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:o(e.type),this.loadAds();break;case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:o(e.type),this.pauseContent();break;case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:o(e.type),this.pollCountdown(),this.resumeContent();break;case google.ima.AdEvent.Type.STARTED:case google.ima.AdEvent.Type.MIDPOINT:case google.ima.AdEvent.Type.COMPLETE:case google.ima.AdEvent.Type.IMPRESSION:case google.ima.AdEvent.Type.CLICK:o(e.type);break;case google.ima.AdEvent.Type.LOG:r.adError&&this.player.debug.warn("Non-fatal ad error: ".concat(r.adError.getMessage()))}}},{key:"onAdError",value:function(e){this.cancel(),this.player.debug.warn("Ads error",e)}},{key:"listeners",value:function(){var e,t=this,n=this.player.elements.container;this.player.on("ended",function(){t.loader.contentComplete()}),this.player.on("timeupdate",function(){e=t.player.currentTime}),this.player.on("seeked",function(){var n=t.player.currentTime;is$1.empty(t.cuePoints)||t.cuePoints.forEach(function(i,r){e<i&&i<n&&(t.manager.discardAdBreak(),t.cuePoints.splice(r,1))})}),window.addEventListener("resize",function(){t.manager&&t.manager.resize(n.offsetWidth,n.offsetHeight,google.ima.ViewMode.NORMAL)})}},{key:"play",value:function(){var e=this,t=this.player.elements.container;this.managerPromise||this.resumeContent(),this.managerPromise.then(function(){e.elements.displayContainer.initialize();try{e.initialized||(e.manager.init(t.offsetWidth,t.offsetHeight,google.ima.ViewMode.NORMAL),e.manager.start()),e.initialized=!0}catch(t){e.onAdError(t)}}).catch(function(){})}},{key:"resumeContent",value:function(){this.elements.container.style.zIndex="",this.playing=!1,this.player.currentTime<this.player.duration&&this.player.play()}},{key:"pauseContent",value:function(){this.elements.container.style.zIndex=3,this.playing=!0,this.player.pause()}},{key:"cancel",value:function(){this.initialized&&this.resumeContent(),this.trigger("error"),this.loadAds()}},{key:"loadAds",value:function(){var e=this;this.managerPromise.then(function(){e.manager&&e.manager.destroy(),e.managerPromise=new Promise(function(t){e.on("loaded",t),e.player.debug.log(e.manager)}),e.requestAds()}).catch(function(){})}},{key:"trigger",value:function(e){for(var t=this,n=arguments.length,i=new Array(n>1?n-1:0),r=1;r<n;r++)i[r-1]=arguments[r];var o=this.events[e];is$1.array(o)&&o.forEach(function(e){is$1.function(e)&&e.apply(t,i)})}},{key:"on",value:function(e,t){return is$1.array(this.events[e])||(this.events[e]=[]),this.events[e].push(t),this}},{key:"startSafetyTimer",value:function(e,t){var n=this;this.player.debug.log("Safety timer invoked from: ".concat(t)),this.safetyTimer=setTimeout(function(){n.cancel(),n.clearSafetyTimer("startSafetyTimer()")},e)}},{key:"clearSafetyTimer",value:function(e){is$1.nullOrUndefined(this.safetyTimer)||(this.player.debug.log("Safety timer cleared from: ".concat(e)),clearTimeout(this.safetyTimer),this.safetyTimer=null)}},{key:"enabled",get:function(){var e=this.config;return this.player.isHTML5&&this.player.isVideo&&e.enabled&&(!is$1.empty(e.publisherId)||is$1.url(e.tagUrl))}},{key:"tagUrl",get:function(){var e=this.config;if(is$1.url(e.tagUrl))return e.tagUrl;var t={AV_PUBLISHERID:"58c25bb0073ef448b1087ad6",AV_CHANNELID:"5a0458dc28a06145e4519d21",AV_URL:window.location.hostname,cb:Date.now(),AV_WIDTH:640,AV_HEIGHT:480,AV_CDIM2:this.publisherId};return"".concat("https://go.aniview.com/api/adserver6/vast/","?").concat(buildUrlParams(t))}}]),e}(),$find$1=_arrayMethods(6),KEY$1="findIndex",forced$1=!0;KEY$1 in[]&&Array(1)[KEY$1](function(){forced$1=!1}),_export(_export.P+_export.F*forced$1,"Array",{findIndex:function(e){return $find$1(this,e,arguments.length>1?arguments[1]:void 0)}}),_addToUnscopables(KEY$1);var parseVtt=function(e){var t=[];return e.split(/\r\n\r\n|\n\n|\r\r/).forEach(function(e){var n={};e.split(/\r\n|\n|\r/).forEach(function(e){if(is$1.number(n.startTime)){if(!is$1.empty(e.trim())&&is$1.empty(n.text)){var t=e.trim().split("#xywh="),i=_slicedToArray(t,1);if(n.text=i[0],t[1]){var r=_slicedToArray(t[1].split(","),4);n.x=r[0],n.y=r[1],n.w=r[2],n.h=r[3]}}}else{var o=e.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);o&&(n.startTime=60*Number(o[1])*60+60*Number(o[2])+Number(o[3])+Number("0.".concat(o[4])),n.endTime=60*Number(o[6])*60+60*Number(o[7])+Number(o[8])+Number("0.".concat(o[9])))}}),n.text&&t.push(n)}),t},PreviewThumbnails=function(){function e(t){_classCallCheck(this,e),this.player=t,this.thumbnails=[],this.loaded=!1,this.lastMouseMoveTime=Date.now(),this.mouseDown=!1,this.loadedImages=[],this.elements={thumb:{},scrubbing:{}},this.load()}return _createClass(e,[{key:"load",value:function(){var e=this;this.player.elements.display.seekTooltip&&(this.player.elements.display.seekTooltip.hidden=this.enabled),this.enabled&&this.getThumbnails().then(function(){e.render(),e.determineContainerAutoSizing(),e.loaded=!0})}},{key:"getThumbnails",value:function(){var e=this;return new Promise(function(t){var n=e.player.config.previewThumbnails.src;if(is$1.empty(n))throw new Error("Missing previewThumbnails.src config attribute");var i=(is$1.string(n)?[n]:n).map(function(t){return e.getThumbnail(t)});Promise.all(i).then(function(){e.thumbnails.sort(function(e,t){return e.height-t.height}),e.player.debug.log("Preview thumbnails",e.thumbnails),t()})})}},{key:"getThumbnail",value:function(e){var t=this;return new Promise(function(n){fetch(e).then(function(i){var r={frames:parseVtt(i),height:null,urlPrefix:""};r.frames[0].text.startsWith("/")||(r.urlPrefix=e.substring(0,e.lastIndexOf("/")+1));var o=new Image;o.onload=function(){r.height=o.naturalHeight,r.width=o.naturalWidth,t.thumbnails.push(r),n()},o.src=r.urlPrefix+r.frames[0].text})})}},{key:"startMove",value:function(e){if(this.loaded&&is$1.event(e)&&["touchmove","mousemove"].includes(e.type)&&this.player.media.duration){if("touchmove"===e.type)this.seekTime=this.player.media.duration*(this.player.elements.inputs.seek.value/100);else{var t=this.player.elements.progress.getBoundingClientRect(),n=100/t.width*(e.pageX-t.left);this.seekTime=this.player.media.duration*(n/100),this.seekTime<0&&(this.seekTime=0),this.seekTime>this.player.media.duration-1&&(this.seekTime=this.player.media.duration-1),this.mousePosX=e.pageX,this.elements.thumb.time.innerText=formatTime(this.seekTime)}this.showImageAtCurrentTime()}}},{key:"endMove",value:function(){this.toggleThumbContainer(!1,!0)}},{key:"startScrubbing",value:function(e){!1!==e.button&&0!==e.button||(this.mouseDown=!0,this.player.media.duration&&(this.toggleScrubbingContainer(!0),this.toggleThumbContainer(!1,!0),this.showImageAtCurrentTime()))}},{key:"finishScrubbing",value:function(){var e=this;this.mouseDown=!1,Math.ceil(this.lastTime)===Math.ceil(this.player.media.currentTime)?this.toggleScrubbingContainer(!1):once.call(this.player,this.player.media,"timeupdate",function(){e.mouseDown||e.toggleScrubbingContainer(!1)})}},{key:"listeners",value:function(){var e=this;this.player.on("play",function(){e.toggleThumbContainer(!1,!0)}),this.player.on("seeked",function(){e.toggleThumbContainer(!1)}),this.player.on("timeupdate",function(){e.lastTime=e.player.media.currentTime})}},{key:"render",value:function(){this.elements.thumb.container=createElement("div",{class:this.player.config.classNames.previewThumbnails.thumbContainer}),this.elements.thumb.imageContainer=createElement("div",{class:this.player.config.classNames.previewThumbnails.imageContainer}),this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);var e=createElement("div",{class:this.player.config.classNames.previewThumbnails.timeContainer});this.elements.thumb.time=createElement("span",{},"00:00"),e.appendChild(this.elements.thumb.time),this.elements.thumb.container.appendChild(e),this.player.elements.progress.appendChild(this.elements.thumb.container),this.elements.scrubbing.container=createElement("div",{class:this.player.config.classNames.previewThumbnails.scrubbingContainer}),this.player.elements.wrapper.appendChild(this.elements.scrubbing.container)}},{key:"showImageAtCurrentTime",value:function(){var e=this;this.mouseDown?this.setScrubbingContainerSize():(this.toggleThumbContainer(!0),this.setThumbContainerSizeAndPos());var t=this.thumbnails[0].frames.findIndex(function(t){return e.seekTime>=t.startTime&&e.seekTime<=t.endTime}),n=t>=0,i=0;this.toggleThumbContainer(n),n&&(this.thumbnails.forEach(function(n,r){e.loadedImages.includes(n.frames[t].text)&&(i=r)}),t!==this.showingThumb&&(this.showingThumb=t,this.loadImage(i)))}},{key:"loadImage",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=this.showingThumb,i=this.thumbnails[t],r=i.urlPrefix,o=i.frames[n],s=i.frames[n].text,a=r+s;if(this.currentImageElement&&this.currentImageElement.dataset.filename===s)this.showImage(this.currentImageElement,o,t,n,s,!1),this.currentImageElement.dataset.index=n,this.removeOldImages(this.currentImageElement);else{this.loadingImage&&this.usingSprites&&(this.loadingImage.onload=null);var l=new Image;l.src=a,l.dataset.index=n,l.dataset.filename=s,this.showingThumbFilename=s,this.player.debug.log("Loading image: ".concat(a)),l.onload=function(){return e.showImage(l,o,t,n,s,!0)},this.loadingImage=l,this.removeOldImages(l)}}},{key:"showImage",value:function(e,t,n,i,r){var o=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];this.player.debug.log("Showing thumb: ".concat(r,". num: ").concat(i,". qual: ").concat(n,". newimg: ").concat(o)),this.setImageSizeAndOffset(e,t),o&&(this.currentImageContainer.appendChild(e),this.currentImageElement=e,this.loadedImages.includes(r)||this.loadedImages.push(r)),this.preloadNearby(i,!0).then(this.preloadNearby(i,!1)).then(this.getHigherQuality(n,e,t,r))}},{key:"removeOldImages",value:function(e){var t=this;Array.from(this.currentImageContainer.children).forEach(function(n){if("img"===n.tagName.toLowerCase()){var i=t.usingSprites?500:1e3;if(n.dataset.index!==e.dataset.index&&!n.dataset.deleting){n.dataset.deleting=!0;var r=t.currentImageContainer;setTimeout(function(){r.removeChild(n),t.player.debug.log("Removing thumb: ".concat(n.dataset.filename))},i)}}})}},{key:"preloadNearby",value:function(e){var t=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return new Promise(function(i){setTimeout(function(){var r=t.thumbnails[0].frames[e].text;if(t.showingThumbFilename===r){var o;o=n?t.thumbnails[0].frames.slice(e):t.thumbnails[0].frames.slice(0,e).reverse();var s=!1;o.forEach(function(e){var n=e.text;if(n!==r&&!t.loadedImages.includes(n)){s=!0,t.player.debug.log("Preloading thumb filename: ".concat(n));var o=t.thumbnails[0].urlPrefix+n,a=new Image;a.src=o,a.onload=function(){t.player.debug.log("Preloaded thumb filename: ".concat(n)),t.loadedImages.includes(n)||t.loadedImages.push(n),i()}}}),s||i()}},300)})}},{key:"getHigherQuality",value:function(e,t,n,i){var r=this;if(e<this.thumbnails.length-1){var o=t.naturalHeight;this.usingSprites&&(o=n.h),o<this.thumbContainerHeight&&setTimeout(function(){r.showingThumbFilename===i&&(r.player.debug.log("Showing higher quality thumb for: ".concat(i)),r.loadImage(e+1))},300)}}},{key:"toggleThumbContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.player.config.classNames.previewThumbnails.thumbContainerShown;this.elements.thumb.container.classList.toggle(n,e),!e&&t&&(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"toggleScrubbingContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.player.config.classNames.previewThumbnails.scrubbingContainerShown;this.elements.scrubbing.container.classList.toggle(t,e),e||(this.showingThumb=null,this.showingThumbFilename=null)}},{key:"determineContainerAutoSizing",value:function(){this.elements.thumb.imageContainer.clientHeight>20&&(this.sizeSpecifiedInCSS=!0)}},{key:"setThumbContainerSizeAndPos",value:function(){if(!this.sizeSpecifiedInCSS){var e=Math.floor(this.thumbContainerHeight*this.thumbAspectRatio);this.elements.thumb.imageContainer.style.height="".concat(this.thumbContainerHeight,"px"),this.elements.thumb.imageContainer.style.width="".concat(e,"px")}this.setThumbContainerPos()}},{key:"setThumbContainerPos",value:function(){var e=this.player.elements.progress.getBoundingClientRect(),t=this.player.elements.container.getBoundingClientRect(),n=this.elements.thumb.container,i=t.left-e.left+10,r=t.right-e.left-n.clientWidth-10,o=this.mousePosX-e.left-n.clientWidth/2;o<i&&(o=i),o>r&&(o=r),n.style.left="".concat(o,"px")}},{key:"setScrubbingContainerSize",value:function(){this.elements.scrubbing.container.style.width="".concat(this.player.media.clientWidth,"px"),this.elements.scrubbing.container.style.height="".concat(this.player.media.clientWidth/this.thumbAspectRatio,"px")}},{key:"setImageSizeAndOffset",value:function(e,t){if(this.usingSprites){var n=this.thumbContainerHeight/t.h;e.style.height="".concat(Math.floor(e.naturalHeight*n),"px"),e.style.width="".concat(Math.floor(e.naturalWidth*n),"px"),e.style.left="-".concat(t.x*n,"px"),e.style.top="-".concat(t.y*n,"px")}}},{key:"enabled",get:function(){return this.player.isHTML5&&this.player.isVideo&&this.player.config.previewThumbnails.enabled}},{key:"currentImageContainer",get:function(){return this.mouseDown?this.elements.scrubbing.container:this.elements.thumb.imageContainer}},{key:"usingSprites",get:function(){return Object.keys(this.thumbnails[0].frames[0]).includes("w")}},{key:"thumbAspectRatio",get:function(){return this.usingSprites?this.thumbnails[0].frames[0].w/this.thumbnails[0].frames[0].h:this.thumbnails[0].width/this.thumbnails[0].height}},{key:"thumbContainerHeight",get:function(){return this.mouseDown?Math.floor(this.player.media.clientWidth/this.thumbAspectRatio):Math.floor(this.player.media.clientWidth/this.thumbAspectRatio/4)}},{key:"currentImageElement",get:function(){return this.mouseDown?this.currentScrubbingImageElement:this.currentThumbnailImageElement},set:function(e){this.mouseDown?this.currentScrubbingImageElement=e:this.currentThumbnailImageElement=e}}]),e}(),source={insertElements:function(e,t){var n=this;is$1.string(t)?insertElement(e,this.media,{src:t}):is$1.array(t)&&t.forEach(function(t){insertElement(e,n.media,t)})},change:function(e){var t=this;getDeep(e,"sources.length")?(html5.cancelRequests.call(this),this.destroy.call(this,function(){t.options.quality=[],removeElement(t.media),t.media=null,is$1.element(t.elements.container)&&t.elements.container.removeAttribute("class");var n=e.sources,i=e.type,r=_slicedToArray(n,1)[0],o=r.provider,s=void 0===o?providers.html5:o,a=r.src,l="html5"===s?i:"div",c="html5"===s?{}:{src:a};Object.assign(t,{provider:s,type:i,supported:support.check(i,s,t.config.playsinline),media:createElement(l,c)}),t.elements.container.appendChild(t.media),is$1.boolean(e.autoplay)&&(t.config.autoplay=e.autoplay),t.isHTML5&&(t.config.crossorigin&&t.media.setAttribute("crossorigin",""),t.config.autoplay&&t.media.setAttribute("autoplay",""),is$1.empty(e.poster)||(t.poster=e.poster),t.config.loop.active&&t.media.setAttribute("loop",""),t.config.muted&&t.media.setAttribute("muted",""),t.config.playsinline&&t.media.setAttribute("playsinline","")),ui.addStyleHook.call(t),t.isHTML5&&source.insertElements.call(t,"source",n),t.config.title=e.title,media.setup.call(t),t.isHTML5&&Object.keys(e).includes("tracks")&&source.insertElements.call(t,"track",e.tracks),(t.isHTML5||t.isEmbed&&!t.supported.ui)&&ui.build.call(t),t.isHTML5&&t.media.load(),t.previewThumbnails&&t.previewThumbnails.load(),t.fullscreen.update()},!0)):this.debug.warn("Invalid source format")}},Plyr=function(){function e(t,n){var i=this;if(_classCallCheck(this,e),this.timers={},this.ready=!1,this.loading=!1,this.failed=!1,this.touch=support.touch,this.media=t,is$1.string(this.media)&&(this.media=document.querySelectorAll(this.media)),(window.jQuery&&this.media instanceof jQuery||is$1.nodeList(this.media)||is$1.array(this.media))&&(this.media=this.media[0]),this.config=extend({},defaults,e.defaults,n||{},function(){try{return JSON.parse(i.media.getAttribute("data-plyr-config"))}catch(e){return{}}}()),this.elements={container:null,captions:null,buttons:{},display:{},progress:{},inputs:{},settings:{popup:null,menu:null,panels:{},buttons:{}}},this.captions={active:null,currentTrack:-1,meta:new WeakMap},this.fullscreen={active:!1},this.options={speed:[],quality:[]},this.debug=new Console(this.config.debug),this.debug.log("Config",this.config),this.debug.log("Support",support),!is$1.nullOrUndefined(this.media)&&is$1.element(this.media))if(this.media.plyr)this.debug.warn("Target already setup");else if(this.config.enabled)if(support.check().api){var r=this.media.cloneNode(!0);r.autoplay=!1,this.elements.original=r;var o=this.media.tagName.toLowerCase(),s=null,a=null;switch(o){case"div":if(s=this.media.querySelector("iframe"),is$1.element(s)){if(a=parseUrl(s.getAttribute("src")),this.provider=getProviderByUrl(a.toString()),this.elements.container=this.media,this.media=s,this.elements.container.className="",a.search.length){var l=["1","true"];l.includes(a.searchParams.get("autoplay"))&&(this.config.autoplay=!0),l.includes(a.searchParams.get("loop"))&&(this.config.loop.active=!0),this.isYouTube?(this.config.playsinline=l.includes(a.searchParams.get("playsinline")),this.config.youtube.hl=a.searchParams.get("hl")):this.config.playsinline=!0}}else this.provider=this.media.getAttribute(this.config.attributes.embed.provider),this.media.removeAttribute(this.config.attributes.embed.provider);if(is$1.empty(this.provider)||!Object.keys(providers).includes(this.provider))return void this.debug.error("Setup failed: Invalid provider");this.type=types.video;break;case"video":case"audio":this.type=o,this.provider=providers.html5,this.media.hasAttribute("crossorigin")&&(this.config.crossorigin=!0),this.media.hasAttribute("autoplay")&&(this.config.autoplay=!0),(this.media.hasAttribute("playsinline")||this.media.hasAttribute("webkit-playsinline"))&&(this.config.playsinline=!0),this.media.hasAttribute("muted")&&(this.config.muted=!0),this.media.hasAttribute("loop")&&(this.config.loop.active=!0);break;default:return void this.debug.error("Setup failed: unsupported type")}this.supported=support.check(this.type,this.provider,this.config.playsinline),this.supported.api?(this.eventListeners=[],this.listeners=new Listeners(this),this.storage=new Storage(this),this.media.plyr=this,is$1.element(this.elements.container)||(this.elements.container=createElement("div",{tabindex:0}),wrap(this.media,this.elements.container)),ui.addStyleHook.call(this),media.setup.call(this),this.config.debug&&on.call(this,this.elements.container,this.config.events.join(" "),function(e){i.debug.log("event: ".concat(e.type))}),(this.isHTML5||this.isEmbed&&!this.supported.ui)&&ui.build.call(this),this.listeners.container(),this.listeners.global(),this.fullscreen=new Fullscreen(this),this.config.ads.enabled&&(this.ads=new Ads(this)),this.config.autoplay&&this.play(),this.lastSeekTime=0,this.config.previewThumbnails.enabled&&(this.previewThumbnails=new PreviewThumbnails(this))):this.debug.error("Setup failed: no support")}else this.debug.error("Setup failed: no support");else this.debug.error("Setup failed: disabled by config");else this.debug.error("Setup failed: no suitable element passed")}return _createClass(e,[{key:"play",value:function(){return is$1.function(this.media.play)?this.media.play():null}},{key:"pause",value:function(){this.playing&&is$1.function(this.media.pause)&&this.media.pause()}},{key:"togglePlay",value:function(e){(is$1.boolean(e)?e:!this.playing)?this.play():this.pause()}},{key:"stop",value:function(){this.isHTML5?(this.pause(),this.restart()):is$1.function(this.media.stop)&&this.media.stop()}},{key:"restart",value:function(){this.currentTime=0}},{key:"rewind",value:function(e){this.currentTime=this.currentTime-(is$1.number(e)?e:this.config.seekTime)}},{key:"forward",value:function(e){this.currentTime=this.currentTime+(is$1.number(e)?e:this.config.seekTime)}},{key:"increaseVolume",value:function(e){var t=this.media.muted?0:this.volume;this.volume=t+(is$1.number(e)?e:0)}},{key:"decreaseVolume",value:function(e){this.increaseVolume(-e)}},{key:"toggleCaptions",value:function(e){captions.toggle.call(this,e,!1)}},{key:"airplay",value:function(){support.airplay&&this.media.webkitShowPlaybackTargetPicker()}},{key:"toggleControls",value:function(e){if(this.supported.ui&&!this.isAudio){var t=hasClass(this.elements.container,this.config.classNames.hideControls),n=void 0===e?void 0:!e,i=toggleClass(this.elements.container,this.config.classNames.hideControls,n);if(i&&this.config.controls.includes("settings")&&!is$1.empty(this.config.settings)&&controls.toggleMenu.call(this,!1),i!==t){var r=i?"controlshidden":"controlsshown";triggerEvent.call(this,this.media,r)}return!i}return!1}},{key:"on",value:function(e,t){on.call(this,this.elements.container,e,t)}},{key:"once",value:function(e,t){once.call(this,this.elements.container,e,t)}},{key:"off",value:function(e,t){off(this.elements.container,e,t)}},{key:"destroy",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.ready){var i=function(){document.body.style.overflow="",t.embed=null,n?(Object.keys(t.elements).length&&(removeElement(t.elements.buttons.play),removeElement(t.elements.captions),removeElement(t.elements.controls),removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),is$1.function(e)&&e()):(unbindListeners.call(t),replaceElement(t.elements.original,t.elements.container),triggerEvent.call(t,t.elements.original,"destroyed",!0),is$1.function(e)&&e.call(t.elements.original),t.ready=!1,setTimeout(function(){t.elements=null,t.media=null},200))};this.stop(),this.isHTML5?(clearTimeout(this.timers.loading),ui.toggleNativeControls.call(this,!0),i()):this.isYouTube?(clearInterval(this.timers.buffering),clearInterval(this.timers.playing),null!==this.embed&&is$1.function(this.embed.destroy)&&this.embed.destroy(),i()):this.isVimeo&&(null!==this.embed&&this.embed.unload().then(i),setTimeout(i,200))}}},{key:"supports",value:function(e){return support.mime.call(this,e)}},{key:"isHTML5",get:function(){return Boolean(this.provider===providers.html5)}},{key:"isEmbed",get:function(){return Boolean(this.isYouTube||this.isVimeo)}},{key:"isYouTube",get:function(){return Boolean(this.provider===providers.youtube)}},{key:"isVimeo",get:function(){return Boolean(this.provider===providers.vimeo)}},{key:"isVideo",get:function(){return Boolean(this.type===types.video)}},{key:"isAudio",get:function(){return Boolean(this.type===types.audio)}},{key:"playing",get:function(){return Boolean(this.ready&&!this.paused&&!this.ended)}},{key:"paused",get:function(){return Boolean(this.media.paused)}},{key:"stopped",get:function(){return Boolean(this.paused&&0===this.currentTime)}},{key:"ended",get:function(){return Boolean(this.media.ended)}},{key:"currentTime",set:function(e){if(this.duration){var t=is$1.number(e)&&e>0;this.media.currentTime=t?Math.min(e,this.duration):0,this.debug.log("Seeking to ".concat(this.currentTime," seconds"))}},get:function(){return Number(this.media.currentTime)}},{key:"buffered",get:function(){var e=this.media.buffered;return is$1.number(e)?e:e&&e.length&&this.duration>0?e.end(0)/this.duration:0}},{key:"seeking",get:function(){return Boolean(this.media.seeking)}},{key:"duration",get:function(){var e=parseFloat(this.config.duration),t=(this.media||{}).duration,n=is$1.number(t)&&t!==1/0?t:0;return e||n}},{key:"volume",set:function(e){var t=e;is$1.string(t)&&(t=Number(t)),is$1.number(t)||(t=this.storage.get("volume")),is$1.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,!is$1.empty(e)&&this.muted&&t>0&&(this.muted=!1)},get:function(){return Number(this.media.volume)}},{key:"muted",set:function(e){var t=e;is$1.boolean(t)||(t=this.storage.get("muted")),is$1.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return Boolean(this.media.muted)}},{key:"hasAudio",get:function(){return!this.isHTML5||(!!this.isAudio||(Boolean(this.media.mozHasAudio)||Boolean(this.media.webkitAudioDecodedByteCount)||Boolean(this.media.audioTracks&&this.media.audioTracks.length)))}},{key:"speed",set:function(e){var t=null;is$1.number(e)&&(t=e),is$1.number(t)||(t=this.storage.get("speed")),is$1.number(t)||(t=this.config.speed.selected),t<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.debug.warn("Unsupported speed (".concat(t,")"))},get:function(){return Number(this.media.playbackRate)}},{key:"quality",set:function(e){var t=this.config.quality,n=this.options.quality;if(n.length){var i=[!is$1.empty(e)&&Number(e),this.storage.get("quality"),t.selected,t.default].find(is$1.number),r=!0;if(!n.includes(i)){var o=closest(n,i);this.debug.warn("Unsupported quality option: ".concat(i,", using ").concat(o," instead")),i=o,r=!1}t.selected=i,this.media.quality=i,r&&this.storage.set({quality:i})}},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=is$1.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return Boolean(this.media.loop)}},{key:"source",set:function(e){source.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"download",get:function(){var e=this.config.urls.download;return is$1.url(e)?e:this.source}},{key:"poster",set:function(e){this.isVideo?ui.setPoster.call(this,e,!1).catch(function(){}):this.debug.warn("Poster can only be set for video")},get:function(){return this.isVideo?this.media.getAttribute("poster"):null}},{key:"autoplay",set:function(e){var t=is$1.boolean(e)?e:this.config.autoplay;this.config.autoplay=t},get:function(){return Boolean(this.config.autoplay)}},{key:"currentTrack",set:function(e){captions.set.call(this,e,!1)},get:function(){var e=this.captions,t=e.toggled,n=e.currentTrack;return t?n:-1}},{key:"language",set:function(e){captions.setLanguage.call(this,e,!1)},get:function(){return(captions.getCurrentTrack.call(this)||{}).language}},{key:"pip",set:function(e){if(support.pip){var t=is$1.boolean(e)?e:!this.pip;is$1.function(this.media.webkitSetPresentationMode)&&this.media.webkitSetPresentationMode(t?pip.active:pip.inactive),is$1.function(this.media.requestPictureInPicture)&&(!this.pip&&t?this.media.requestPictureInPicture():this.pip&&!t&&document.exitPictureInPicture())}},get:function(){return support.pip?is$1.empty(this.media.webkitPresentationMode)?this.media===document.pictureInPictureElement:this.media.webkitPresentationMode===pip.active:null}}],[{key:"supported",value:function(e,t,n){return support.check(e,t,n)}},{key:"loadSprite",value:function(e,t){return loadSprite(e,t)}},{key:"setup",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=null;return is$1.string(t)?i=Array.from(document.querySelectorAll(t)):is$1.nodeList(t)?i=Array.from(t):is$1.array(t)&&(i=t.filter(is$1.element)),is$1.empty(i)?null:i.map(function(t){return new e(t,n)})}}]),e}();Plyr.defaults=cloneDeep(defaults);export default Plyr;
\ No newline at end of file diff --git a/dist/plyr.polyfilled.min.mjs.map b/dist/plyr.polyfilled.min.mjs.map new file mode 100644 index 00000000..75873caf --- /dev/null +++ b/dist/plyr.polyfilled.min.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["node_modules/custom-event-polyfill/polyfill.js","node_modules/url-polyfill/url-polyfill.js","node_modules/core-js/modules/_a-function.js","node_modules/core-js/modules/_ctx.js","node_modules/core-js/modules/_global.js","node_modules/core-js/modules/_core.js","node_modules/core-js/modules/_is-object.js","node_modules/core-js/modules/_an-object.js","node_modules/core-js/modules/_fails.js","node_modules/core-js/modules/_descriptors.js","node_modules/core-js/modules/_dom-create.js","node_modules/core-js/modules/_ie8-dom-define.js","node_modules/core-js/modules/_to-primitive.js","node_modules/core-js/modules/_object-dp.js","node_modules/core-js/modules/_property-desc.js","node_modules/core-js/modules/_hide.js","node_modules/core-js/modules/_has.js","node_modules/core-js/modules/_uid.js","node_modules/core-js/modules/_redefine.js","node_modules/core-js/modules/_export.js","node_modules/core-js/modules/_defined.js","node_modules/core-js/modules/_to-object.js","node_modules/core-js/modules/_iter-call.js","node_modules/core-js/modules/_iterators.js","node_modules/core-js/modules/_library.js","node_modules/core-js/modules/_shared.js","node_modules/core-js/modules/_wks.js","node_modules/core-js/modules/_is-array-iter.js","node_modules/core-js/modules/_to-integer.js","node_modules/core-js/modules/_to-length.js","node_modules/core-js/modules/_create-property.js","node_modules/core-js/modules/_cof.js","node_modules/core-js/modules/_classof.js","node_modules/core-js/modules/core.get-iterator-method.js","node_modules/core-js/modules/_iter-detect.js","node_modules/core-js/modules/es6.array.from.js","node_modules/core-js/modules/_iobject.js","node_modules/core-js/modules/_is-array.js","node_modules/core-js/modules/_array-species-constructor.js","node_modules/core-js/modules/_array-species-create.js","node_modules/core-js/modules/_array-methods.js","node_modules/core-js/modules/_add-to-unscopables.js","node_modules/core-js/modules/es6.array.find.js","node_modules/core-js/modules/_object-pie.js","node_modules/core-js/modules/_to-iobject.js","node_modules/core-js/modules/_object-gopd.js","node_modules/core-js/modules/_set-proto.js","node_modules/core-js/modules/_inherit-if-required.js","node_modules/core-js/modules/_to-absolute-index.js","node_modules/core-js/modules/_array-includes.js","node_modules/core-js/modules/_shared-key.js","node_modules/core-js/modules/_object-keys-internal.js","node_modules/core-js/modules/_enum-bug-keys.js","node_modules/core-js/modules/_object-gopn.js","node_modules/core-js/modules/_string-ws.js","node_modules/core-js/modules/_string-trim.js","node_modules/core-js/modules/_object-keys.js","node_modules/core-js/modules/_object-dps.js","node_modules/core-js/modules/_html.js","node_modules/core-js/modules/_object-create.js","node_modules/core-js/modules/es6.number.constructor.js","node_modules/core-js/modules/_object-sap.js","node_modules/core-js/modules/es6.object.keys.js","node_modules/core-js/modules/_is-regexp.js","node_modules/core-js/modules/_string-context.js","node_modules/core-js/modules/_fails-is-regexp.js","node_modules/core-js/modules/es6.string.includes.js","node_modules/core-js/modules/es7.array.includes.js","node_modules/core-js/modules/_same-value.js","node_modules/core-js/modules/_regexp-exec-abstract.js","node_modules/core-js/modules/_flags.js","node_modules/core-js/modules/_regexp-exec.js","node_modules/core-js/modules/es6.regexp.exec.js","node_modules/core-js/modules/_fix-re-wks.js","node_modules/core-js/modules/es6.regexp.search.js","node_modules/core-js/modules/es6.regexp.flags.js","node_modules/core-js/modules/es6.regexp.to-string.js","node_modules/core-js/modules/_iter-step.js","node_modules/core-js/modules/_set-to-string-tag.js","node_modules/core-js/modules/_iter-create.js","node_modules/core-js/modules/_object-gpo.js","node_modules/core-js/modules/_iter-define.js","node_modules/core-js/modules/es6.array.iterator.js","node_modules/core-js/modules/web.dom.iterable.js","node_modules/core-js/modules/_string-at.js","node_modules/core-js/modules/es6.string.iterator.js","node_modules/core-js/modules/_meta.js","node_modules/core-js/modules/_object-gops.js","node_modules/core-js/modules/_object-assign.js","node_modules/core-js/modules/_redefine-all.js","node_modules/core-js/modules/_an-instance.js","node_modules/core-js/modules/_for-of.js","node_modules/core-js/modules/_validate-collection.js","node_modules/core-js/modules/_collection-weak.js","node_modules/core-js/modules/_collection.js","node_modules/core-js/modules/es6.weak-map.js","node_modules/core-js/modules/_strict-method.js","node_modules/core-js/modules/es6.array.sort.js","node_modules/core-js/modules/es6.object.assign.js","node_modules/core-js/modules/_species-constructor.js","node_modules/core-js/modules/_advance-string-index.js","node_modules/core-js/modules/es6.regexp.split.js","node_modules/core-js/modules/_object-to-array.js","node_modules/core-js/modules/es7.object.entries.js","node_modules/core-js/modules/es7.object.values.js","node_modules/core-js/modules/es6.regexp.replace.js","node_modules/core-js/modules/_invoke.js","node_modules/core-js/modules/_task.js","node_modules/core-js/modules/_microtask.js","node_modules/core-js/modules/_new-promise-capability.js","node_modules/core-js/modules/es6.promise.js","node_modules/core-js/modules/_perform.js","node_modules/core-js/modules/_user-agent.js","node_modules/core-js/modules/_promise-resolve.js","node_modules/core-js/modules/_set-species.js","node_modules/core-js/modules/es6.string.starts-with.js","node_modules/core-js/modules/es6.number.is-nan.js","src/js/utils/is.js","src/js/utils/events.js","src/js/utils/elements.js","src/js/utils/animation.js","src/js/utils/browser.js","src/js/support.js","src/js/html5.js","src/js/utils/arrays.js","src/js/utils/objects.js","node_modules/core-js/modules/es6.regexp.constructor.js","src/js/utils/strings.js","src/js/utils/i18n.js","src/js/storage.js","src/js/utils/fetch.js","src/js/utils/loadSprite.js","node_modules/core-js/modules/es6.math.trunc.js","src/js/utils/time.js","src/js/controls.js","src/js/utils/urls.js","src/js/captions.js","src/js/config/defaults.js","src/js/config/states.js","src/js/config/types.js","src/js/console.js","src/js/fullscreen.js","node_modules/core-js/modules/_math-sign.js","src/js/utils/loadImage.js","node_modules/core-js/modules/es6.math.sign.js","src/js/ui.js","src/js/utils/style.js","src/js/listeners.js","node_modules/core-js/modules/es6.function.name.js","node_modules/core-js/modules/es6.regexp.match.js","node_modules/loadjs/dist/loadjs.umd.js","src/js/utils/loadScript.js","src/js/plugins/vimeo.js","src/js/plugins/youtube.js","src/js/media.js","src/js/plugins/ads.js","node_modules/core-js/modules/es6.array.find-index.js","src/js/plugins/previewThumbnails.js","src/js/source.js","src/js/plyr.js"],"names":["window","ce","CustomEvent","cancelable","preventDefault","defaultPrevented","Error","e","event","params","evt","origPrevent","bubbles","detail","undefined","document","createEvent","initCustomEvent","call","this","Object","defineProperty","get","prototype","Event","global","iteratorSupported","Symbol","iterator","error","checkIfIteratorIsSupported","createIterator","items","next","value","shift","done","serializeParam","encodeURIComponent","replace","deserializeParam","decodeURIComponent","URLSearchParams","toString","searchString","writable","typeofSearchString","_fromString","_this","forEach","name","append","TypeError","i","length","entry","key","hasOwnProperty","proto","_entries","push","String","delete","getAll","slice","has","set","callback","thisArg","entries","keys","values","searchArray","join","polyfillURLSearchParams","sort","a","b","enumerable","configurable","attribute","attributes","split","self","u","URL","pathname","href","searchParams","checkIfURLIsSupported","_URL","url","base","baseElement","doc","location","implementation","createHTMLDocument","createElement","head","appendChild","indexOf","err","anchorElement","body","protocol","test","search","enableSearchUpdate","enableSearchParamsUpdate","methodName","method","apply","arguments","attributeName","_anchorElement","linkURLWithAnchorAttribute","_updateSearchParams","defineProperties","origin","expectedPort","http:","https:","ftp:","addPortToOrigin","port","hostname","password","username","createObjectURL","blob","revokeObjectURL","polyfillURL","getOrigin","setInterval","_aFunction","it","_ctx","fn","that","aFunction","c","module","exports","Math","Function","__g","core","version","__e","_isObject","_anObject","isObject","_fails","exec","_descriptors","require$$0","is","_domCreate","_ie8DomDefine","require$$1","require$$2","_toPrimitive","S","val","valueOf","dP","f","O","P","Attributes","anObject","toPrimitive","IE8_DOM_DEFINE","_propertyDesc","bitmap","_hide","object","createDesc","_has","id","px","random","_uid","concat","SRC","$toString","TPL","inspectSource","safe","isFunction","hide","PROTOTYPE","$export","type","source","own","out","exp","IS_FORCED","F","IS_GLOBAL","G","IS_STATIC","IS_PROTO","IS_BIND","B","target","expProto","ctx","redefine","U","W","R","_export","_defined","_toObject","defined","_iterCall","ret","_iterators","_library","store","mode","copyright","USE_SYMBOL","uid","ITERATOR","ArrayProto","Array","_isArrayIter","Iterators","ceil","floor","_toInteger","isNaN","min","_toLength","toInteger","_createProperty","index","$defineProperty","_cof","TAG","ARG","cof","tryGet","_classof","T","callee","core_getIteratorMethod","getIteratorMethod","classof","SAFE_CLOSING","riter","_iterDetect","skipClosing","arr","iter","from","arrayLike","result","step","toObject","C","aLen","mapfn","mapping","iterFn","getIterFn","isArrayIter","toLength","createProperty","_iobject","propertyIsEnumerable","_isArray","isArray","arg","SPECIES","_arraySpeciesConstructor","original","constructor","_arraySpeciesCreate","speciesConstructor","_arrayMethods","TYPE","$create","IS_MAP","IS_FILTER","IS_SOME","IS_EVERY","IS_FIND_INDEX","NO_HOLES","create","asc","$this","callbackfn","res","IObject","UNSCOPABLES","_addToUnscopables","$find","KEY","forced","find","f$1","_toIobject","gOPD","getOwnPropertyDescriptor","f$2","toIObject","pIE","check","_setProto","setPrototypeOf","buggy","__proto__","_inheritIfRequired","max","_toAbsoluteIndex","_arrayIncludes","IS_INCLUDES","el","fromIndex","toAbsoluteIndex","shared","_sharedKey","arrayIndexOf","IE_PROTO","_objectKeysInternal","names","_enumBugKeys","hiddenKeys","f$3","getOwnPropertyNames","$keys","_stringWs","space","spaces","non","ltrim","RegExp","rtrim","exporter","ALIAS","FORCE","fails","trim","string","_stringTrim","_objectKeys","enumBugKeys","_objectDps","Properties","getKeys","_html","documentElement","Empty","createDict","iframeDocument","iframe","style","display","src","contentWindow","open","write","lt","close","_objectCreate","dPs","gOPN","$trim","require$$3","NUMBER","$Number","Base","BROKEN_COF","require$$4","TRIM","toNumber","argument","third","radix","maxCode","first","charCodeAt","NaN","code","digits","l","parseInt","inheritIfRequired","require$$5","j","require$$6","_objectSap","MATCH","_isRegexp","isRegExp","_stringContext","NAME","_failsIsRegexp","re","INCLUDES","includes","context","$includes","_sameValue","x","y","builtinExec","_regexpExecAbstract","_flags","ignoreCase","multiline","unicode","sticky","nativeExec","nativeReplace","patchedExec","LAST_INDEX","UPDATES_LAST_INDEX_WRONG","re1","re2","NPCG_INCLUDED","PATCH","str","lastIndex","reCopy","match","regexpFlags","_regexpExec","regexpExec","wks","REPLACE_SUPPORTS_NAMED_GROUPS","groups","SPLIT_WORKS_WITH_OVERWRITTEN_EXEC","originalExec","_fixReWks","SYMBOL","DELEGATES_TO_SYMBOL","DELEGATES_TO_EXEC","execCalled","nativeRegExpMethod","fns","nativeMethod","regexp","arg2","forceStringMethod","strfn","rxfn","SEARCH","$search","maybeCallNative","rx","previousLastIndex","sameValue","regExpExec","flags","TO_STRING","define","DESCRIPTORS","$flags","_iterStep","def","_setToStringTag","tag","stat","IteratorPrototype","_iterCreate","Constructor","descriptor","setToStringTag","ObjectProto","_objectGpo","getPrototypeOf","BUGGY","FF_ITERATOR","KEYS","VALUES","returnThis","_iterDefine","DEFAULT","IS_SET","FORCED","$iterCreate","methods","getMethod","kind","DEF_VALUES","VALUES_BUG","$native","$default","$entries","$anyNative","LIBRARY","es6_array_iterator","iterated","_t","_i","_k","Arguments","addToUnscopables","TO_STRING_TAG","ArrayValues","DOMIterables","CSSRuleList","CSSStyleDeclaration","CSSValueList","ClientRectList","DOMRectList","DOMStringList","DOMTokenList","DataTransferItemList","FileList","HTMLAllCollection","HTMLCollection","HTMLFormElement","HTMLSelectElement","MediaList","MimeTypeArray","NamedNodeMap","NodeList","PaintRequestList","Plugin","PluginArray","SVGLengthList","SVGNumberList","SVGPathSegList","SVGPointList","SVGStringList","SVGTransformList","SourceBufferList","StyleSheetList","TextTrackCueList","TextTrackList","TouchList","collections","explicit","Collection","$iterators","_stringAt","pos","s","charAt","$at","point","META","setDesc","isExtensible","FREEZE","preventExtensions","setMeta","w","meta","NEED","fastKey","getWeak","onFreeze","f$4","getOwnPropertySymbols","$assign","assign","_objectAssign","A","K","k","getSymbols","gOPS","isEnum","_redefineAll","_anInstance","forbiddenField","BREAK","RETURN","iterable","_validateCollection","arrayFind","createArrayMethod","arrayFindIndex","uncaughtFrozenStore","_l","UncaughtFrozenStore","findUncaughtFrozen","splice","_collectionWeak","getConstructor","wrapper","ADDER","anInstance","forOf","redefineAll","data","validate","$has","ufstore","_collection","common","IS_WEAK","fixMethod","instance","HASNT_CHAINING","THROWS_ON_PRIMITIVES","ACCEPT_ITERABLES","$iterDetect","BUGGY_ZERO","$instance","clear","setStrong","InternalMap","each","weak","tmp","$WeakMap","freeze","_f","_strictMethod","$sort","comparefn","_speciesConstructor","D","at","_advanceStringIndex","$min","$push","$SPLIT","LENGTH","MAX_UINT32","SUPPORTS_Y","SPLIT","$split","internalSplit","separator","limit","lastLength","output","lastLastIndex","splitLimit","separatorCopy","splitter","unicodeMatching","lim","callRegExpExec","p","q","z","advanceStringIndex","_objectToArray","isEntries","$values","SUBSTITUTION_SYMBOLS","SUBSTITUTION_SYMBOLS_NO_NAMED","maybeToString","REPLACE","$replace","searchValue","replaceValue","functionalReplace","fullUnicode","results","accumulatedResult","nextSourcePosition","matched","position","captures","namedCaptures","replacerArgs","replacement","getSubstitution","tailPos","m","symbols","ch","capture","n","defer","channel","_invoke","args","un","process","setTask","setImmediate","clearTask","clearImmediate","MessageChannel","Dispatch","counter","queue","ONREADYSTATECHANGE","run","listener","invoke","nextTick","now","port2","port1","onmessage","postMessage","addEventListener","importScripts","cel","html","removeChild","setTimeout","_task","macrotask","Observer","MutationObserver","WebKitMutationObserver","Promise","isNode","_microtask","last","notify","flush","parent","domain","exit","enter","navigator","standalone","resolve","promise","then","toggle","node","createTextNode","observe","characterData","task","PromiseCapability","reject","$$resolve","$$reject","Internal","newGenericPromiseCapability","OwnPromiseCapability","Wrapper","f$5","_perform","v","_userAgent","userAgent","_promiseResolve","promiseCapability","newPromiseCapability","_setSpecies","microtask","PROMISE","versions","v8","$Promise","empty","newPromiseCapabilityModule","USE_NATIVE","FakePromise","PromiseRejectionEvent","isThenable","isReject","_n","chain","_c","_v","ok","_s","reaction","exited","handler","fail","_h","onHandleUnhandled","onUnhandled","console","unhandled","isUnhandled","perform","emit","onunhandledrejection","reason","_a","onrejectionhandled","$reject","_d","_w","$resolve","executor","onFulfilled","onRejected","catch","r","capability","promiseResolve","require$$7","all","remaining","$index","alreadyCalled","race","STARTS_WITH","$startsWith","startsWith","number","input","instanceOf","Boolean","isNullOrUndefined","isNumber","Number","isString","isBoolean","isWeakMap","WeakMap","isNodeList","isElement","Element","isTextNode","Text","isEvent","isKeyboardEvent","KeyboardEvent","isCue","TextTrackCue","VTTCue","isTrack","TextTrack","isEmpty","isUrl","is$1","nullOrUndefined","boolean","function","array","weakMap","nodeList","element","textNode","keyboardEvent","cue","track","supportsPassiveListeners","supported","options","removeEventListener","toggleListener","passive","events","eventListeners","on","off","once","onceCallback","_len","_key","_this2","triggerEvent","plyr","dispatchEvent","unbindListeners","item","ready","_this3","elements","container","wrap","targets","reverse","child","cloneNode","parentNode","sibling","nextSibling","insertBefore","setAttributes","filter","_ref","_ref3","_ref4","setAttribute","text","innerText","insertAfter","insertElement","removeElement","emptyElement","childNodes","lastChild","replaceElement","newChild","oldChild","replaceChild","getAttributesFromSelector","sel","existingAttributes","existing","selector","className","parts","class","toggleHidden","hidden","removeAttribute","toggleClass","force","map","classList","contains","hasClass","matches","querySelectorAll","getElements","getElement","querySelector","trapFocus","focusable","keyCode","focused","activeElement","shiftKey","focus","setFocus","tabFocus","preventScroll","config","classNames","transitionEndEvent","WebkitTransition","MozTransition","OTransition","transition","repaint","offsetHeight","browser","isIE","documentMode","isEdge","isWebkit","isIPhone","platform","isIos","defaultCodecs","support","audio","video","provider","playsinline","canPlayInline","api","ui","rangeInput","pip","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","mime","mediaType","isHTML5","media","canPlayType","textTracks","range","touch","transitions","reducedMotion","matchMedia","html5","getSources","getAttribute","getQualityOptions","extend","player","currentTime","_player$media","paused","preload","readyState","play","load","quality","cancelRequests","blankVideo","debug","log","dedupe","closest","reduce","prev","curr","abs","cloneDeep","JSON","parse","stringify","getDeep","path","obj","sources","_defineProperty","$RegExp","CORRECT_NEW","tiRE","piRE","fiU","proxy","generateId","prefix","format","getPercentage","current","toFixed","replaceAll","toTitleCase","toUpperCase","substr","toLowerCase","toPascalCase","toCamelCase","stripHTML","fragment","createDocumentFragment","innerHTML","firstChild","getHTML","resources","vimeo","youtube","i18n","seekTime","title","_ref2","Storage","enabled","storage","localStorage","getItem","json","setItem","removeItem","fetch","responseType","request","XMLHttpRequest","responseText","response","status","send","loadSprite","hasId","exists","getElementById","update","insertAdjacentElement","useStorage","cached","content","trunc","getHours","getMinutes","getSeconds","formatTime","time","displayHours","inverted","hours","mins","secs","controls","getIconUrl","cors","iconUrl","host","svg4everybody","findElements","selectors","buttons","pause","restart","rewind","fastForward","mute","settings","captions","fullscreen","progress","inputs","seek","volume","buffer","duration","seekTooltip","tooltip","warn","toggleNativeControls","createIcon","iconPath","iconPrefix","icon","createElementNS","role","use","setAttributeNS","createLabel","attr","createBadge","badge","menu","createButton","buttonType","props","label","labelPressed","iconPressed","control","button","createRange","autocomplete","updateRangeFill","createProgress","suffixKey","played","suffix","createTime","bindMenuItemShortcuts","menuItem","which","stopPropagation","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","list","_ref$badge","checked","_ref$checked","flex","children","listeners","bind","currentTrack","speed","parseFloat","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","getElementsByTagName","nodeValue","setProgress","buffered","percent","setProperty","updateSeekTooltip","tooltips","clientRect","getBoundingClientRect","visible","_this4","width","pageX","left","timeUpdate","invert","invertTime","seeking","durationUpdate","pow","hasDuration","displayDuration","toggleMenuButton","setting","updateSetting","pane","panels","default","getLabel","setQualityMenu","_this5","checkMenu","getBadge","sorting","setCaptionsMenu","tracks","getTracks","_this6","toggled","language","unshift","setSpeedMenu","isVimeo","_this7","some","popup","firstItem","toggleMenu","show","isMenuItem","getMenuSize","tab","clone","opacity","scrollWidth","height","scrollHeight","size","restore","propertyName","_this8","setDownloadLink","download","inner","home","_this9","backButton","urls","isEmbed","inject","seektime","addProperty","_this10","controlPressed","_this$config","labels","parseUrl","parser","buildUrlParams","setup","isVideo","isYouTube","languages","userLanguage","active","trackEvents","_this$captions","currentTrackNode","languageExists","updateCues","setLanguage","activeClass","findTrack","_toConsumableArray","embed","enableTextTrack","sortIsDefault","sorted","every","getCurrentTrack","cues","activeCues","getCueAsHTML","cueText","caption","defaults","autoplay","autopause","toggleInvert","ratio","clickToPlay","hideControls","resetOnEnd","disableContextMenu","loop","selected","keyboard","fallback","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","start","end","reset","disabled","advertisement","qualityBadge","sdk","googleIMA","editable","embedContainer","poster","posterEnabled","ads","playing","stopped","loading","hover","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","google","publisherId","tagUrl","byline","portrait","transparent","noCookie","rel","showinfo","iv_load_policy","modestbranding","inactive","providers","types","getProviderByUrl","noop","Console","onChange","toggleFallback","scrollPosition","scrollX","scrollY","scrollTo","overflow","viewport","property","hasProperty","cleanupViewport","part","Fullscreen","forceFallback","native","webkitEnterFullscreen","requestFullscreen","webkitExitFullscreen","action","cancelFullScreen","fullscreenElement","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","pre","_mathSign","sign","loadImage","minWidth","image","Image","onload","onerror","naturalWidth","addStyleHook","build","checkPlaying","setTitle","setPoster","togglePoster","enable","backgroundImage","backgroundSize","toggleControls","checkLoading","clearTimeout","timers","recentTouchSeek","lastSeekTime","Date","setAspectRatio","padding","_ratio$split$map2","paddingBottom","offset","transform","Listeners","lastKey","focusTimer","lastKeyDown","handleKey","setTabFocus","firstTouch","repeat","altKey","ctrlKey","metaKey","togglePlay","increaseVolume","decreaseVolume","forward","toggleCaptions","usingNative","timeStamp","wasKeyDown","delay","setPlayerSize","measure","rect","resized","_player$fullscreen","isEnter","_setPlayerSize","videoWidth","_player$embed$ratio$s2","videoHeight","maxWidth","margin","setGutter","hasAudio","initialized","managerPromise","isAudio","ended","proxyEvents","_event$detail","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","currentTarget","hasAttribute","seekTo","loaded","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","deltaX","deltaY","_map2","direction","FProto","nameRE","$match","matchStr","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","executeCallbacks","depsNotFound","success","loadFile","callbackFn","numTries","isCss","async","maxTries","numRetries","beforeCallbackFn","before","pathStripped","onbeforeload","ev","sheet","cssText","loadjs","paths","arg1","numWaiting","loadFiles","deps","bundleIds","subscribe","isDefined","factory","loadScript","parseId","$2","assurePlaybackState","hasPlayed","Vimeo","gesture","thumbnail_large","Player","disableTextTrack","stop","restorePause","setVolume","setCurrentTime","setPlaybackRate","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","dimensions","_dimensions","setAutopause","state","getVideoTitle","getCurrentTime","getDuration","getTextTracks","strippedCues","_ref$cues","getPaused","seconds","YT","onYouTubeReadyCallbacks","onYouTubeIframeAPIReady","getTitle","videoId","getVideoData","snippet","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","onError","message","onPlaybackRateChange","playbackRate","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","getAvailablePlaybackRates","clearInterval","buffering","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","displayContainer","manager","loader","cuePoints","safetyTimer","countdownTimer","ima","trigger","startSafetyTimer","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setLocale","AdDisplayContainer","requestAds","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","AdsRequest","adTagUrl","linearAdSlotWidth","offsetWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","getCuePoints","cuePoint","seekElement","cuePercentage","AdEvent","onAdEvent","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","ALL_ADS_COMPLETED","loadAds","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","STARTED","MIDPOINT","COMPLETE","IMPRESSION","CLICK","LOG","adError","getMessage","cancel","contentComplete","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","initialize","init","zIndex","destroy","handlers","_this11","_this12","AV_PUBLISHERID","AV_CHANNELID","AV_URL","cb","AV_WIDTH","AV_HEIGHT","AV_CDIM2","findIndex","parseVtt","vttDataString","processedList","frame","line","startTime","lineSplit","_lineSplit","_lineSplit$1$split2","h","matchTimes","endTime","PreviewThumbnails","thumbnails","lastMouseMoveTime","mouseDown","loadedImages","thumb","scrubbing","getThumbnails","render","determineContainerAutoSizing","promises","getThumbnail","thumbnail","frames","urlPrefix","substring","lastIndexOf","tempImage","naturalHeight","percentage","mousePosX","showImageAtCurrentTime","toggleThumbContainer","toggleScrubbingContainer","lastTime","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","hasThumb","qualityIndex","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","filename","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","tagName","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","clientHeight","sizeSpecifiedInCSS","thumbWidth","thumbAspectRatio","setThumbContainerPos","seekbarRect","plyrRect","minVal","maxVal","right","clientWidth","previewPos","multiplier","top","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","change","_sources$$provider","_sources$","crossorigin","Plyr","failed","jQuery","truthy","tabindex","webkitShowPlaybackTargetPicker","isHidden","hiding","eventName","soft","unload","inputIsValid","fauxDuration","realDuration","Infinity","mozHasAudio","webkitAudioDecodedByteCount","audioTracks","updateStorage","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","inline","t"],"mappings":"4BAMA,WACE,GAAsB,oBAAXA,OAIX,IACE,IAAIC,EAAK,IAAID,OAAOE,YAAY,OAAQ,CAAEC,YAAY,IAEtD,GADAF,EAAGG,kBACyB,IAAxBH,EAAGI,iBAGL,MAAM,IAAIC,MAAM,6BAElB,MAAOC,GACP,IAAIL,EAAc,SAASM,EAAOC,GAChC,IAAIC,EAAKC,EA2BT,OA1BAF,EAASA,GAAU,CACjBG,SAAS,EACTT,YAAY,EACZU,YAAQC,IAGVJ,EAAMK,SAASC,YAAY,gBACvBC,gBACFT,EACAC,EAAOG,QACPH,EAAON,WACPM,EAAOI,QAETF,EAAcD,EAAIN,eAClBM,EAAIN,eAAiB,WACnBO,EAAYO,KAAKC,MACjB,IACEC,OAAOC,eAAeF,KAAM,mBAAoB,CAC9CG,IAAK,WACH,OAAO,KAGX,MAAOf,GACPY,KAAKd,kBAAmB,IAGrBK,GAGTR,EAAYqB,UAAYvB,OAAOwB,MAAMD,UACrCvB,OAAOE,YAAcA,GA9CzB,4MCNA,SAAUuB,GAOR,IASIC,EAT6B,WAC/B,IACE,QAASC,OAAOC,SAChB,MAAOC,GACP,OAAO,GAKaC,GAEpBC,EAAiB,SAASC,GAC5B,IAAIJ,EAAW,CACbK,KAAM,WACJ,IAAIC,EAAQF,EAAMG,QAClB,MAAO,CAAEC,UAAgB,IAAVF,EAAkBA,MAAOA,KAU5C,OANIR,IACFE,EAASD,OAAOC,UAAY,WAC1B,OAAOA,IAIJA,GAOLS,EAAiB,SAASH,GAC5B,OAAOI,mBAAmBJ,GAAOK,QAAQ,OAAQ,MAG/CC,EAAmB,SAASN,GAC9B,OAAOO,mBAAmBP,GAAOK,QAAQ,MAAO,MA4H5C,oBAAqBd,GAAuD,QAA3C,IAAIiB,gBAAgB,QAAQC,YAzHrC,WAE5B,IAAID,EAAkB,SAASE,GAC7BxB,OAAOC,eAAeF,KAAM,WAAY,CAAE0B,UAAU,EAAMX,MAAO,KACjE,IAAIY,SAA4BF,EAEhC,GAA2B,cAAvBE,QAEG,GAA2B,WAAvBA,EACY,KAAjBF,GACFzB,KAAK4B,YAAYH,QAEd,GAAIA,aAAwBF,EAAiB,CAClD,IAAIM,EAAQ7B,KACZyB,EAAaK,QAAQ,SAASf,EAAOgB,GACnCF,EAAMG,OAAOD,EAAMhB,SAEhB,CAAA,GAAsB,OAAjBU,GAAkD,WAAvBE,EAkBrC,MAAM,IAAIM,UAAU,gDAjBpB,GAAqD,mBAAjDhC,OAAOG,UAAUoB,SAASzB,KAAK0B,GACjC,IAAK,IAAIS,EAAI,EAAGA,EAAIT,EAAaU,OAAQD,IAAK,CAC5C,IAAIE,EAAQX,EAAaS,GACzB,GAA+C,mBAA1CjC,OAAOG,UAAUoB,SAASzB,KAAKqC,IAAkD,IAAjBA,EAAMD,OAGzE,MAAM,IAAIF,UAAU,4CAA8CC,EAAI,+BAFtElC,KAAKgC,OAAOI,EAAM,GAAIA,EAAM,SAMhC,IAAK,IAAIC,KAAOZ,EACVA,EAAaa,eAAeD,IAC9BrC,KAAKgC,OAAOK,EAAKZ,EAAaY,MASpCE,EAAQhB,EAAgBnB,UAE5BmC,EAAMP,OAAS,SAASD,EAAMhB,GACxBgB,KAAQ/B,KAAKwC,SACfxC,KAAKwC,SAAST,GAAMU,KAAKC,OAAO3B,IAEhCf,KAAKwC,SAAST,GAAQ,CAACW,OAAO3B,KAIlCwB,EAAMI,OAAS,SAASZ,UACf/B,KAAKwC,SAAST,IAGvBQ,EAAMpC,IAAM,SAAS4B,GACnB,OAAQA,KAAQ/B,KAAKwC,SAAYxC,KAAKwC,SAAST,GAAM,GAAK,MAG5DQ,EAAMK,OAAS,SAASb,GACtB,OAAQA,KAAQ/B,KAAKwC,SAAYxC,KAAKwC,SAAST,GAAMc,MAAM,GAAK,IAGlEN,EAAMO,IAAM,SAASf,GACnB,OAAQA,KAAQ/B,KAAKwC,UAGvBD,EAAMQ,IAAM,SAAShB,EAAMhB,GACzBf,KAAKwC,SAAST,GAAQ,CAACW,OAAO3B,KAGhCwB,EAAMT,QAAU,SAASkB,EAAUC,GACjC,IAAIC,EACJ,IAAK,IAAInB,KAAQ/B,KAAKwC,SACpB,GAAIxC,KAAKwC,SAASF,eAAeP,GAAO,CACtCmB,EAAUlD,KAAKwC,SAAST,GACxB,IAAK,IAAIG,EAAI,EAAGA,EAAIgB,EAAQf,OAAQD,IAClCc,EAASjD,KAAKkD,EAASC,EAAQhB,GAAIH,EAAM/B,QAMjDuC,EAAMY,KAAO,WACX,IAAItC,EAAQ,GAIZ,OAHAb,KAAK8B,QAAQ,SAASf,EAAOgB,GAC3BlB,EAAM4B,KAAKV,KAENnB,EAAeC,IAGxB0B,EAAMa,OAAS,WACb,IAAIvC,EAAQ,GAIZ,OAHAb,KAAK8B,QAAQ,SAASf,GACpBF,EAAM4B,KAAK1B,KAENH,EAAeC,IAGxB0B,EAAMW,QAAU,WACd,IAAIrC,EAAQ,GAIZ,OAHAb,KAAK8B,QAAQ,SAASf,EAAOgB,GAC3BlB,EAAM4B,KAAK,CAACV,EAAMhB,MAEbH,EAAeC,IAGpBN,IACFgC,EAAM/B,OAAOC,UAAY8B,EAAMW,SAGjCX,EAAMf,SAAW,WACf,IAAI6B,EAAc,GAIlB,OAHArD,KAAK8B,QAAQ,SAASf,EAAOgB,GAC3BsB,EAAYZ,KAAKvB,EAAea,GAAQ,IAAMb,EAAeH,MAExDsC,EAAYC,KAAK,MAI1BhD,EAAOiB,gBAAkBA,EAIzBgC,GAGF,IAAIhB,EAAQhB,gBAAgBnB,UAEF,mBAAfmC,EAAMiB,OACfjB,EAAMiB,KAAO,WACX,IAAI3B,EAAQ7B,KACRa,EAAQ,GACZb,KAAK8B,QAAQ,SAASf,EAAOgB,GAC3BlB,EAAM4B,KAAK,CAACV,EAAMhB,IACbc,EAAMW,UACTX,EAAMc,OAAOZ,KAGjBlB,EAAM2C,KAAK,SAASC,EAAGC,GACrB,OAAID,EAAE,GAAKC,EAAE,IACH,EACCD,EAAE,GAAKC,EAAE,GACX,EAEA,IAGP7B,EAAMW,WACRX,EAAMW,SAAW,IAEnB,IAAK,IAAIN,EAAI,EAAGA,EAAIrB,EAAMsB,OAAQD,IAChClC,KAAKgC,OAAOnB,EAAMqB,GAAG,GAAIrB,EAAMqB,GAAG,MAKP,mBAAtBK,EAAMX,aACf3B,OAAOC,eAAeqC,EAAO,cAAe,CAC1CoB,YAAY,EACZC,cAAc,EACdlC,UAAU,EACVX,MAAO,SAASU,GACd,GAAIzB,KAAKwC,SACPxC,KAAKwC,SAAW,OACX,CACL,IAAIW,EAAO,GACXnD,KAAK8B,QAAQ,SAASf,EAAOgB,GAC3BoB,EAAKV,KAAKV,KAEZ,IAAK,IAAIG,EAAI,EAAGA,EAAIiB,EAAKhB,OAAQD,IAC/BlC,KAAK2C,OAAOQ,EAAKjB,IAKrB,IACI2B,EADAC,GADJrC,EAAeA,EAAaL,QAAQ,MAAO,KACb2C,MAAM,KAEpC,IAAS7B,EAAI,EAAGA,EAAI4B,EAAW3B,OAAQD,IACrC2B,EAAYC,EAAW5B,GAAG6B,MAAM,KAChC/D,KAAKgC,OACHX,EAAiBwC,EAAU,IAC1BA,EAAU1B,OAAS,EAAKd,EAAiBwC,EAAU,IAAM,OAnOtE,MA6OqB,IAAXvD,eAA0BA,eACV,oBAAXzB,OAA0BA,OACjB,oBAATmF,KAAwBA,KAAOhE,gBAG9C,SAAUM,GAiNR,GA1M4B,WAC1B,IACE,IAAI2D,EAAI,IAAIC,IAAI,IAAK,YAErB,OADAD,EAAEE,SAAW,QACM,mBAAXF,EAAEG,MAA8BH,EAAEI,aAC1C,MAAOjF,GACP,OAAO,GAgMNkF,IA3La,WAChB,IAAIC,EAAOjE,EAAO4D,IAEdA,EAAM,SAASM,EAAKC,GACH,iBAARD,IAAkBA,EAAM9B,OAAO8B,IAG1C,IAAoBE,EAAhBC,EAAM/E,SACV,GAAI6E,SAA6B,IAApBnE,EAAOsE,UAAuBH,IAASnE,EAAOsE,SAASR,MAAO,EAEzEM,GADAC,EAAM/E,SAASiF,eAAeC,mBAAmB,KAC/BC,cAAc,SACpBX,KAAOK,EACnBE,EAAIK,KAAKC,YAAYP,GACrB,IACE,GAAuC,IAAnCA,EAAYN,KAAKc,QAAQT,GAAa,MAAM,IAAItF,MAAMuF,EAAYN,MACtE,MAAOe,GACP,MAAM,IAAIhG,MAAM,0BAA4BsF,EAAO,WAAaU,IAIpE,IAAIC,EAAgBT,EAAII,cAAc,KAOtC,GANAK,EAAchB,KAAOI,EACjBE,IACFC,EAAIU,KAAKJ,YAAYG,GACrBA,EAAchB,KAAOgB,EAAchB,MAGN,MAA3BgB,EAAcE,WAAqB,IAAIC,KAAKH,EAAchB,MAC5D,MAAM,IAAInC,UAAU,eAGtBhC,OAAOC,eAAeF,KAAM,iBAAkB,CAC5Ce,MAAOqE,IAKT,IAAIf,EAAe,IAAI9C,gBAAgBvB,KAAKwF,QACxCC,GAAqB,EACrBC,GAA2B,EAC3B7D,EAAQ7B,KACZ,CAAC,SAAU,SAAU,OAAO8B,QAAQ,SAAS6D,GAC3C,IAAIC,EAASvB,EAAasB,GAC1BtB,EAAasB,GAAc,WACzBC,EAAOC,MAAMxB,EAAcyB,WACvBL,IACFC,GAA2B,EAC3B7D,EAAM2D,OAASnB,EAAa7C,WAC5BkE,GAA2B,MAKjCzF,OAAOC,eAAeF,KAAM,eAAgB,CAC1Ce,MAAOsD,EACPV,YAAY,IAGd,IAAI6B,OAAS,EACbvF,OAAOC,eAAeF,KAAM,sBAAuB,CACjD2D,YAAY,EACZC,cAAc,EACdlC,UAAU,EACVX,MAAO,WACDf,KAAKwF,SAAWA,IAClBA,EAASxF,KAAKwF,OACVE,IACFD,GAAqB,EACrBzF,KAAKqE,aAAazC,YAAY5B,KAAKwF,QACnCC,GAAqB,QAO3BlD,EAAQ2B,EAAI9D,UAchB,CAAC,OAAQ,OAAQ,WAAY,OAAQ,YAClC0B,QAAQ,SAASiE,IAba,SAASA,GACxC9F,OAAOC,eAAeqC,EAAOwD,EAAe,CAC1C5F,IAAK,WACH,OAAOH,KAAKgG,eAAeD,IAE7BhD,IAAK,SAAShC,GACZf,KAAKgG,eAAeD,GAAiBhF,GAEvC4C,YAAY,IAMZsC,CAA2BF,KAG/B9F,OAAOC,eAAeqC,EAAO,SAAU,CACrCpC,IAAK,WACH,OAAOH,KAAKgG,eAAuB,QAErCjD,IAAK,SAAShC,GACZf,KAAKgG,eAAuB,OAAIjF,EAChCf,KAAKkG,uBAEPvC,YAAY,IAGd1D,OAAOkG,iBAAiB5D,EAAO,CAE7Bf,SAAY,CACVrB,IAAK,WACH,IAAI0B,EAAQ7B,KACZ,OAAO,WACL,OAAO6B,EAAMuC,QAKnBA,KAAQ,CACNjE,IAAK,WACH,OAAOH,KAAKgG,eAAe5B,KAAKhD,QAAQ,MAAO,KAEjD2B,IAAK,SAAShC,GACZf,KAAKgG,eAAe5B,KAAOrD,EAC3Bf,KAAKkG,uBAEPvC,YAAY,GAGdQ,SAAY,CACVhE,IAAK,WACH,OAAOH,KAAKgG,eAAe7B,SAAS/C,QAAQ,SAAU,MAExD2B,IAAK,SAAShC,GACZf,KAAKgG,eAAe7B,SAAWpD,GAEjC4C,YAAY,GAGdyC,OAAU,CACRjG,IAAK,WAEH,IAAIkG,EAAe,CAAEC,QAAS,GAAIC,SAAU,IAAKC,OAAQ,IAAKxG,KAAKgG,eAAeV,UAI9EmB,EAAkBzG,KAAKgG,eAAeU,MAAQL,GACnB,KAA7BrG,KAAKgG,eAAeU,KAEtB,OAAO1G,KAAKgG,eAAeV,SACzB,KACAtF,KAAKgG,eAAeW,UACnBF,EAAmB,IAAMzG,KAAKgG,eAAeU,KAAQ,KAE1D/C,YAAY,GAGdiD,SAAY,CACVzG,IAAK,WACH,MAAO,IAET4C,IAAK,SAAShC,KAEd4C,YAAY,GAGdkD,SAAY,CACV1G,IAAK,WACH,MAAO,IAET4C,IAAK,SAAShC,KAEd4C,YAAY,KAIhBO,EAAI4C,gBAAkB,SAASC,GAC7B,OAAOxC,EAAKuC,gBAAgBjB,MAAMtB,EAAMuB,YAG1C5B,EAAI8C,gBAAkB,SAASxC,GAC7B,OAAOD,EAAKyC,gBAAgBnB,MAAMtB,EAAMuB,YAG1CxF,EAAO4D,IAAMA,EAKb+C,QAGuB,IAApB3G,EAAOsE,YAA0B,WAAYtE,EAAOsE,UAAW,CAClE,IAAIsC,EAAY,WACd,OAAO5G,EAAOsE,SAASU,SAAW,KAAOhF,EAAOsE,SAAS+B,UAAYrG,EAAOsE,SAAS8B,KAAQ,IAAMpG,EAAOsE,SAAS8B,KAAQ,KAG7H,IACEzG,OAAOC,eAAeI,EAAOsE,SAAU,SAAU,CAC/CzE,IAAK+G,EACLvD,YAAY,IAEd,MAAOvE,GACP+H,YAAY,WACV7G,EAAOsE,SAASwB,OAASc,KACxB,OA9NT,MAmOqB,IAAX5G,eAA0BA,eACV,oBAAXzB,OAA0BA,OACjB,oBAATmF,KAAwBA,KAAOhE,gBCvd9C,IAAAoH,WAAiB,SAAUC,GACzB,GAAiB,mBAANA,EAAkB,MAAMpF,UAAUoF,EAAK,uBAClD,OAAOA,GCATC,KAAiB,SAAUC,EAAIC,EAAMrF,GAEnC,GADAsF,WAAUF,QACG5H,IAAT6H,EAAoB,OAAOD,EAC/B,OAAQpF,GACN,KAAK,EAAG,OAAO,SAAUsB,GACvB,OAAO8D,EAAGxH,KAAKyH,EAAM/D,IAEvB,KAAK,EAAG,OAAO,SAAUA,EAAGC,GAC1B,OAAO6D,EAAGxH,KAAKyH,EAAM/D,EAAGC,IAE1B,KAAK,EAAG,OAAO,SAAUD,EAAGC,EAAGgE,GAC7B,OAAOH,EAAGxH,KAAKyH,EAAM/D,EAAGC,EAAGgE,IAG/B,OAAO,WACL,OAAOH,EAAG1B,MAAM2B,EAAM1B,sDChB1B,IAAIxF,EAASqH,EAAAC,QAAkC,oBAAV/I,QAAyBA,OAAOgJ,MAAQA,KACzEhJ,OAAwB,oBAARmF,MAAuBA,KAAK6D,MAAQA,KAAO7D,KAE3D8D,SAAS,cAATA,GACc,iBAAPC,MAAiBA,IAAMzH,4CCLlC,IAAI0H,EAAOL,EAAAC,QAAiB,CAAEK,QAAS,SACrB,iBAAPC,MAAiBA,IAAMF,2BCDlCG,UAAiB,SAAUd,GACzB,MAAqB,iBAAPA,EAAyB,OAAPA,EAA4B,mBAAPA,GCAvDe,UAAiB,SAAUf,GACzB,IAAKgB,UAAShB,GAAK,MAAMpF,UAAUoF,EAAK,sBACxC,OAAOA,GCHTiB,OAAiB,SAAUC,GACzB,IACE,QAASA,IACT,MAAOnJ,GACP,OAAO,ICHXoJ,cAAkBC,OAAoB,WACpC,OAA+E,GAAxExI,OAAOC,eAAe,GAAI,IAAK,CAAEC,IAAK,WAAc,OAAO,KAAQsD,ICDxE7D,WAAW6I,QAAqB7I,SAEhC8I,GAAKL,UAASzI,aAAayI,UAASzI,WAASmF,eACjD4D,WAAiB,SAAUtB,GACzB,OAAOqB,GAAK9I,WAASmF,cAAcsC,GAAM,ICL3CuB,eAAkBH,eAA8BI,OAAoB,WAClE,OAA4G,GAArG5I,OAAOC,eAAe4I,WAAyB,OAAQ,IAAK,CAAE3I,IAAK,WAAc,OAAO,KAAQsD,ICGzGsF,aAAiB,SAAU1B,EAAI2B,GAC7B,IAAKX,UAAShB,GAAK,OAAOA,EAC1B,IAAIE,EAAI0B,EACR,GAAID,GAAkC,mBAArBzB,EAAKF,EAAG7F,YAA4B6G,UAASY,EAAM1B,EAAGxH,KAAKsH,IAAM,OAAO4B,EACzF,GAAgC,mBAApB1B,EAAKF,EAAG6B,WAA2Bb,UAASY,EAAM1B,EAAGxH,KAAKsH,IAAM,OAAO4B,EACnF,IAAKD,GAAkC,mBAArBzB,EAAKF,EAAG7F,YAA4B6G,UAASY,EAAM1B,EAAGxH,KAAKsH,IAAM,OAAO4B,EAC1F,MAAMhH,UAAU,4CCPdkH,GAAKlJ,OAAOC,eAEhBkJ,EAAYX,aAA4BxI,OAAOC,eAAiB,SAAwBmJ,EAAGC,EAAGC,GAI5F,GAHAC,UAASH,GACTC,EAAIG,aAAYH,GAAG,GACnBE,UAASD,GACLG,cAAgB,IAClB,OAAOP,GAAGE,EAAGC,EAAGC,GAChB,MAAOnK,IACT,GAAI,QAASmK,GAAc,QAASA,EAAY,MAAMtH,UAAU,4BAEhE,MADI,UAAWsH,IAAYF,EAAEC,GAAKC,EAAWxI,OACtCsI,mBCdTM,cAAiB,SAAUC,EAAQ7I,GACjC,MAAO,CACL4C,aAAuB,EAATiG,GACdhG,eAAyB,EAATgG,GAChBlI,WAAqB,EAATkI,GACZ7I,MAAOA,ICHX8I,MAAiBpB,aAA4B,SAAUqB,EAAQzH,EAAKtB,GAClE,OAAOoI,UAAGC,EAAEU,EAAQzH,EAAK0H,cAAW,EAAGhJ,KACrC,SAAU+I,EAAQzH,EAAKtB,GAEzB,OADA+I,EAAOzH,GAAOtB,EACP+I,GCNLxH,eAAiB,GAAGA,eACxB0H,KAAiB,SAAU3C,EAAIhF,GAC7B,OAAOC,eAAevC,KAAKsH,EAAIhF,ICF7B4H,GAAK,EACLC,GAAKrC,KAAKsC,SACdC,KAAiB,SAAU/H,GACzB,MAAO,UAAUgI,YAAe1K,IAAR0C,EAAoB,GAAKA,EAAK,QAAS4H,GAAKC,IAAI1I,SAAS,iDCAnF,IAAI8I,EAAM7B,KAAkB,OAExB8B,EAAYzC,SAAkB,SAC9B0C,GAAO,GAAKD,GAAWxG,MAFX,YAIhB8E,MAAmB4B,cAAgB,SAAUpD,GAC3C,OAAOkD,EAAUxK,KAAKsH,KAGvBM,EAAAC,QAAiB,SAAUyB,EAAGhH,EAAK4G,EAAKyB,GACvC,IAAIC,EAA2B,mBAAP1B,EACpB0B,IAAY7H,KAAImG,EAAK,SAAW2B,MAAK3B,EAAK,OAAQ5G,IAClDgH,EAAEhH,KAAS4G,IACX0B,IAAY7H,KAAImG,EAAKqB,IAAQM,MAAK3B,EAAKqB,EAAKjB,EAAEhH,GAAO,GAAKgH,EAAEhH,GAAOmI,EAAIlH,KAAKZ,OAAOL,MACnFgH,IAAM/I,QACR+I,EAAEhH,GAAO4G,EACCyB,EAGDrB,EAAEhH,GACXgH,EAAEhH,GAAO4G,EAET2B,MAAKvB,EAAGhH,EAAK4G,WALNI,EAAEhH,GACTuI,MAAKvB,EAAGhH,EAAK4G,OAOdnB,SAAS1H,UAxBI,WAwBkB,WAChC,MAAsB,mBAARJ,MAAsBA,KAAKsK,IAAQC,EAAUxK,KAAKC,UCxB9D6K,UAAY,YAEZC,QAAU,SAAUC,EAAMhJ,EAAMiJ,GAClC,IAQI3I,EAAK4I,EAAKC,EAAKC,EARfC,EAAYL,EAAOD,QAAQO,EAC3BC,EAAYP,EAAOD,QAAQS,EAC3BC,EAAYT,EAAOD,QAAQ9B,EAC3ByC,EAAWV,EAAOD,QAAQxB,EAC1BoC,EAAUX,EAAOD,QAAQa,EACzBC,EAASN,EAAYhL,QAASkL,EAAYlL,QAAOyB,KAAUzB,QAAOyB,GAAQ,KAAOzB,QAAOyB,IAAS,IAAI8I,WACrGjD,EAAU0D,EAAYtD,MAAOA,MAAKjG,KAAUiG,MAAKjG,GAAQ,IACzD8J,EAAWjE,EAAQiD,aAAejD,EAAQiD,WAAa,IAG3D,IAAKxI,KADDiJ,IAAWN,EAASjJ,GACZiJ,EAIVE,IAFAD,GAAOG,GAAaQ,QAA0BjM,IAAhBiM,EAAOvJ,IAExBuJ,EAASZ,GAAQ3I,GAE9B8I,EAAMO,GAAWT,EAAMa,KAAIZ,EAAK5K,SAAUmL,GAA0B,mBAAPP,EAAoBY,KAAIhE,SAAS/H,KAAMmL,GAAOA,EAEvGU,GAAQG,UAASH,EAAQvJ,EAAK6I,EAAKH,EAAOD,QAAQkB,GAElDpE,EAAQvF,IAAQ6I,GAAKN,MAAKhD,EAASvF,EAAK8I,GACxCM,GAAYI,EAASxJ,IAAQ6I,IAAKW,EAASxJ,GAAO6I,IAG1D5K,QAAO0H,KAAOA,MAEd8C,QAAQO,EAAI,EACZP,QAAQS,EAAI,EACZT,QAAQ9B,EAAI,EACZ8B,QAAQxB,EAAI,EACZwB,QAAQa,EAAI,GACZb,QAAQmB,EAAI,GACZnB,QAAQkB,EAAI,GACZlB,QAAQoB,EAAI,IACZ,IAAAC,QAAiBrB,QCzCjBsB,SAAiB,SAAU/E,GACzB,GAAU1H,MAAN0H,EAAiB,MAAMpF,UAAU,yBAA2BoF,GAChE,OAAOA,GCDTgF,UAAiB,SAAUhF,GACzB,OAAOpH,OAAOqM,SAAQjF,KCDxBkF,UAAiB,SAAU9L,EAAU8G,EAAIxG,EAAOmC,GAC9C,IACE,OAAOA,EAAUqE,EAAGiC,UAASzI,GAAO,GAAIA,EAAM,IAAMwG,EAAGxG,GAEvD,MAAO3B,GACP,IAAIoN,EAAM/L,EAAiB,OAE3B,WADYd,IAAR6M,GAAmBhD,UAASgD,EAAIzM,KAAKU,IACnCrB,ICTVqN,WAAiB,GCAjBC,UAAiB,2CCEjB,IACIC,EAAQrM,QADC,wBACkBA,QADlB,sBACmC,KAE/CqH,EAAAC,QAAiB,SAAUvF,EAAKtB,GAC/B,OAAO4L,EAAMtK,KAASsK,EAAMtK,QAAiB1C,IAAVoB,EAAsBA,EAAQ,MAChE,WAAY,IAAI0B,KAAK,CACtBwF,QAASD,MAAKC,QACd2E,KAAM,SACNC,UAAW,iFCVb,IAAIF,EAAQlE,QAAqB,OAE7BjI,EAASqI,QAAqBrI,OAC9BsM,EAA8B,mBAAVtM,GAETmH,EAAAC,QAAiB,SAAU7F,GACxC,OAAO4K,EAAM5K,KAAU4K,EAAM5K,GAC3B+K,GAActM,EAAOuB,KAAU+K,EAAatM,EAASuM,MAAK,UAAYhL,MAGjE4K,MAAQA,ICRbK,SAAWvE,KAAkB,YAC7BwE,WAAaC,MAAM9M,UAEvB+M,aAAiB,SAAU9F,GACzB,YAAc1H,IAAP0H,IAAqB+F,WAAUF,QAAU7F,GAAM4F,WAAWD,YAAc3F,ICL7EgG,KAAOxF,KAAKwF,KACZC,MAAQzF,KAAKyF,MACjBC,WAAiB,SAAUlG,GACzB,OAAOmG,MAAMnG,GAAMA,GAAM,GAAKA,EAAK,EAAIiG,MAAQD,MAAMhG,ICFnDoG,IAAM5F,KAAK4F,IACfC,UAAiB,SAAUrG,GACzB,OAAOA,EAAK,EAAIoG,IAAIE,WAAUtG,GAAK,kBAAoB,GCAzDuG,gBAAiB,SAAU9D,EAAQ+D,EAAO9M,GACpC8M,KAAS/D,EAAQgE,UAAgB1E,EAAEU,EAAQ+D,EAAO9D,cAAW,EAAGhJ,IAC/D+I,EAAO+D,GAAS9M,GCNnBS,SAAW,GAAGA,SAElBuM,KAAiB,SAAU1G,GACzB,OAAO7F,SAASzB,KAAKsH,GAAIxE,MAAM,GAAI,ICDjCmL,IAAMvF,KAAkB,eAExBwF,IAAkD,aAA5CC,KAAI,WAAc,OAAOpI,UAArB,IAGVqI,OAAS,SAAU9G,EAAIhF,GACzB,IACE,OAAOgF,EAAGhF,GACV,MAAOjD,MAGXgP,SAAiB,SAAU/G,GACzB,IAAIgC,EAAGgF,EAAG1C,EACV,YAAchM,IAAP0H,EAAmB,YAAqB,OAAPA,EAAc,OAEN,iBAApCgH,EAAIF,OAAO9E,EAAIpJ,OAAOoH,GAAK2G,MAAoBK,EAEvDJ,IAAMC,KAAI7E,GAEM,WAAfsC,EAAIuC,KAAI7E,KAAsC,mBAAZA,EAAEiF,OAAuB,YAAc3C,GCpB5EqB,WAAWvE,KAAkB,YAEjC8F,uBAAiB1F,MAAmB2F,kBAAoB,SAAUnH,GAChE,GAAU1H,MAAN0H,EAAiB,OAAOA,EAAG2F,aAC1B3F,EAAG,eACH+F,WAAUqB,SAAQpH,KCNrB2F,WAAWvE,KAAkB,YAC7BiG,cAAe,EAEnB,IACE,IAAIC,MAAQ,CAAC,GAAG3B,cAChB2B,MAAc,OAAI,WAAcD,cAAe,GAG/C,MAAOtP,IAET,IAAAwP,YAAiB,SAAUrG,EAAMsG,GAC/B,IAAKA,IAAgBH,aAAc,OAAO,EAC1C,IAAIhE,GAAO,EACX,IACE,IAAIoE,EAAM,CAAC,GACPC,EAAOD,EAAI9B,cACf+B,EAAKjO,KAAO,WAAc,MAAO,CAAEG,KAAMyJ,GAAO,IAChDoE,EAAI9B,YAAY,WAAc,OAAO+B,GACrCxG,EAAKuG,GACL,MAAO1P,IACT,OAAOsL,GCVTI,QAAQA,QAAQ9B,EAAI8B,QAAQO,GAAK5C,YAA0B,SAAUsG,MAA8B,QAAS,CAE1GC,KAAM,SAAcC,GAClB,IAOI9M,EAAQ+M,EAAQC,EAAM1O,EAPtB4I,EAAI+F,UAASH,GACbI,EAAmB,mBAARrP,KAAqBA,KAAOkN,MACvCoC,EAAOxJ,UAAU3D,OACjBoN,EAAQD,EAAO,EAAIxJ,UAAU,QAAKnG,EAClC6P,OAAoB7P,IAAV4P,EACV1B,EAAQ,EACR4B,EAASC,uBAAUrG,GAIvB,GAFImG,IAASD,EAAQzD,KAAIyD,EAAOD,EAAO,EAAIxJ,UAAU,QAAKnG,EAAW,IAEvDA,MAAV8P,GAAyBJ,GAAKnC,OAASyC,aAAYF,GAMrD,IAAKP,EAAS,IAAIG,EADlBlN,EAASyN,UAASvG,EAAElH,SACSA,EAAS0L,EAAOA,IAC3CgC,gBAAeX,EAAQrB,EAAO2B,EAAUD,EAAMlG,EAAEwE,GAAQA,GAASxE,EAAEwE,SANrE,IAAKpN,EAAWgP,EAAO1P,KAAKsJ,GAAI6F,EAAS,IAAIG,IAAOF,EAAO1O,EAASK,QAAQG,KAAM4M,IAChFgC,gBAAeX,EAAQrB,EAAO2B,EAAUzP,UAAKU,EAAU8O,EAAO,CAACJ,EAAKpO,MAAO8M,IAAQ,GAAQsB,EAAKpO,OASpG,OADAmO,EAAO/M,OAAS0L,EACTqB,KC/BX,IAAAY,SAAiB7P,OAAO,KAAK8P,qBAAqB,GAAK9P,OAAS,SAAUoH,GACxE,MAAkB,UAAX6G,KAAI7G,GAAkBA,EAAGtD,MAAM,IAAM9D,OAAOoH,ICFrD2I,SAAiB9C,MAAM+C,SAAW,SAAiBC,GACjD,MAAmB,SAAZhC,KAAIgC,ICDTC,QAAU1H,KAAkB,WAEhC2H,yBAAiB,SAAUC,GACzB,IAAIhB,EASF,OAREY,SAAQI,KAGM,mBAFhBhB,EAAIgB,EAASC,cAEkBjB,IAAMnC,QAAS+C,SAAQZ,EAAEjP,aAAaiP,OAAI1P,GACrE0I,UAASgH,IAED,QADVA,EAAIA,EAAEc,YACUd,OAAI1P,SAETA,IAAN0P,EAAkBnC,MAAQmC,GCXrCkB,oBAAiB,SAAUF,EAAUlO,GACnC,OAAO,IAAKqO,yBAAmBH,GAAxB,CAAmClO,ICQ5CsO,cAAiB,SAAUC,EAAMC,GAC/B,IAAIC,EAAiB,GAARF,EACTG,EAAoB,GAARH,EACZI,EAAkB,GAARJ,EACVK,EAAmB,GAARL,EACXM,EAAwB,GAARN,EAChBO,EAAmB,GAARP,GAAaM,EACxBE,EAASP,GAAWQ,oBACxB,OAAO,SAAUC,EAAOC,EAAY7J,GAQlC,IAPA,IAMIyB,EAAKqI,EANLjI,EAAI+F,UAASgC,GACbpN,EAAOuN,SAAQlI,GACfD,EAAI0C,KAAIuF,EAAY7J,EAAM,GAC1BrF,EAASyN,UAAS5L,EAAK7B,QACvB0L,EAAQ,EACRqB,EAAS0B,EAASM,EAAOE,EAAOjP,GAAU0O,EAAYK,EAAOE,EAAO,QAAKzR,EAEvEwC,EAAS0L,EAAOA,IAAS,IAAIoD,GAAYpD,KAAS7J,KAEtDsN,EAAMlI,EADNH,EAAMjF,EAAK6J,GACEA,EAAOxE,GAChBqH,GACF,GAAIE,EAAQ1B,EAAOrB,GAASyD,OACvB,GAAIA,EAAK,OAAQZ,GACpB,KAAK,EAAG,OAAO,EACf,KAAK,EAAG,OAAOzH,EACf,KAAK,EAAG,OAAO4E,EACf,KAAK,EAAGqB,EAAOzM,KAAKwG,QACf,GAAI8H,EAAU,OAAO,EAGhC,OAAOC,GAAiB,EAAIF,GAAWC,EAAWA,EAAW7B,ICxC7DsC,YAAc/I,KAAkB,eAChCwE,aAAaC,MAAM9M,UACQT,MAA3BsN,aAAWuE,cAA2B3I,MAAmBoE,aAAYuE,YAAa,IACtF,IAAAC,kBAAiB,SAAUpP,GACzB4K,aAAWuE,aAAanP,IAAO,GCF7BqP,MAAQjJ,cAA4B,GACpCkJ,IAAM,OACNC,QAAS,EAETD,MAAO,IAAIzE,MAAM,GAAGyE,KAAK,WAAcC,QAAS,IACpD9G,QAAQA,QAAQxB,EAAIwB,QAAQO,EAAIuG,OAAQ,QAAS,CAC/CC,KAAM,SAAcR,GAClB,OAAOK,MAAM1R,KAAMqR,EAAYvL,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,MAGzEkJ,kBAAiC8I,KCbjC,IAAAG,IAAY,GAAG/B,wCCGfgC,WAAiB,SAAU1K,GACzB,OAAOkK,SAAQjF,SAAQjF,KCErB2K,KAAO/R,OAAOgS,yBAElBC,IAAYzJ,aAA4BuJ,KAAO,SAAkC3I,EAAGC,GAGlF,GAFAD,EAAI8I,WAAU9I,GACdC,EAAIG,aAAYH,GAAG,GACfI,cAAgB,IAClB,OAAOsI,KAAK3I,EAAGC,GACf,MAAOlK,IACT,GAAI0D,KAAIuG,EAAGC,GAAI,OAAOS,eAAYqI,WAAIhJ,EAAErJ,KAAKsJ,EAAGC,GAAID,EAAEC,yBCVpD+I,MAAQ,SAAUhJ,EAAG9G,GAEvB,GADAiH,UAASH,IACJhB,UAAS9F,IAAoB,OAAVA,EAAgB,MAAMN,UAAUM,EAAQ,8BAElE+P,UAAiB,CACfvP,IAAK9C,OAAOsS,iBAAmB,aAAe,GAC5C,SAAUhN,EAAMiN,EAAOzP,GACrB,KACEA,EAAM0F,KAAkBX,SAAS/H,KAAM8I,YAA0BO,EAAEnJ,OAAOG,UAAW,aAAa2C,IAAK,IACnGwC,EAAM,IACViN,IAAUjN,aAAgB2H,OAC1B,MAAO9N,GAAKoT,GAAQ,EACtB,OAAO,SAAwBnJ,EAAG9G,GAIhC,OAHA8P,MAAMhJ,EAAG9G,GACLiQ,EAAOnJ,EAAEoJ,UAAYlQ,EACpBQ,EAAIsG,EAAG9G,GACL8G,GAVX,CAYE,IAAI,QAAS1J,GACjB0S,MAAOA,OCtBLE,eAAiB9J,UAAwB1F,IAC7C2P,mBAAiB,SAAUlL,EAAMoE,EAAQyD,GACvC,IACI/F,EADAN,EAAI4C,EAAO0E,YAIb,OAFEtH,IAAMqG,GAAiB,mBAALrG,IAAoBM,EAAIN,EAAE5I,aAAeiP,EAAEjP,WAAaiI,UAASiB,IAAMiJ,gBAC3FA,eAAe/K,EAAM8B,GACd9B,GCNPmL,IAAM9K,KAAK8K,IACXlF,MAAM5F,KAAK4F,IACfmF,iBAAiB,SAAU/E,EAAO1L,GAEhC,OADA0L,EAAQF,WAAUE,IACH,EAAI8E,IAAI9E,EAAQ1L,EAAQ,GAAKsL,MAAII,EAAO1L,ICAzD0Q,eAAiB,SAAUC,GACzB,OAAO,SAAU1B,EAAO2B,EAAIC,GAC1B,IAGIjS,EAHAsI,EAAI8I,WAAUf,GACdjP,EAASyN,UAASvG,EAAElH,QACpB0L,EAAQoF,iBAAgBD,EAAW7Q,GAIvC,GAAI2Q,GAAeC,GAAMA,GAAI,KAAO5Q,EAAS0L,GAG3C,IAFA9M,EAAQsI,EAAEwE,OAEG9M,EAAO,OAAO,OAEtB,KAAMoB,EAAS0L,EAAOA,IAAS,IAAIiF,GAAejF,KAASxE,IAC5DA,EAAEwE,KAAWkF,EAAI,OAAOD,GAAejF,GAAS,EACpD,OAAQiF,IAAgB,ICpB1BI,OAASzK,QAAqB,QAElC0K,WAAiB,SAAU9Q,GACzB,OAAO6Q,OAAO7Q,KAAS6Q,OAAO7Q,GAAO0K,KAAI1K,KCDvC+Q,aAAe3K,gBAA6B,GAC5C4K,SAAWxK,WAAyB,YAExCyK,oBAAiB,SAAUxJ,EAAQyJ,GACjC,IAGIlR,EAHAgH,EAAI8I,WAAUrI,GACd5H,EAAI,EACJgN,EAAS,GAEb,IAAK7M,KAAOgH,EAAOhH,GAAOgR,UAAUvQ,KAAIuG,EAAGhH,IAAQ6M,EAAOzM,KAAKJ,GAE/D,KAAOkR,EAAMpR,OAASD,GAAOY,KAAIuG,EAAGhH,EAAMkR,EAAMrR,SAC7CkR,aAAalE,EAAQ7M,IAAQ6M,EAAOzM,KAAKJ,IAE5C,OAAO6M,GCdTsE,aAAiB,gGAEfzP,MAAM,KCDJ0P,WAAahL,aAA4B4B,OAAO,SAAU,aAE9DqJ,IAAYzT,OAAO0T,qBAAuB,SAA6BtK,GACrE,OAAOuK,oBAAMvK,EAAGoK,iCCLlBI,UAAiB,iDCIbC,MAAQ,IAAMC,UAAS,IACvBC,IAAM,KACNC,MAAQC,OAAO,IAAMJ,MAAQA,MAAQ,KACrCK,MAAQD,OAAOJ,MAAQA,MAAQ,MAE/BM,SAAW,SAAUzC,EAAKpJ,EAAM8L,GAClC,IAAIlJ,EAAM,GACNmJ,EAAQC,OAAM,WAChB,QAASR,UAAOpC,MAAUqC,IAAIrC,MAAUqC,MAEtCzM,EAAK4D,EAAIwG,GAAO2C,EAAQ/L,EAAKiM,MAAQT,UAAOpC,GAC5C0C,IAAOlJ,EAAIkJ,GAAS9M,GACxBuD,QAAQA,QAAQxB,EAAIwB,QAAQO,EAAIiJ,EAAO,SAAUnJ,IAM/CqJ,KAAOJ,SAASI,KAAO,SAAUC,EAAQ/D,GAI3C,OAHA+D,EAAS/R,OAAO4J,SAAQmI,IACb,EAAP/D,IAAU+D,EAASA,EAAOrT,QAAQ6S,MAAO,KAClC,EAAPvD,IAAU+D,EAASA,EAAOrT,QAAQ+S,MAAO,KACtCM,GAGTC,YAAiBN,SCzBjBO,YAAiB1U,OAAOkD,MAAQ,SAAckG,GAC5C,OAAOuK,oBAAMvK,EAAGuL,eCDlBC,WAAiBpM,aAA4BxI,OAAOkG,iBAAmB,SAA0BkD,EAAGyL,GAClGtL,UAASH,GAKT,IAJA,IAGIC,EAHAnG,EAAO4R,YAAQD,GACf3S,EAASgB,EAAKhB,OACdD,EAAI,EAEDC,EAASD,GAAGiH,UAAGC,EAAEC,EAAGC,EAAInG,EAAKjB,KAAM4S,EAAWxL,IACrD,OAAOD,GCXLzJ,WAAW6I,QAAqB7I,SACpCoV,MAAiBpV,YAAYA,WAASqV,gBCGlC5B,WAAW5K,WAAyB,YACpCyM,MAAQ,aACRrK,YAAY,YAGZsK,WAAa,WAEf,IAIIC,EAJAC,EAASxM,WAAyB,UAClC3G,EAAI0S,aAAYzS,OAcpB,IAVAkT,EAAOC,MAAMC,QAAU,OACvBzM,MAAmB7D,YAAYoQ,GAC/BA,EAAOG,IAAM,eAGbJ,EAAiBC,EAAOI,cAAc7V,UACvB8V,OACfN,EAAeO,MAAMC,uCACrBR,EAAeS,QACfV,WAAaC,EAAe/J,EACrBnJ,YAAYiT,WAAWtK,aAAW+J,aAAY1S,IACrD,OAAOiT,cAGTW,cAAiB7V,OAAOiR,QAAU,SAAgB7H,EAAGyL,GACnD,IAAI5F,EAQJ,OAPU,OAAN7F,GACF6L,MAAMrK,aAAarB,UAASH,GAC5B6F,EAAS,IAAIgG,MACbA,MAAMrK,aAAa,KAEnBqE,EAAOmE,YAAYhK,GACd6F,EAASiG,kBACMxV,IAAfmV,EAA2B5F,EAAS6G,WAAI7G,EAAQ4F,IChCrDkB,KAAOvN,YAA0BW,EACjC4I,OAAOnJ,YAA0BO,EACjCD,KAAKL,UAAwBM,EAC7B6M,MAAQC,YAA0B1B,KAClC2B,OAAS,SACTC,QAAU9V,QAAO6V,QACjBE,KAAOD,QACP7T,MAAQ6T,QAAQhW,UAEhBkW,WAAapI,KAAIqI,cAA4BhU,SAAW4T,OACxDK,KAAO,SAAU9T,OAAOtC,UAGxBqW,SAAW,SAAUC,GACvB,IAAIrP,EAAKoC,aAAYiN,GAAU,GAC/B,GAAiB,iBAANrP,GAAkBA,EAAGlF,OAAS,EAAG,CAE1C,IACIwU,EAAOC,EAAOC,EADdC,GADJzP,EAAKmP,KAAOnP,EAAGmN,OAASyB,MAAM5O,EAAI,IACnB0P,WAAW,GAE1B,GAAc,KAAVD,GAA0B,KAAVA,GAElB,GAAc,MADdH,EAAQtP,EAAG0P,WAAW,KACQ,MAAVJ,EAAe,OAAOK,SACrC,GAAc,KAAVF,EAAc,CACvB,OAAQzP,EAAG0P,WAAW,IACpB,KAAK,GAAI,KAAK,GAAIH,EAAQ,EAAGC,EAAU,GAAI,MAC3C,KAAK,GAAI,KAAK,IAAKD,EAAQ,EAAGC,EAAU,GAAI,MAC5C,QAAS,OAAQxP,EAEnB,IAAK,IAAoD4P,EAAhDC,EAAS7P,EAAGxE,MAAM,GAAIX,EAAI,EAAGiV,EAAID,EAAO/U,OAAcD,EAAIiV,EAAGjV,IAIpE,IAHA+U,EAAOC,EAAOH,WAAW7U,IAGd,IAAM+U,EAAOJ,EAAS,OAAOG,IACxC,OAAOI,SAASF,EAAQN,IAE5B,OAAQvP,GAGZ,IAAK+O,QAAQ,UAAYA,QAAQ,QAAUA,QAAQ,QAAS,CAC1DA,QAAU,SAAgBrV,GACxB,IAAIsG,EAAKvB,UAAU3D,OAAS,EAAI,EAAIpB,EAChCyG,EAAOxH,KACX,OAAOwH,aAAgB4O,UAEjBE,WAAa/B,OAAM,WAAchS,MAAM2G,QAAQnJ,KAAKyH,KAAY0G,KAAI1G,IAAS2O,QAC7EkB,mBAAkB,IAAIhB,KAAKI,SAASpP,IAAMG,EAAM4O,SAAWK,SAASpP,IAE5E,IAAK,IAMgBhF,IANZc,KAAOmU,aAA4BtB,KAAKK,MAAQ,6KAMvDtS,MAAM,KAAMwT,EAAI,EAAQpU,KAAKhB,OAASoV,EAAGA,IACrCzU,KAAIuT,KAAMhU,IAAMc,KAAKoU,MAAQzU,KAAIsT,QAAS/T,MAC5C8G,KAAGiN,QAAS/T,IAAK2P,OAAKqE,KAAMhU,MAGhC+T,QAAQhW,UAAYmC,MACpBA,MAAM+N,YAAc8F,QACpBoB,UAAuBlX,QAAQ6V,OAAQC,SC/DzC,IAAAqB,WAAiB,SAAU9F,EAAKpJ,GAC9B,IAAIhB,GAAMS,MAAK/H,QAAU,IAAI0R,IAAQ1R,OAAO0R,GACxCxG,EAAM,GACVA,EAAIwG,GAAOpJ,EAAKhB,GAChBuD,QAAQA,QAAQ9B,EAAI8B,QAAQO,EAAIkJ,OAAM,WAAchN,EAAG,KAAQ,SAAU4D,ICJ3E1C,WAAyB,OAAQ,WAC/B,OAAO,SAAcpB,GACnB,OAAOuM,YAAMxE,UAAS/H,OCH1B,IAAIqQ,MAAQjP,KAAkB,SAC9BkP,UAAiB,SAAUtQ,GACzB,IAAIuQ,EACJ,OAAOvP,UAAShB,UAAmC1H,KAA1BiY,EAAWvQ,EAAGqQ,UAA0BE,EAAsB,UAAX1J,KAAI7G,KCFlFwQ,eAAiB,SAAUrQ,EAAM/F,EAAcqW,GAC7C,GAAIF,UAASnW,GAAe,MAAMQ,UAAU,UAAY6V,EAAO,0BAC/D,OAAOpV,OAAO4J,SAAQ9E,KCNpBkQ,QAAQjP,KAAkB,SAC9BsP,eAAiB,SAAUpG,GACzB,IAAIqG,EAAK,IACT,IACE,MAAMrG,GAAKqG,GACX,MAAO5Y,GACP,IAEE,OADA4Y,EAAGN,UAAS,GACJ,MAAM/F,GAAKqG,GACnB,MAAO5O,KACT,OAAO,GCNP6O,SAAW,WAEfnN,QAAQA,QAAQxB,EAAIwB,QAAQO,EAAI5C,eAA8BwP,UAAW,SAAU,CACjFC,SAAU,SAAkBzW,GAC1B,SAAU0W,eAAQnY,KAAMyB,EAAcwW,UACnC/S,QAAQzD,EAAcqE,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,MCNnE,IAAIyY,UAAY3P,gBAA6B,GAE7CqC,QAAQA,QAAQxB,EAAG,QAAS,CAC1B4O,SAAU,SAAkBnF,GAC1B,OAAOqF,UAAUpY,KAAM+S,EAAIjN,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,MAIrEkJ,kBAAiC,YCVjC,IAAAwP,WAAiBpY,OAAOyI,IAAM,SAAY4P,EAAGC,GAE3C,OAAOD,IAAMC,EAAU,IAAND,GAAW,EAAIA,GAAM,EAAIC,EAAID,GAAKA,GAAKC,GAAKA,GCA3DC,YAActE,OAAO9T,UAAUmI,KAInCkQ,oBAAiB,SAAUvM,EAAGlD,GAC5B,IAAIT,EAAO2D,EAAE3D,KACb,GAAoB,mBAATA,EAAqB,CAC9B,IAAI2G,EAAS3G,EAAKxI,KAAKmM,EAAGlD,GAC1B,GAAsB,iBAAXkG,EACT,MAAM,IAAIjN,UAAU,sEAEtB,OAAOiN,EAET,GAAmB,WAAfT,SAAQvC,GACV,MAAM,IAAIjK,UAAU,+CAEtB,OAAOuW,YAAYzY,KAAKmM,EAAGlD,IChB7B0P,OAAiB,WACf,IAAIlR,EAAOgC,UAASxJ,MAChBkP,EAAS,GAMb,OALI1H,EAAKlH,SAAQ4O,GAAU,KACvB1H,EAAKmR,aAAYzJ,GAAU,KAC3B1H,EAAKoR,YAAW1J,GAAU,KAC1B1H,EAAKqR,UAAS3J,GAAU,KACxB1H,EAAKsR,SAAQ5J,GAAU,KACpBA,GCPL6J,WAAa7E,OAAO9T,UAAUmI,KAI9ByQ,cAAgBtW,OAAOtC,UAAUgB,QAEjC6X,YAAcF,WAEdG,WAAa,YAEbC,yBAA2B,WAC7B,IAAIC,EAAM,IACNC,EAAM,MAGV,OAFAN,WAAWhZ,KAAKqZ,EAAK,KACrBL,WAAWhZ,KAAKsZ,EAAK,KACM,IAApBD,EAAIF,aAAyC,IAApBG,EAAIH,YALP,GAS3BI,mBAAuC3Z,IAAvB,OAAO4I,KAAK,IAAI,GAEhCgR,MAAQJ,0BAA4BG,cAEpCC,QACFN,YAAc,SAAcO,GAC1B,IACIC,EAAWC,EAAQC,EAAOzX,EAD1B8V,EAAKhY,KAwBT,OArBIsZ,gBACFI,EAAS,IAAIxF,OAAO,IAAM8D,EAAGhN,OAAS,WAAY4O,OAAY7Z,KAAKiY,KAEjEmB,2BAA0BM,EAAYzB,EAAGkB,aAE7CS,EAAQZ,WAAWhZ,KAAKiY,EAAIwB,GAExBL,0BAA4BQ,IAC9B3B,EAAGkB,YAAclB,EAAG1X,OAASqZ,EAAM9L,MAAQ8L,EAAM,GAAGxX,OAASsX,GAE3DH,eAAiBK,GAASA,EAAMxX,OAAS,GAI3C6W,cAAcjZ,KAAK4Z,EAAM,GAAID,EAAQ,WACnC,IAAKxX,EAAI,EAAGA,EAAI4D,UAAU3D,OAAS,EAAGD,SACfvC,IAAjBmG,UAAU5D,KAAkByX,EAAMzX,QAAKvC,KAK1Cga,IAIX,IAAAE,YAAiBZ,YCvDjBxQ,QAAqB,CACnBmD,OAAQ,SACRrJ,OAAO,EACPqP,OAAQkI,cAAe,IAAIvR,MAC1B,CACDA,KAAMuR,cCER,IAAI3J,UAAU4J,KAAI,WAEdC,+BAAiCzF,OAAM,WAIzC,IAAIyD,EAAK,IAMT,OALAA,EAAGzP,KAAO,WACR,IAAI2G,EAAS,GAEb,OADAA,EAAO+K,OAAS,CAAExW,EAAG,KACdyL,GAEyB,MAA3B,GAAG9N,QAAQ4W,EAAI,UAGpBkC,kCAAoC,WAEtC,IAAIlC,EAAK,OACLmC,EAAenC,EAAGzP,KACtByP,EAAGzP,KAAO,WAAc,OAAO4R,EAAatU,MAAM7F,KAAM8F,YACxD,IAAIoJ,EAAS,KAAKnL,MAAMiU,GACxB,OAAyB,IAAlB9I,EAAO/M,QAA8B,MAAd+M,EAAO,IAA4B,MAAdA,EAAO,GANpB,GASxCkL,UAAiB,SAAUzI,EAAKxP,EAAQoG,GACtC,IAAI8R,EAASN,KAAIpI,GAEb2I,GAAuB/F,OAAM,WAE/B,IAAIlL,EAAI,GAER,OADAA,EAAEgR,GAAU,WAAc,OAAO,GACZ,GAAd,GAAG1I,GAAKtI,KAGbkR,EAAoBD,GAAuB/F,OAAM,WAEnD,IAAIiG,GAAa,EACbxC,EAAK,IAST,OARAA,EAAGzP,KAAO,WAAiC,OAAnBiS,GAAa,EAAa,MACtC,UAAR7I,IAGFqG,EAAG1H,YAAc,GACjB0H,EAAG1H,YAAYH,WAAW,WAAc,OAAO6H,IAEjDA,EAAGqC,GAAQ,KACHG,SACL7a,EAEL,IACG2a,IACAC,GACQ,YAAR5I,IAAsBqI,+BACd,UAARrI,IAAoBuI,kCACrB,CACA,IAAIO,EAAqB,IAAIJ,GACzBK,EAAMnS,EACR+D,SACA+N,EACA,GAAG1I,GACH,SAAyBgJ,EAAcC,EAAQpB,EAAKqB,EAAMC,GACxD,OAAIF,EAAOrS,OAASuR,YACdQ,IAAwBQ,EAInB,CAAE7Z,MAAM,EAAMF,MAAO0Z,EAAmB1a,KAAK6a,EAAQpB,EAAKqB,IAE5D,CAAE5Z,MAAM,EAAMF,MAAO4Z,EAAa5a,KAAKyZ,EAAKoB,EAAQC,IAEtD,CAAE5Z,MAAM,KAGf8Z,EAAQL,EAAI,GACZM,EAAON,EAAI,GAEf3O,UAASrJ,OAAOtC,UAAWuR,EAAKoJ,GAChCnQ,MAAKsJ,OAAO9T,UAAWia,EAAkB,GAAVlY,EAG3B,SAAUsS,EAAQvE,GAAO,OAAO8K,EAAKjb,KAAK0U,EAAQzU,KAAMkQ,IAGxD,SAAUuE,GAAU,OAAOuG,EAAKjb,KAAK0U,EAAQzU,UCrFrDyI,UAAyB,SAAU,EAAG,SAAU6D,EAAS2O,EAAQC,EAASC,GACxE,MAAO,CAGL,SAAgBP,GACd,IAAIvR,EAAIiD,EAAQtM,MACZuH,EAAe5H,MAAVib,OAAsBjb,EAAYib,EAAOK,GAClD,YAActb,IAAP4H,EAAmBA,EAAGxH,KAAK6a,EAAQvR,GAAK,IAAI6K,OAAO0G,GAAQK,GAAQvY,OAAO2G,KAInF,SAAUuR,GACR,IAAItJ,EAAM6J,EAAgBD,EAASN,EAAQ5a,MAC3C,GAAIsR,EAAIrQ,KAAM,OAAOqQ,EAAIvQ,MACzB,IAAIqa,EAAK5R,UAASoR,GACd5R,EAAItG,OAAO1C,MACXqb,EAAoBD,EAAG3B,UACtB6B,WAAUD,EAAmB,KAAID,EAAG3B,UAAY,GACrD,IAAIvK,EAASqM,oBAAWH,EAAIpS,GAE5B,OADKsS,WAAUF,EAAG3B,UAAW4B,KAAoBD,EAAG3B,UAAY4B,GAC9C,OAAXnM,GAAmB,EAAIA,EAAOrB,UC1BvCpF,cAA2C,KAAd,KAAK+S,OAAc3S,UAAwBO,EAAE8K,OAAO9T,UAAW,QAAS,CACvGwD,cAAc,EACdzD,IAAK2I,SCEP,IAAI2S,UAAY,WACZlR,UAAY,IAAIkR,WAEhBC,OAAS,SAAUnU,GACrBsB,UAAuBqL,OAAO9T,UAAWqb,UAAWlU,GAAI,IAItDuB,OAAoB,WAAc,MAAsD,QAA/CyB,UAAUxK,KAAK,CAAEiL,OAAQ,IAAKwQ,MAAO,QAChFE,OAAO,WACL,IAAIxP,EAAI1C,UAASxJ,MACjB,MAAO,IAAIqK,OAAO6B,EAAElB,OAAQ,IAC1B,UAAWkB,EAAIA,EAAEsP,OAASG,cAAezP,aAAagI,OAAS0H,OAAO7b,KAAKmM,QAAKvM,KAG3E4K,UAAUxI,MAAQ0Z,WAC3BC,OAAO,WACL,OAAOnR,UAAUxK,KAAKC,QCtB1B,IAAA6b,UAAiB,SAAU5a,EAAMF,GAC/B,MAAO,CAAEA,MAAOA,EAAOE,OAAQA,ICD7B6a,IAAMrT,UAAwBW,EAE9B4E,MAAMnF,KAAkB,eAE5BkT,gBAAiB,SAAU1U,EAAI2U,EAAKC,GAC9B5U,IAAOvE,KAAIuE,EAAK4U,EAAO5U,EAAKA,EAAGjH,UAAW4N,QAAM8N,IAAIzU,EAAI2G,MAAK,CAAEpK,cAAc,EAAM7C,MAAOib,KCD5FE,kBAAoB,GAGxBzT,MAAmByT,kBAAmBrT,KAAkB,YAAa,WAAc,OAAO7I,OAE1F,IAAAmc,YAAiB,SAAUC,EAAatE,EAAMhX,GAC5Csb,EAAYhc,UAAY8Q,cAAOgL,kBAAmB,CAAEpb,KAAMub,cAAW,EAAGvb,KACxEwb,gBAAeF,EAAatE,EAAO,cCRjCzE,WAAW5K,WAAyB,YACpC8T,YAActc,OAAOG,UAEzBoc,WAAiBvc,OAAOwc,gBAAkB,SAAUpT,GAElD,OADAA,EAAI+F,UAAS/F,GACTvG,KAAIuG,EAAGgK,YAAkBhK,EAAEgK,YACH,mBAAjBhK,EAAEiH,aAA6BjH,aAAaA,EAAEiH,YAChDjH,EAAEiH,YAAYlQ,UACdiJ,aAAapJ,OAASsc,YAAc,MCF3CvP,WAAWvE,KAAkB,YAC7BiU,QAAU,GAAGvZ,MAAQ,QAAU,GAAGA,QAClCwZ,YAAc,aACdC,KAAO,OACPC,OAAS,SAETC,WAAa,WAAc,OAAO9c,MAEtC+c,YAAiB,SAAU1G,EAAMyB,EAAMsE,EAAatb,EAAMkc,EAASC,EAAQC,GACzEC,YAAYf,EAAatE,EAAMhX,GAC/B,IAeIsc,EAAS/a,EAAK6Z,EAfdmB,EAAY,SAAUC,GACxB,IAAKZ,OAASY,KAAQ/a,EAAO,OAAOA,EAAM+a,GAC1C,OAAQA,GACN,KAAKV,KACL,KAAKC,OAAQ,OAAO,WAAoB,OAAO,IAAIT,EAAYpc,KAAMsd,IACrE,OAAO,WAAqB,OAAO,IAAIlB,EAAYpc,KAAMsd,KAEzDtP,EAAM8J,EAAO,YACbyF,EAAaP,GAAWH,OACxBW,GAAa,EACbjb,EAAQ8T,EAAKjW,UACbqd,EAAUlb,EAAMyK,aAAazK,EAAMoa,cAAgBK,GAAWza,EAAMya,GACpEU,EAAWD,GAAWJ,EAAUL,GAChCW,EAAWX,EAAWO,EAAwBF,EAAU,WAArBK,OAAkC/d,EACrEie,EAAqB,SAAR9F,GAAkBvV,EAAMW,SAAqBua,EAwB9D,GArBIG,IACF1B,EAAoBO,WAAemB,EAAW7d,KAAK,IAAIsW,OAC7BpW,OAAOG,WAAa8b,EAAkBpb,OAE9Dwb,gBAAeJ,EAAmBlO,GAAK,GAElC6P,UAAiD,mBAA/B3B,EAAkBlP,aAAyBpC,MAAKsR,EAAmBlP,WAAU8P,aAIpGS,GAAcE,GAAWA,EAAQ1b,OAAS8a,SAC5CW,GAAa,EACbE,EAAW,WAAoB,OAAOD,EAAQ1d,KAAKC,QAG/C6d,WAAWX,IAAYR,QAASc,GAAejb,EAAMyK,aACzDpC,MAAKrI,EAAOyK,WAAU0Q,GAGxBtQ,WAAU0K,GAAQ4F,EAClBtQ,WAAUY,GAAO8O,WACbE,EAMF,GALAI,EAAU,CACRha,OAAQma,EAAaG,EAAWL,EAAUR,QAC1C1Z,KAAM8Z,EAASS,EAAWL,EAAUT,MACpC1Z,QAASya,GAEPT,EAAQ,IAAK7a,KAAO+a,EAChB/a,KAAOE,GAAQwJ,UAASxJ,EAAOF,EAAK+a,EAAQ/a,SAC7CyI,QAAQA,QAAQxB,EAAIwB,QAAQO,GAAKqR,OAASc,GAAa1F,EAAMsF,GAEtE,OAAOA,GCzDTU,mBAAiBrV,YAA0ByE,MAAO,QAAS,SAAU6Q,EAAUT,GAC7Etd,KAAKge,GAAK7L,WAAU4L,GACpB/d,KAAKie,GAAK,EACVje,KAAKke,GAAKZ,GAET,WACD,IAAIjU,EAAIrJ,KAAKge,GACTV,EAAOtd,KAAKke,GACZrQ,EAAQ7N,KAAKie,KACjB,OAAK5U,GAAKwE,GAASxE,EAAElH,QACnBnC,KAAKge,QAAKre,EACHwP,UAAK,IAEaA,UAAK,EAApB,QAARmO,EAA+BzP,EACvB,UAARyP,EAAiCjU,EAAEwE,GACxB,CAACA,EAAOxE,EAAEwE,MACxB,UAGHT,WAAU+Q,UAAY/Q,WAAUF,MAEhCkR,kBAAiB,QACjBA,kBAAiB,UACjBA,kBAAiB,WCYjB,IAtCA,IAAIpR,WAAW+M,KAAI,YACfsE,cAAgBtE,KAAI,eACpBuE,YAAclR,WAAUF,MAExBqR,aAAe,CACjBC,aAAa,EACbC,qBAAqB,EACrBC,cAAc,EACdC,gBAAgB,EAChBC,aAAa,EACbC,eAAe,EACfC,cAAc,EACdC,sBAAsB,EACtBC,UAAU,EACVC,mBAAmB,EACnBC,gBAAgB,EAChBC,iBAAiB,EACjBC,mBAAmB,EACnBC,WAAW,EACXC,eAAe,EACfC,cAAc,EACdC,UAAU,EACVC,kBAAkB,EAClBC,QAAQ,EACRC,aAAa,EACbC,eAAe,EACfC,eAAe,EACfC,gBAAgB,EAChBC,cAAc,EACdC,eAAe,EACfC,kBAAkB,EAClBC,kBAAkB,EAClBC,gBAAgB,EAChBC,kBAAkB,EAClBC,eAAe,EACfC,WAAW,GAGJC,YAAcxL,YAAQwJ,cAAerc,EAAI,EAAGA,EAAIqe,YAAYpe,OAAQD,IAAK,CAChF,IAIIG,MAJAyV,KAAOyI,YAAYre,GACnBse,SAAWjC,aAAazG,MACxB2I,WAAangB,QAAOwX,MACpBvV,QAAQke,YAAcA,WAAWrgB,UAErC,GAAImC,UACGA,QAAMyK,aAAWpC,MAAKrI,QAAOyK,WAAUsR,aACvC/b,QAAM8b,gBAAgBzT,MAAKrI,QAAO8b,cAAevG,MACtD1K,WAAU0K,MAAQwG,YACdkC,UAAU,IAAKne,SAAOqe,mBAAiBne,QAAMF,QAAM0J,UAASxJ,QAAOF,MAAKqe,mBAAWre,QAAM,GCnDjG,IAAAse,UAAiB,SAAUlF,GACzB,OAAO,SAAUjU,EAAMoZ,GACrB,IAGInd,EAAGC,EAHHmd,EAAIne,OAAO4J,SAAQ9E,IACnBtF,EAAIyL,WAAUiT,GACdzJ,EAAI0J,EAAE1e,OAEV,OAAID,EAAI,GAAKA,GAAKiV,EAAUsE,EAAY,QAAK9b,GAC7C8D,EAAIod,EAAE9J,WAAW7U,IACN,OAAUuB,EAAI,OAAUvB,EAAI,IAAMiV,IAAMzT,EAAImd,EAAE9J,WAAW7U,EAAI,IAAM,OAAUwB,EAAI,MACxF+X,EAAYoF,EAAEC,OAAO5e,GAAKuB,EAC1BgY,EAAYoF,EAAEhe,MAAMX,EAAGA,EAAI,GAA2BwB,EAAI,OAAzBD,EAAI,OAAU,IAAqB,QCbxEsd,IAAMtY,WAAwB,GAGlCI,YAA0BnG,OAAQ,SAAU,SAAUqb,GACpD/d,KAAKge,GAAKtb,OAAOqb,GACjB/d,KAAKie,GAAK,GAET,WACD,IAEI+C,EAFA3X,EAAIrJ,KAAKge,GACTnQ,EAAQ7N,KAAKie,GAEjB,OAAIpQ,GAASxE,EAAElH,OAAe,CAAEpB,WAAOpB,EAAWsB,MAAM,IACxD+f,EAAQD,IAAI1X,EAAGwE,GACf7N,KAAKie,IAAM+C,EAAM7e,OACV,CAAEpB,MAAOigB,EAAO/f,MAAM,iDCf/B,IAAIggB,EAAOxY,KAAkB,QAGzByY,EAAUrY,UAAwBO,EAClCa,EAAK,EACLkX,EAAelhB,OAAOkhB,cAAgB,WACxC,OAAO,GAELC,GAAUtY,OAAoB,WAChC,OAAOqY,EAAalhB,OAAOohB,kBAAkB,OAE3CC,EAAU,SAAUja,GACtB6Z,EAAQ7Z,EAAI4Z,EAAM,CAAElgB,MAAO,CACzBmB,EAAG,OAAQ+H,EACXsX,EAAG,OAgCHC,EAAO7Z,EAAAC,QAAiB,CAC1B+J,IAAKsP,EACLQ,MAAM,EACNC,QAhCY,SAAUra,EAAI6J,GAE1B,IAAK7I,UAAShB,GAAK,MAAoB,iBAANA,EAAiBA,GAAmB,iBAANA,EAAiB,IAAM,KAAOA,EAC7F,IAAKvE,KAAIuE,EAAI4Z,GAAO,CAElB,IAAKE,EAAa9Z,GAAK,MAAO,IAE9B,IAAK6J,EAAQ,MAAO,IAEpBoQ,EAAQja,GAER,OAAOA,EAAG4Z,GAAM/e,GAsBlByf,QApBY,SAAUta,EAAI6J,GAC1B,IAAKpO,KAAIuE,EAAI4Z,GAAO,CAElB,IAAKE,EAAa9Z,GAAK,OAAO,EAE9B,IAAK6J,EAAQ,OAAO,EAEpBoQ,EAAQja,GAER,OAAOA,EAAG4Z,GAAMM,GAYlBK,SATa,SAAUva,GAEvB,OADI+Z,GAAUI,EAAKC,MAAQN,EAAa9Z,KAAQvE,KAAIuE,EAAI4Z,IAAOK,EAAQja,GAChEA,8GC5CTwa,IAAY5hB,OAAO6hB,0CCOfC,QAAU9hB,OAAO+hB,OAGrBC,eAAkBF,SAAWtZ,OAAoB,WAC/C,IAAIyZ,EAAI,GACJvW,EAAI,GAEJ3C,EAAIxI,SACJ2hB,EAAI,uBAGR,OAFAD,EAAElZ,GAAK,EACPmZ,EAAEpe,MAAM,IAAIjC,QAAQ,SAAUsgB,GAAKzW,EAAEyW,GAAKA,IACd,GAArBL,QAAQ,GAAIG,GAAGlZ,IAAW/I,OAAOkD,KAAK4e,QAAQ,GAAIpW,IAAIrI,KAAK,KAAO6e,IACtE,SAAgBvW,EAAQZ,GAM3B,IALA,IAAIqD,EAAIe,UAASxD,GACb0D,EAAOxJ,UAAU3D,OACjB0L,EAAQ,EACRwU,EAAaC,YAAKlZ,EAClBmZ,EAASnQ,WAAIhJ,EACVkG,EAAOzB,GAMZ,IALA,IAIIxL,EAJA2G,EAAIuI,SAAQzL,UAAU+H,MACtB1K,EAAOkf,EAAatN,YAAQ/L,GAAGqB,OAAOgY,EAAWrZ,IAAM+L,YAAQ/L,GAC/D7G,EAASgB,EAAKhB,OACdoV,EAAI,EAEDpV,EAASoV,GAAOgL,EAAOxiB,KAAKiJ,EAAG3G,EAAMc,EAAKoU,QAAOlJ,EAAEhM,GAAO2G,EAAE3G,IACnE,OAAOgM,GACP0T,QChCJS,aAAiB,SAAU5W,EAAQ4J,EAAK9K,GACtC,IAAK,IAAIrI,KAAOmT,EAAKzJ,UAASH,EAAQvJ,EAAKmT,EAAInT,GAAMqI,GACrD,OAAOkB,GCHT6W,YAAiB,SAAUpb,EAAI+U,EAAara,EAAM2gB,GAChD,KAAMrb,aAAc+U,SAAoCzc,IAAnB+iB,GAAgCA,KAAkBrb,EACrF,MAAMpF,UAAUF,EAAO,2BACvB,OAAOsF,2CCGX,IAAIsb,EAAQ,GACRC,EAAS,GACThb,EAAUD,EAAAC,QAAiB,SAAUib,EAAU3f,EAASqE,EAAIC,EAAMwF,GACpE,IAGI7K,EAAQgN,EAAM1O,EAAUyO,EAHxBO,EAASzC,EAAW,WAAc,OAAO6V,GAAcnT,uBAAUmT,GACjEzZ,EAAI0C,KAAIvE,EAAIC,EAAMtE,EAAU,EAAI,GAChC2K,EAAQ,EAEZ,GAAqB,mBAAV4B,EAAsB,MAAMxN,UAAU4gB,EAAW,qBAE5D,GAAIlT,aAAYF,IAAS,IAAKtN,EAASyN,UAASiT,EAAS1gB,QAASA,EAAS0L,EAAOA,IAEhF,IADAqB,EAAShM,EAAUkG,EAAEI,UAAS2F,EAAO0T,EAAShV,IAAQ,GAAIsB,EAAK,IAAM/F,EAAEyZ,EAAShV,OACjE8U,GAASzT,IAAW0T,EAAQ,OAAO1T,OAC7C,IAAKzO,EAAWgP,EAAO1P,KAAK8iB,KAAa1T,EAAO1O,EAASK,QAAQG,MAEtE,IADAiO,EAASnP,UAAKU,EAAU2I,EAAG+F,EAAKpO,MAAOmC,MACxByf,GAASzT,IAAW0T,EAAQ,OAAO1T,GAGtDtH,EAAQ+a,MAAQA,EAChB/a,EAAQgb,OAASA,ICvBjBE,oBAAiB,SAAUzb,EAAIqJ,GAC7B,IAAKrI,UAAShB,IAAOA,EAAG2W,KAAOtN,EAAM,MAAMzO,UAAU,0BAA4ByO,EAAO,cACxF,OAAOrJ,GCDLsa,QAAUlZ,MAAmBkZ,QAQ7BoB,UAAYC,cAAkB,GAC9BC,eAAiBD,cAAkB,GACnC/Y,KAAK,EAGLiZ,oBAAsB,SAAU1b,GAClC,OAAOA,EAAK2b,KAAO3b,EAAK2b,GAAK,IAAIC,sBAE/BA,oBAAsB,WACxBpjB,KAAKyD,EAAI,IAEP4f,mBAAqB,SAAU1W,EAAOtK,GACxC,OAAO0gB,UAAUpW,EAAMlJ,EAAG,SAAU4D,GAClC,OAAOA,EAAG,KAAOhF,KAGrB+gB,oBAAoBhjB,UAAY,CAC9BD,IAAK,SAAUkC,GACb,IAAID,EAAQihB,mBAAmBrjB,KAAMqC,GACrC,GAAID,EAAO,OAAOA,EAAM,IAE1BU,IAAK,SAAUT,GACb,QAASghB,mBAAmBrjB,KAAMqC,IAEpCU,IAAK,SAAUV,EAAKtB,GAClB,IAAIqB,EAAQihB,mBAAmBrjB,KAAMqC,GACjCD,EAAOA,EAAM,GAAKrB,EACjBf,KAAKyD,EAAEhB,KAAK,CAACJ,EAAKtB,KAEzB4B,OAAU,SAAUN,GAClB,IAAIwL,EAAQoV,eAAejjB,KAAKyD,EAAG,SAAU4D,GAC3C,OAAOA,EAAG,KAAOhF,IAGnB,OADKwL,GAAO7N,KAAKyD,EAAE6f,OAAOzV,EAAO,MACvBA,IAId,IAAA0V,gBAAiB,CACfC,eAAgB,SAAUC,EAAS3L,EAAMlH,EAAQ8S,GAC/C,IAAIrU,EAAIoU,EAAQ,SAAUjc,EAAMqb,GAC9Bc,YAAWnc,EAAM6H,EAAGyI,EAAM,MAC1BtQ,EAAKwW,GAAKlG,EACVtQ,EAAKyW,GAAKhU,OACVzC,EAAK2b,QAAKxjB,EACMA,MAAZkjB,GAAuBe,OAAMf,EAAUjS,EAAQpJ,EAAKkc,GAAQlc,KAoBlE,OAlBAqc,aAAYxU,EAAEjP,UAAW,CAGvBuC,OAAU,SAAUN,GAClB,IAAKgG,UAAShG,GAAM,OAAO,EAC3B,IAAIyhB,EAAOnC,QAAQtf,GACnB,OAAa,IAATyhB,EAAsBZ,oBAAoBa,oBAAS/jB,KAAM8X,IAAe,OAAEzV,GACvEyhB,GAAQE,KAAKF,EAAM9jB,KAAKie,YAAc6F,EAAK9jB,KAAKie,KAIzDnb,IAAK,SAAaT,GAChB,IAAKgG,UAAShG,GAAM,OAAO,EAC3B,IAAIyhB,EAAOnC,QAAQtf,GACnB,OAAa,IAATyhB,EAAsBZ,oBAAoBa,oBAAS/jB,KAAM8X,IAAOhV,IAAIT,GACjEyhB,GAAQE,KAAKF,EAAM9jB,KAAKie,OAG5B5O,GAETyM,IAAK,SAAUtU,EAAMnF,EAAKtB,GACxB,IAAI+iB,EAAOnC,QAAQnY,UAASnH,IAAM,GAGlC,OAFa,IAATyhB,EAAeZ,oBAAoB1b,GAAMzE,IAAIV,EAAKtB,GACjD+iB,EAAKtc,EAAKyW,IAAMld,EACdyG,GAETyc,QAASf,qBCrEXgB,YAAiB,SAAUpM,EAAM2L,EAASrG,EAAS+G,EAAQvT,EAAQwT,GACjE,IAAI/N,EAAO/V,QAAOwX,GACdzI,EAAIgH,EACJqN,EAAQ9S,EAAS,MAAQ,MACzBrO,EAAQ8M,GAAKA,EAAEjP,UACfiJ,EAAI,GACJgb,EAAY,SAAU1S,GACxB,IAAIpK,EAAKhF,EAAMoP,GACf5F,UAASxJ,EAAOoP,EACP,UAAPA,EAAkB,SAAUlO,GAC1B,QAAO2gB,IAAY/b,UAAS5E,KAAa8D,EAAGxH,KAAKC,KAAY,IAANyD,EAAU,EAAIA,IAC5D,OAAPkO,EAAe,SAAalO,GAC9B,QAAO2gB,IAAY/b,UAAS5E,KAAa8D,EAAGxH,KAAKC,KAAY,IAANyD,EAAU,EAAIA,IAC5D,OAAPkO,EAAe,SAAalO,GAC9B,OAAO2gB,IAAY/b,UAAS5E,QAAK9D,EAAY4H,EAAGxH,KAAKC,KAAY,IAANyD,EAAU,EAAIA,IAChE,OAAPkO,EAAe,SAAalO,GAAqC,OAAhC8D,EAAGxH,KAAKC,KAAY,IAANyD,EAAU,EAAIA,GAAWzD,MACxE,SAAayD,EAAGC,GAAwC,OAAnC6D,EAAGxH,KAAKC,KAAY,IAANyD,EAAU,EAAIA,EAAGC,GAAW1D,QAGvE,GAAgB,mBAALqP,IAAqB+U,GAAW7hB,EAAMT,UAAYyS,OAAM,YACjE,IAAIlF,GAAInM,UAAUpC,UAMb,CACL,IAAIwjB,EAAW,IAAIjV,EAEfkV,EAAiBD,EAASZ,GAAOU,EAAU,IAAM,EAAG,IAAME,EAE1DE,EAAuBjQ,OAAM,WAAc+P,EAASxhB,IAAI,KAExD2hB,EAAmBC,YAAY,SAAU3V,GAAQ,IAAIM,EAAEN,KAEvD4V,GAAcP,GAAW7P,OAAM,WAIjC,IAFA,IAAIqQ,EAAY,IAAIvV,EAChBxB,EAAQ,EACLA,KAAS+W,EAAUlB,GAAO7V,EAAOA,GACxC,OAAQ+W,EAAU9hB,KAAK,KAEpB2hB,KACHpV,EAAIoU,EAAQ,SAAU7X,EAAQiX,GAC5Bc,YAAW/X,EAAQyD,EAAGyI,GACtB,IAAItQ,EAAO6P,mBAAkB,IAAIhB,EAAQzK,EAAQyD,GAEjD,OADgB1P,MAAZkjB,GAAuBe,OAAMf,EAAUjS,EAAQpJ,EAAKkc,GAAQlc,GACzDA,KAEPpH,UAAYmC,EACdA,EAAM+N,YAAcjB,IAElBmV,GAAwBG,KAC1BN,EAAU,UACVA,EAAU,OACVzT,GAAUyT,EAAU,SAElBM,GAAcJ,IAAgBF,EAAUX,GAExCU,GAAW7hB,EAAMsiB,cAActiB,EAAMsiB,WApCzCxV,EAAI8U,EAAOX,eAAeC,EAAS3L,EAAMlH,EAAQ8S,GACjDG,aAAYxU,EAAEjP,UAAWgd,GACzBoE,MAAKC,MAAO,EA4Cd,OAPAnF,gBAAejN,EAAGyI,GAElBzO,EAAEyO,GAAQzI,EACVvE,QAAQA,QAAQS,EAAIT,QAAQmB,EAAInB,QAAQO,GAAKgE,GAAKgH,GAAOhN,GAEpD+a,GAASD,EAAOW,UAAUzV,EAAGyI,EAAMlH,GAEjCvB,gDCnFT,IAcI0V,EAbAC,EAAOvc,cAA4B,GASnCkZ,EAAUH,MAAKG,QACfR,EAAelhB,OAAOkhB,aACtB+B,EAAsB+B,gBAAKhB,QAC3BiB,EAAM,GAGNzB,EAAU,SAAUtjB,GACtB,OAAO,WACL,OAAOA,EAAIH,KAAM8F,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,KAIvDyd,EAAU,CAEZjd,IAAK,SAAakC,GAChB,GAAIgG,UAAShG,GAAM,CACjB,IAAIyhB,EAAOnC,EAAQtf,GACnB,OAAa,IAATyhB,EAAsBZ,EAAoBa,oBAAS/jB,KAlB9C,YAkB+DG,IAAIkC,GACrEyhB,EAAOA,EAAK9jB,KAAKie,SAAMte,IAIlCoD,IAAK,SAAaV,EAAKtB,GACrB,OAAOkkB,gBAAKnJ,IAAIiI,oBAAS/jB,KAxBd,WAwB+BqC,EAAKtB,KAK/CokB,EAAWxd,EAAAC,QAAiBiB,YA7BjB,UA6BoD4a,EAASrG,EAAS6H,iBAAM,GAAM,GAG7F1Q,OAAM,WAAc,OAAyE,IAAlE,IAAI4Q,GAAWpiB,KAAK9C,OAAOmlB,QAAUnlB,QAAQilB,GAAM,GAAG/kB,IAAI+kB,OACvFH,EAAcE,gBAAKzB,eAAeC,EAjCrB,WAkCbzB,cAAO+C,EAAY3kB,UAAWgd,GAC9BoE,MAAKC,MAAO,EACZuD,EAAK,CAAC,SAAU,MAAO,MAAO,OAAQ,SAAU3iB,GAC9C,IAAIE,EAAQ4iB,EAAS/kB,UACjBwF,EAASrD,EAAMF,GACnB0J,UAASxJ,EAAOF,EAAK,SAAUoB,EAAGC,GAEhC,GAAI2E,UAAS5E,KAAO0d,EAAa1d,GAAI,CAC9BzD,KAAKqlB,KAAIrlB,KAAKqlB,GAAK,IAAIN,GAC5B,IAAI7V,EAASlP,KAAKqlB,GAAGhjB,GAAKoB,EAAGC,GAC7B,MAAc,OAAPrB,EAAerC,KAAOkP,EAE7B,OAAOtJ,EAAO7F,KAAKC,KAAMyD,EAAGC,i/CCpDpC,IAAA4hB,cAAiB,SAAU1f,EAAQsK,GACjC,QAAStK,GAAU2O,OAAM,WAEvBrE,EAAMtK,EAAO7F,KAAK,KAAM,aAA6B,GAAK6F,EAAO7F,KAAK,SCDtEwlB,MAAQ,GAAG/hB,KACX+B,KAAO,CAAC,EAAG,EAAG,GAElBuF,QAAQA,QAAQxB,EAAIwB,QAAQO,GAAKkJ,OAAM,WAErChP,KAAK/B,UAAK7D,OACL4U,OAAM,WAEXhP,KAAK/B,KAAK,UAELiF,cAA4B8c,QAAS,QAAS,CAEnD/hB,KAAM,SAAcgiB,GAClB,YAAqB7lB,IAAd6lB,EACHD,MAAMxlB,KAAKqP,UAASpP,OACpBulB,MAAMxlB,KAAKqP,UAASpP,MAAOyH,WAAU+d,OCjB7C1a,QAAQA,QAAQ9B,EAAI8B,QAAQO,EAAG,SAAU,CAAE2W,OAAQvZ,gBCAnD,IAAI0H,UAAU1H,KAAkB,WAChCgd,oBAAiB,SAAUpc,EAAGqc,GAC5B,IACI1c,EADAqG,EAAI7F,UAASH,GAAGiH,YAEpB,YAAa3Q,IAAN0P,GAAiD1P,OAA7BqJ,EAAIQ,UAAS6F,GAAGc,YAAyBuV,EAAIje,WAAUuB,ICNhF2c,GAAKld,WAAwB,GAIjCmd,oBAAiB,SAAU5c,EAAG6E,EAAOgL,GACnC,OAAOhL,GAASgL,EAAU8M,GAAG3c,EAAG6E,GAAO1L,OAAS,ICI9C0jB,KAAOhe,KAAK4F,IACZqY,MAAQ,GAAGrjB,KACXsjB,OAAS,QACTC,OAAS,SACT9M,aAAa,YACb+M,WAAa,WAGbC,YAAc3R,OAAM,cAGxB9L,UAAyB,QAAS,EAAG,SAAU6D,EAAS6Z,EAAOC,EAAQjL,GACrE,IAAIkL,EAkDJ,OAxCEA,EAR6B,KAA7B,OAAON,QAAQ,QAAQ,IACe,GAAtC,OAAOA,QAAQ,QAAS,GAAGC,SACQ,GAAnC,KAAKD,QAAQ,WAAWC,SACW,GAAnC,IAAID,QAAQ,YAAYC,SACxB,IAAID,QAAQ,QAAQC,QAAU,GAC9B,GAAGD,QAAQ,MAAMC,QAGD,SAAUM,EAAWC,GACnC,IAAI9R,EAAS/R,OAAO1C,MACpB,QAAkBL,IAAd2mB,GAAqC,IAAVC,EAAa,MAAO,GAEnD,IAAK3O,UAAS0O,GAAY,OAAOF,EAAOrmB,KAAK0U,EAAQ6R,EAAWC,GAWhE,IAVA,IASI5M,EAAOF,EAAW+M,EATlBC,EAAS,GACTjL,GAAS8K,EAAU3N,WAAa,IAAM,KAC7B2N,EAAU1N,UAAY,IAAM,KAC5B0N,EAAUzN,QAAU,IAAM,KAC1ByN,EAAUxN,OAAS,IAAM,IAClC4N,EAAgB,EAChBC,OAAuBhnB,IAAV4mB,EAAsBN,WAAaM,IAAU,EAE1DK,EAAgB,IAAI1S,OAAOoS,EAAUtb,OAAQwQ,EAAQ,MAElD7B,EAAQG,YAAW/Z,KAAK6mB,EAAenS,QAC5CgF,EAAYmN,EAAc1N,eACVwN,IACdD,EAAOhkB,KAAKgS,EAAO5R,MAAM6jB,EAAe/M,EAAM9L,QAC1C8L,EAAMqM,QAAU,GAAKrM,EAAM9L,MAAQ4G,EAAOuR,SAASF,MAAMjgB,MAAM4gB,EAAQ9M,EAAM9W,MAAM,IACvF2jB,EAAa7M,EAAM,GAAGqM,QACtBU,EAAgBjN,EACZgN,EAAOT,SAAWW,KAEpBC,EAAc1N,gBAAgBS,EAAM9L,OAAO+Y,EAAc1N,gBAK/D,OAHIwN,IAAkBjS,EAAOuR,SACvBQ,GAAeI,EAAcrhB,KAAK,KAAKkhB,EAAOhkB,KAAK,IAClDgkB,EAAOhkB,KAAKgS,EAAO5R,MAAM6jB,IACzBD,EAAOT,QAAUW,EAAaF,EAAO5jB,MAAM,EAAG8jB,GAAcF,GAG5D,IAAIV,aAAQpmB,EAAW,GAAGqmB,QACnB,SAAUM,EAAWC,GACnC,YAAqB5mB,IAAd2mB,GAAqC,IAAVC,EAAc,GAAKH,EAAOrmB,KAAKC,KAAMsmB,EAAWC,IAGpEH,EAGX,CAGL,SAAeE,EAAWC,GACxB,IAAIld,EAAIiD,EAAQtM,MACZ6mB,EAAwBlnB,MAAb2mB,OAAyB3mB,EAAY2mB,EAAUH,GAC9D,YAAoBxmB,IAAbknB,EACHA,EAAS9mB,KAAKumB,EAAWjd,EAAGkd,GAC5BF,EAActmB,KAAK2C,OAAO2G,GAAIid,EAAWC,IAO/C,SAAU3L,EAAQ2L,GAChB,IAAIjV,EAAM6J,EAAgBkL,EAAezL,EAAQ5a,KAAMumB,EAAOF,IAAkBD,GAChF,GAAI9U,EAAIrQ,KAAM,OAAOqQ,EAAIvQ,MAEzB,IAAIqa,EAAK5R,UAASoR,GACd5R,EAAItG,OAAO1C,MACXqP,EAAImB,oBAAmB4K,EAAIlH,QAE3B4S,EAAkB1L,EAAGvC,QACrB2C,GAASJ,EAAGzC,WAAa,IAAM,KACtByC,EAAGxC,UAAY,IAAM,KACrBwC,EAAGvC,QAAU,IAAM,KACnBqN,WAAa,IAAM,KAI5BW,EAAW,IAAIxX,EAAE6W,WAAa9K,EAAK,OAASA,EAAGpQ,OAAS,IAAKwQ,GAC7DuL,OAAgBpnB,IAAV4mB,EAAsBN,WAAaM,IAAU,EACvD,GAAY,IAARQ,EAAW,MAAO,GACtB,GAAiB,IAAb/d,EAAE7G,OAAc,OAAuC,OAAhC6kB,oBAAeH,EAAU7d,GAAc,CAACA,GAAK,GAIxE,IAHA,IAAIie,EAAI,EACJC,EAAI,EACJhF,EAAI,GACDgF,EAAIle,EAAE7G,QAAQ,CACnB0kB,EAASpN,UAAYyM,WAAagB,EAAI,EACtC,IACI9nB,EADA+nB,EAAIH,oBAAeH,EAAUX,WAAald,EAAIA,EAAEnG,MAAMqkB,IAE1D,GACQ,OAANC,IACC/nB,EAAIymB,KAAKjW,UAASiX,EAASpN,WAAayM,WAAa,EAAIgB,IAAKle,EAAE7G,WAAa8kB,EAE9EC,EAAIE,oBAAmBpe,EAAGke,EAAGJ,OACxB,CAEL,GADA5E,EAAEzf,KAAKuG,EAAEnG,MAAMokB,EAAGC,IACdhF,EAAE/f,SAAW4kB,EAAK,OAAO7E,EAC7B,IAAK,IAAIhgB,EAAI,EAAGA,GAAKilB,EAAEhlB,OAAS,EAAGD,IAEjC,GADAggB,EAAEzf,KAAK0kB,EAAEjlB,IACLggB,EAAE/f,SAAW4kB,EAAK,OAAO7E,EAE/BgF,EAAID,EAAI7nB,GAIZ,OADA8iB,EAAEzf,KAAKuG,EAAEnG,MAAMokB,IACR/E,MChIb,IAAIK,OAAS9Z,WAAyBW,EACtCie,eAAiB,SAAUC,GACzB,OAAO,SAAUjgB,GAOf,IANA,IAKIhF,EALAgH,EAAI8I,WAAU9K,GACdlE,EAAO4R,YAAQ1L,GACflH,EAASgB,EAAKhB,OACdD,EAAI,EACJgN,EAAS,GAEN/M,EAASD,GAAOqgB,OAAOxiB,KAAKsJ,EAAGhH,EAAMc,EAAKjB,OAC/CgN,EAAOzM,KAAK6kB,EAAY,CAACjlB,EAAKgH,EAAEhH,IAAQgH,EAAEhH,IAC1C,OAAO6M,ICXTyO,SAAWlV,gBAA8B,GAE7CqC,QAAQA,QAAQ9B,EAAG,SAAU,CAC3B9F,QAAS,SAAiBmE,GACxB,OAAOsW,SAAStW,MCJpB,IAAIkgB,QAAU9e,gBAA8B,GAE5CqC,QAAQA,QAAQ9B,EAAG,SAAU,CAC3B5F,OAAQ,SAAgBiE,GACtB,OAAOkgB,QAAQlgB,MCEnB,IAAIsL,MAAM9K,KAAK8K,IACXlF,MAAM5F,KAAK4F,IACXH,QAAQzF,KAAKyF,MACbka,qBAAuB,4BACvBC,8BAAgC,oBAEhCC,cAAgB,SAAUrgB,GAC5B,YAAc1H,IAAP0H,EAAmBA,EAAK3E,OAAO2E,IAIxCoB,UAAyB,UAAW,EAAG,SAAU6D,EAASqb,EAASC,EAAUzM,GAC3E,MAAO,CAGL,SAAiB0M,EAAaC,GAC5B,IAAIze,EAAIiD,EAAQtM,MACZuH,EAAoB5H,MAAfkoB,OAA2BloB,EAAYkoB,EAAYF,GAC5D,YAAchoB,IAAP4H,EACHA,EAAGxH,KAAK8nB,EAAaxe,EAAGye,GACxBF,EAAS7nB,KAAK2C,OAAO2G,GAAIwe,EAAaC,IAI5C,SAAUlN,EAAQkN,GAChB,IAAIxW,EAAM6J,EAAgByM,EAAUhN,EAAQ5a,KAAM8nB,GAClD,GAAIxW,EAAIrQ,KAAM,OAAOqQ,EAAIvQ,MAEzB,IAAIqa,EAAK5R,UAASoR,GACd5R,EAAItG,OAAO1C,MACX+nB,EAA4C,mBAAjBD,EAC1BC,IAAmBD,EAAeplB,OAAOolB,IAC9C,IAAIxnB,EAAS8a,EAAG9a,OAChB,GAAIA,EAAQ,CACV,IAAI0nB,EAAc5M,EAAGvC,QACrBuC,EAAG3B,UAAY,EAGjB,IADA,IAAIwO,EAAU,KACD,CACX,IAAI/Y,EAASqM,oBAAWH,EAAIpS,GAC5B,GAAe,OAAXkG,EAAiB,MAErB,GADA+Y,EAAQxlB,KAAKyM,IACR5O,EAAQ,MAEI,KADFoC,OAAOwM,EAAO,MACRkM,EAAG3B,UAAY2N,oBAAmBpe,EAAG4G,UAASwL,EAAG3B,WAAYuO,IAIpF,IAFA,IAAIE,EAAoB,GACpBC,EAAqB,EAChBjmB,EAAI,EAAGA,EAAI+lB,EAAQ9lB,OAAQD,IAAK,CACvCgN,EAAS+Y,EAAQ/lB,GASjB,IARA,IAAIkmB,EAAU1lB,OAAOwM,EAAO,IACxBmZ,EAAW1V,MAAIlF,MAAIE,WAAUuB,EAAOrB,OAAQ7E,EAAE7G,QAAS,GACvDmmB,EAAW,GAMN/Q,EAAI,EAAGA,EAAIrI,EAAO/M,OAAQoV,IAAK+Q,EAAS7lB,KAAKilB,cAAcxY,EAAOqI,KAC3E,IAAIgR,EAAgBrZ,EAAO+K,OAC3B,GAAI8N,EAAmB,CACrB,IAAIS,EAAe,CAACJ,GAAS/d,OAAOie,EAAUD,EAAUrf,QAClCrJ,IAAlB4oB,GAA6BC,EAAa/lB,KAAK8lB,GACnD,IAAIE,EAAc/lB,OAAOolB,EAAajiB,WAAMlG,EAAW6oB,SAEvDC,EAAcC,EAAgBN,EAASpf,EAAGqf,EAAUC,EAAUC,EAAeT,GAE3EO,GAAYF,IACdD,GAAqBlf,EAAEnG,MAAMslB,EAAoBE,GAAYI,EAC7DN,EAAqBE,EAAWD,EAAQjmB,QAG5C,OAAO+lB,EAAoBlf,EAAEnG,MAAMslB,KAKvC,SAASO,EAAgBN,EAAS5O,EAAK6O,EAAUC,EAAUC,EAAeE,GACxE,IAAIE,EAAUN,EAAWD,EAAQjmB,OAC7BymB,EAAIN,EAASnmB,OACb0mB,EAAUpB,8BAKd,YAJsB9nB,IAAlB4oB,IACFA,EAAgBnZ,UAASmZ,GACzBM,EAAUrB,sBAELI,EAAS7nB,KAAK0oB,EAAaI,EAAS,SAAUlP,EAAOmP,GAC1D,IAAIC,EACJ,OAAQD,EAAGhI,OAAO,IAChB,IAAK,IAAK,MAAO,IACjB,IAAK,IAAK,OAAOsH,EACjB,IAAK,IAAK,OAAO5O,EAAI3W,MAAM,EAAGwlB,GAC9B,IAAK,IAAK,OAAO7O,EAAI3W,MAAM8lB,GAC3B,IAAK,IACHI,EAAUR,EAAcO,EAAGjmB,MAAM,GAAI,IACrC,MACF,QACE,IAAImmB,GAAKF,EACT,GAAU,IAANE,EAAS,OAAOrP,EACpB,GAAIqP,EAAIJ,EAAG,CACT,IAAIxf,EAAIkE,QAAM0b,EAAI,IAClB,OAAU,IAAN5f,EAAgBuQ,EAChBvQ,GAAKwf,OAA8BjpB,IAApB2oB,EAASlf,EAAI,GAAmB0f,EAAGhI,OAAO,GAAKwH,EAASlf,EAAI,GAAK0f,EAAGhI,OAAO,GACvFnH,EAEToP,EAAUT,EAASU,EAAI,GAE3B,YAAmBrpB,IAAZopB,EAAwB,GAAKA,OCjH1C,ICYIE,MAAOC,QAASxiB,KDZpByiB,QAAiB,SAAU5hB,EAAI6hB,EAAM5hB,GACnC,IAAI6hB,OAAc1pB,IAAT6H,EACT,OAAQ4hB,EAAKjnB,QACX,KAAK,EAAG,OAAOknB,EAAK9hB,IACAA,EAAGxH,KAAKyH,GAC5B,KAAK,EAAG,OAAO6hB,EAAK9hB,EAAG6hB,EAAK,IACR7hB,EAAGxH,KAAKyH,EAAM4hB,EAAK,IACvC,KAAK,EAAG,OAAOC,EAAK9hB,EAAG6hB,EAAK,GAAIA,EAAK,IACjB7hB,EAAGxH,KAAKyH,EAAM4hB,EAAK,GAAIA,EAAK,IAChD,KAAK,EAAG,OAAOC,EAAK9hB,EAAG6hB,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAC1B7hB,EAAGxH,KAAKyH,EAAM4hB,EAAK,GAAIA,EAAK,GAAIA,EAAK,IACzD,KAAK,EAAG,OAAOC,EAAK9hB,EAAG6hB,EAAK,GAAIA,EAAK,GAAIA,EAAK,GAAIA,EAAK,IACnC7hB,EAAGxH,KAAKyH,EAAM4hB,EAAK,GAAIA,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAClE,OAAO7hB,EAAG1B,MAAM2B,EAAM4hB,ICTtBE,QAAUhpB,QAAOgpB,QACjBC,QAAUjpB,QAAOkpB,aACjBC,UAAYnpB,QAAOopB,eACnBC,eAAiBrpB,QAAOqpB,eACxBC,SAAWtpB,QAAOspB,SAClBC,QAAU,EACVC,MAAQ,GACRC,mBAAqB,qBAErBC,IAAM,WACR,IAAI/f,GAAMjK,KAEV,GAAI8pB,MAAMxnB,eAAe2H,GAAK,CAC5B,IAAI1C,EAAKuiB,MAAM7f,UACR6f,MAAM7f,GACb1C,MAGA0iB,SAAW,SAAU5qB,GACvB2qB,IAAIjqB,KAAKV,EAAMykB,OAGZyF,SAAYE,YACfF,QAAU,SAAsBhiB,GAG9B,IAFA,IAAI6hB,EAAO,GACPlnB,EAAI,EACD4D,UAAU3D,OAASD,GAAGknB,EAAK3mB,KAAKqD,UAAU5D,MAMjD,OALA4nB,QAAQD,SAAW,WAEjBK,QAAoB,mBAAN3iB,EAAmBA,EAAKO,SAASP,GAAK6hB,IAEtDH,MAAMY,SACCA,SAETJ,UAAY,SAAwBxf,UAC3B6f,MAAM7f,IAGmB,WAA9BxB,KAAkB6gB,SACpBL,MAAQ,SAAUhf,GAChBqf,QAAQa,SAASre,KAAIke,IAAK/f,EAAI,KAGvB2f,UAAYA,SAASQ,IAC9BnB,MAAQ,SAAUhf,GAChB2f,SAASQ,IAAIte,KAAIke,IAAK/f,EAAI,KAGnB0f,gBAETjjB,MADAwiB,QAAU,IAAIS,gBACCU,MACfnB,QAAQoB,MAAMC,UAAYN,SAC1BhB,MAAQnd,KAAIpF,KAAK8jB,YAAa9jB,KAAM,IAG3BpG,QAAOmqB,kBAA0C,mBAAfD,cAA8BlqB,QAAOoqB,eAChFzB,MAAQ,SAAUhf,GAChB3J,QAAOkqB,YAAYvgB,EAAK,GAAI,MAE9B3J,QAAOmqB,iBAAiB,UAAWR,UAAU,IAG7ChB,MADSc,sBAAsBY,WAAI,UAC3B,SAAU1gB,GAChB2gB,MAAK3lB,YAAY0lB,WAAI,WAAWZ,oBAAsB,WACpDa,MAAKC,YAAY7qB,MACjBgqB,IAAIjqB,KAAKkK,KAKL,SAAUA,GAChB6gB,WAAWhf,KAAIke,IAAK/f,EAAI,GAAI,KAIlC,IAAA8gB,MAAiB,CACfhoB,IAAKwmB,QACL1E,MAAO4E,WCjFLuB,UAAYviB,MAAmB1F,IAC/BkoB,SAAW3qB,QAAO4qB,kBAAoB5qB,QAAO6qB,uBAC7C7B,UAAUhpB,QAAOgpB,QACjB8B,UAAU9qB,QAAO8qB,QACjBC,OAAuC,WAA9BxiB,KAAkBygB,WAE/BgC,WAAiB,WACf,IAAItmB,EAAMumB,EAAMC,EAEZC,EAAQ,WACV,IAAIC,EAAQnkB,EAEZ,IADI8jB,SAAWK,EAASpC,UAAQqC,SAASD,EAAOE,OACzC5mB,GAAM,CACXuC,EAAKvC,EAAKuC,GACVvC,EAAOA,EAAKlE,KACZ,IACEyG,IACA,MAAOnI,GAGP,MAFI4F,EAAMwmB,IACLD,OAAO5rB,EACNP,GAERmsB,OAAO5rB,EACL+rB,GAAQA,EAAOG,SAIrB,GAAIR,OACFG,EAAS,WACPlC,UAAQa,SAASsB,SAGd,IAAIR,UAAc3qB,QAAOwrB,WAAaxrB,QAAOwrB,UAAUC,WAQvD,GAAIX,WAAWA,UAAQY,QAAS,CAErC,IAAIC,EAAUb,UAAQY,aAAQrsB,GAC9B6rB,EAAS,WACPS,EAAQC,KAAKT,SASfD,EAAS,WAEPR,UAAUjrB,KAAKO,QAAQmrB,QAvBgD,CACzE,IAAIU,GAAS,EACTC,EAAOxsB,SAASysB,eAAe,IACnC,IAAIpB,SAASQ,GAAOa,QAAQF,EAAM,CAAEG,eAAe,IACnDf,EAAS,WACPY,EAAKtI,KAAOqI,GAAUA,GAsB1B,OAAO,SAAU5kB,GACf,IAAIilB,EAAO,CAAEjlB,GAAIA,EAAIzG,UAAMnB,GACvB4rB,IAAMA,EAAKzqB,KAAO0rB,GACjBxnB,IACHA,EAAOwnB,EACPhB,KACAD,EAAOiB,IC9Db,SAASC,kBAAkBpd,GACzB,IAAI2c,EAASU,EACb1sB,KAAKisB,QAAU,IAAI5c,EAAE,SAAUsd,EAAWC,GACxC,QAAgBjtB,IAAZqsB,QAAoCrsB,IAAX+sB,EAAsB,MAAMzqB,UAAU,2BACnE+pB,EAAUW,EACVD,EAASE,IAEX5sB,KAAKgsB,QAAUvkB,WAAUukB,GACzBhsB,KAAK0sB,OAASjlB,WAAUilB,GAG1B,ICUIG,SAAUC,4BAA6BC,qBAAsBC,QDVjEC,IAAmB,SAAU5d,GAC3B,OAAO,IAAIod,kBAAkBpd,kCEhB/B6d,SAAiB,SAAU3kB,GACzB,IACE,MAAO,CAAEnJ,GAAG,EAAO+tB,EAAG5kB,KACtB,MAAOnJ,GACP,MAAO,CAAEA,GAAG,EAAM+tB,EAAG/tB,KCHrB0sB,YAAYxrB,QAAOwrB,UAEvBsB,WAAiBtB,aAAaA,YAAUuB,WAAa,GCCrDC,gBAAiB,SAAUje,EAAGiJ,GAE5B,GADA9O,UAAS6F,GACLhH,UAASiQ,IAAMA,EAAEhI,cAAgBjB,EAAG,OAAOiJ,EAC/C,IAAIiV,EAAoBC,sBAAqBpkB,EAAEiG,GAG/C,OADA2c,EADcuB,EAAkBvB,SACxB1T,GACDiV,EAAkBtB,SCNvB9b,UAAU1H,KAAkB,WAEhCglB,YAAiB,SAAU9b,GACzB,IAAItC,EAAI/O,QAAOqR,GACXgK,cAAetM,IAAMA,EAAEc,YAAUhH,UAAGC,EAAEiG,EAAGc,UAAS,CACpDvM,cAAc,EACdzD,IAAK,WAAc,OAAOH,SJC1BwsB,KAAO/jB,MAAmB1F,IAC1B2qB,UAAY7kB,aAKZ8kB,QAAU,UACV1rB,YAAY3B,QAAO2B,UACnBqnB,UAAUhpB,QAAOgpB,QACjBsE,SAAWtE,WAAWA,UAAQsE,SAC9BC,GAAKD,UAAYA,SAASC,IAAM,GAChCC,SAAWxtB,QAAOqtB,SAClBtC,SAA6B,WAApB5c,SAAQ6a,WACjByE,MAAQ,aAERP,qBAAuBV,4BAA8BkB,sBAA2B5kB,EAEhF6kB,aAAe,WACjB,IAEE,IAAIhC,EAAU6B,SAAS9B,QAAQ,GAC3BkC,GAAejC,EAAQ3b,YAAc,IAAIxH,KAAkB,YAAc,SAAUP,GACrFA,EAAKwlB,MAAOA,QAGd,OAAQ1C,UAA0C,mBAAzB8C,wBACpBlC,EAAQC,KAAK6B,iBAAkBG,GAIT,IAAtBL,GAAG3oB,QAAQ,SACyB,IAApCmoB,WAAUnoB,QAAQ,aACvB,MAAO9F,KAfQ,GAmBfgvB,WAAa,SAAU/mB,GACzB,IAAI6kB,EACJ,SAAO7jB,UAAShB,IAAkC,mBAAnB6kB,EAAO7kB,EAAG6kB,QAAsBA,GAE7DV,OAAS,SAAUS,EAASoC,GAC9B,IAAIpC,EAAQqC,GAAZ,CACArC,EAAQqC,IAAK,EACb,IAAIC,EAAQtC,EAAQuC,GACpBd,UAAU,WAoCR,IAnCA,IAAI3sB,EAAQkrB,EAAQwC,GAChBC,EAAmB,GAAdzC,EAAQ0C,GACbzsB,EAAI,EACJ8nB,EAAM,SAAU4E,GAClB,IAII1f,EAAQgd,EAAM2C,EAJdC,EAAUJ,EAAKE,EAASF,GAAKE,EAASG,KACtC/C,EAAU4C,EAAS5C,QACnBU,EAASkC,EAASlC,OAClBf,EAASiD,EAASjD,OAEtB,IACMmD,GACGJ,IACe,GAAdzC,EAAQ+C,IAASC,kBAAkBhD,GACvCA,EAAQ+C,GAAK,IAEC,IAAZF,EAAkB5f,EAASnO,GAEzB4qB,GAAQA,EAAOE,QACnB3c,EAAS4f,EAAQ/tB,GACb4qB,IACFA,EAAOC,OACPiD,GAAS,IAGT3f,IAAW0f,EAAS3C,QACtBS,EAAOzqB,YAAU,yBACRiqB,EAAOkC,WAAWlf,IAC3Bgd,EAAKnsB,KAAKmP,EAAQ8c,EAASU,GACtBV,EAAQ9c,IACVwd,EAAO3rB,GACd,MAAO3B,GACHusB,IAAWkD,GAAQlD,EAAOC,OAC9Bc,EAAOttB,KAGJmvB,EAAMpsB,OAASD,GAAG8nB,EAAIuE,EAAMrsB,MACnC+pB,EAAQuC,GAAK,GACbvC,EAAQqC,IAAK,EACTD,IAAapC,EAAQ+C,IAAIE,YAAYjD,OAGzCiD,YAAc,SAAUjD,GAC1BO,KAAKzsB,KAAKO,QAAQ,WAChB,IAEI4O,EAAQ4f,EAASK,EAFjBpuB,EAAQkrB,EAAQwC,GAChBW,EAAYC,YAAYpD,GAe5B,GAbImD,IACFlgB,EAASogB,SAAQ,WACXjE,SACF/B,UAAQiG,KAAK,qBAAsBxuB,EAAOkrB,IACjC6C,EAAUxuB,QAAOkvB,sBAC1BV,EAAQ,CAAE7C,QAASA,EAASwD,OAAQ1uB,KAC1BouB,EAAU7uB,QAAO6uB,UAAYA,EAAQzuB,OAC/CyuB,EAAQzuB,MAAM,8BAA+BK,KAIjDkrB,EAAQ+C,GAAK3D,UAAUgE,YAAYpD,GAAW,EAAI,GAClDA,EAAQyD,QAAK/vB,EACXyvB,GAAalgB,EAAO9P,EAAG,MAAM8P,EAAOie,KAGxCkC,YAAc,SAAUpD,GAC1B,OAAsB,IAAfA,EAAQ+C,IAAkD,KAArC/C,EAAQyD,IAAMzD,EAAQuC,IAAIrsB,QAEpD8sB,kBAAoB,SAAUhD,GAChCO,KAAKzsB,KAAKO,QAAQ,WAChB,IAAIwuB,EACAzD,SACF/B,UAAQiG,KAAK,mBAAoBtD,IACxB6C,EAAUxuB,QAAOqvB,qBAC1Bb,EAAQ,CAAE7C,QAASA,EAASwD,OAAQxD,EAAQwC,QAI9CmB,QAAU,SAAU7uB,GACtB,IAAIkrB,EAAUjsB,KACVisB,EAAQ4D,KACZ5D,EAAQ4D,IAAK,GACb5D,EAAUA,EAAQ6D,IAAM7D,GAChBwC,GAAK1tB,EACbkrB,EAAQ0C,GAAK,EACR1C,EAAQyD,KAAIzD,EAAQyD,GAAKzD,EAAQuC,GAAG3rB,SACzC2oB,OAAOS,GAAS,KAEd8D,SAAW,SAAUhvB,GACvB,IACImrB,EADAD,EAAUjsB,KAEd,IAAIisB,EAAQ4D,GAAZ,CACA5D,EAAQ4D,IAAK,EACb5D,EAAUA,EAAQ6D,IAAM7D,EACxB,IACE,GAAIA,IAAYlrB,EAAO,MAAMkB,YAAU,qCACnCiqB,EAAOkC,WAAWrtB,IACpB2sB,UAAU,WACR,IAAIjK,EAAU,CAAEqM,GAAI7D,EAAS4D,IAAI,GACjC,IACE3D,EAAKnsB,KAAKgB,EAAO+K,KAAIikB,SAAUtM,EAAS,GAAI3X,KAAI8jB,QAASnM,EAAS,IAClE,MAAOrkB,GACPwwB,QAAQ7vB,KAAK0jB,EAASrkB,OAI1B6sB,EAAQwC,GAAK1tB,EACbkrB,EAAQ0C,GAAK,EACbnD,OAAOS,GAAS,IAElB,MAAO7sB,GACPwwB,QAAQ7vB,KAAK,CAAE+vB,GAAI7D,EAAS4D,IAAI,GAASzwB,MAKxC6uB,aAEHH,SAAW,SAAiBkC,GAC1BrM,YAAW3jB,KAAM8tB,SAAUH,QAAS,MACpClmB,WAAUuoB,GACVnD,SAAS9sB,KAAKC,MACd,IACEgwB,EAASlkB,KAAIikB,SAAU/vB,KAAM,GAAI8L,KAAI8jB,QAAS5vB,KAAM,IACpD,MAAOmF,GACPyqB,QAAQ7vB,KAAKC,KAAMmF,MAIvB0nB,SAAW,SAAiBmD,GAC1BhwB,KAAKwuB,GAAK,GACVxuB,KAAK0vB,QAAK/vB,EACVK,KAAK2uB,GAAK,EACV3uB,KAAK6vB,IAAK,EACV7vB,KAAKyuB,QAAK9uB,EACVK,KAAKgvB,GAAK,EACVhvB,KAAKsuB,IAAK,IAEHluB,UAAY8V,aAA2B4X,SAAS1tB,UAAW,CAElE8rB,KAAM,SAAc+D,EAAaC,GAC/B,IAAItB,EAAWpB,qBAAqBhd,oBAAmBxQ,KAAM8tB,WAO7D,OANAc,EAASF,GAA2B,mBAAfuB,GAA4BA,EACjDrB,EAASG,KAA4B,mBAAdmB,GAA4BA,EACnDtB,EAASjD,OAASN,SAAS/B,UAAQqC,YAAShsB,EAC5CK,KAAKwuB,GAAG/rB,KAAKmsB,GACT5uB,KAAK0vB,IAAI1vB,KAAK0vB,GAAGjtB,KAAKmsB,GACtB5uB,KAAK2uB,IAAInD,OAAOxrB,MAAM,GACnB4uB,EAAS3C,SAGlBkE,MAAS,SAAUD,GACjB,OAAOlwB,KAAKksB,UAAKvsB,EAAWuwB,MAGhCnD,qBAAuB,WACrB,IAAId,EAAU,IAAIY,SAClB7sB,KAAKisB,QAAUA,EACfjsB,KAAKgsB,QAAUlgB,KAAIikB,SAAU9D,EAAS,GACtCjsB,KAAK0sB,OAAS5gB,KAAI8jB,QAAS3D,EAAS,IAEtC+B,sBAA2B5kB,EAAIokB,qBAAuB,SAAUne,GAC9D,OAAOA,IAAMye,UAAYze,IAAM2d,QAC3B,IAAID,qBAAqB1d,GACzByd,4BAA4Bzd,KAIpCvE,QAAQA,QAAQS,EAAIT,QAAQmB,EAAInB,QAAQO,GAAK4iB,WAAY,CAAE7C,QAAS0C,WACpEvX,gBAAgCuX,SAAUH,SAC1CrW,YAA0BqW,SAC1BX,QAAUxV,MAAmBmW,SAG7B7iB,QAAQA,QAAQ9B,EAAI8B,QAAQO,GAAK4iB,WAAYN,QAAS,CAEpDjB,OAAQ,SAAgB0D,GACtB,IAAIC,EAAa7C,qBAAqBxtB,MAGtC,OADA4sB,EADeyD,EAAW3D,QACjB0D,GACFC,EAAWpE,WAGtBnhB,QAAQA,QAAQ9B,EAAI8B,QAAQO,GAAKwS,WAAYoQ,YAAaN,QAAS,CAEjE3B,QAAS,SAAiB1T,GACxB,OAAOgY,gBAAezS,UAAW7d,OAASgtB,QAAUc,SAAW9tB,KAAMsY,MAGzExN,QAAQA,QAAQ9B,EAAI8B,QAAQO,IAAM4iB,YAAcsC,YAA0B,SAAUxhB,GAClF+e,SAAS0C,IAAIzhB,GAAa,MAAEgf,UACzBJ,QAAS,CAEZ6C,IAAK,SAAa3N,GAChB,IAAIxT,EAAIrP,KACJqwB,EAAa7C,qBAAqBne,GAClC2c,EAAUqE,EAAWrE,QACrBU,EAAS2D,EAAW3D,OACpBxd,EAASogB,SAAQ,WACnB,IAAIlsB,EAAS,GACTyK,EAAQ,EACR4iB,EAAY,EAChB7M,OAAMf,GAAU,EAAO,SAAUoJ,GAC/B,IAAIyE,EAAS7iB,IACT8iB,GAAgB,EACpBvtB,EAAOX,UAAK9C,GACZ8wB,IACAphB,EAAE2c,QAAQC,GAASC,KAAK,SAAUnrB,GAC5B4vB,IACJA,GAAgB,EAChBvtB,EAAOstB,GAAU3vB,IACf0vB,GAAazE,EAAQ5oB,KACtBspB,OAEH+D,GAAazE,EAAQ5oB,KAGzB,OADI8L,EAAO9P,GAAGstB,EAAOxd,EAAOie,GACrBkD,EAAWpE,SAGpB2E,KAAM,SAAc/N,GAClB,IAAIxT,EAAIrP,KACJqwB,EAAa7C,qBAAqBne,GAClCqd,EAAS2D,EAAW3D,OACpBxd,EAASogB,SAAQ,WACnB1L,OAAMf,GAAU,EAAO,SAAUoJ,GAC/B5c,EAAE2c,QAAQC,GAASC,KAAKmE,EAAWrE,QAASU,OAIhD,OADIxd,EAAO9P,GAAGstB,EAAOxd,EAAOie,GACrBkD,EAAWpE,WKtRtB,IAAI4E,YAAc,aACdC,YAAc,GAAGD,aAErB/lB,QAAQA,QAAQxB,EAAIwB,QAAQO,EAAI5C,eAA8BooB,aAAc,SAAU,CACpFE,WAAY,SAAoBtvB,GAC9B,IAAI+F,EAAO2Q,eAAQnY,KAAMyB,EAAcovB,aACnChjB,EAAQ+B,UAAS/H,KAAK4F,IAAI3H,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,EAAW6H,EAAKrF,SAChFqD,EAAS9C,OAAOjB,GACpB,OAAOqvB,YACHA,YAAY/wB,KAAKyH,EAAMhC,EAAQqI,GAC/BrG,EAAK3E,MAAMgL,EAAOA,EAAQrI,EAAOrD,UAAYqD,KCZrDsF,QAAQA,QAAQ9B,EAAG,SAAU,CAC3BwE,MAAO,SAAewjB,GAEpB,OAAOA,GAAUA,KCFrB,IAAMxN,eAAiB,SAAAyN,UAAUA,MAAAA,EAAiDA,EAAM3gB,YAAc,MAChG4gB,WAAa,SAACD,EAAO3gB,UAAgB6gB,QAAQF,GAAS3gB,GAAe2gB,aAAiB3gB,IACtF8gB,kBAAoB,SAAAH,UAASA,MAAAA,GAC7B5oB,SAAW,SAAA4oB,UAASzN,eAAeyN,KAAWhxB,QAC9CoxB,SAAW,SAAAJ,UAASzN,eAAeyN,KAAWK,SAAWA,OAAO9jB,MAAMyjB,IACtEM,SAAW,SAAAN,UAASzN,eAAeyN,KAAWvuB,QAC9C8uB,UAAY,SAAAP,UAASzN,eAAeyN,KAAWE,SAC/CxmB,WAAa,SAAAsmB,UAASzN,eAAeyN,KAAWnpB,UAChDmI,QAAU,SAAAghB,UAAS/jB,MAAM+C,QAAQghB,IACjCQ,UAAY,SAAAR,UAASC,WAAWD,EAAOS,UACvCC,WAAa,SAAAV,UAASC,WAAWD,EAAOzR,WACxCoS,UAAY,SAAAX,UAASC,WAAWD,EAAOY,UACvCC,WAAa,SAAAb,UAASzN,eAAeyN,KAAWc,MAChDC,QAAU,SAAAf,UAASC,WAAWD,EAAO5wB,QACrC4xB,gBAAkB,SAAAhB,UAASC,WAAWD,EAAOiB,gBAC7CC,MAAQ,SAAAlB,UAASC,WAAWD,EAAOpyB,OAAOuzB,eAAiBlB,WAAWD,EAAOpyB,OAAOwzB,SACpFC,QAAU,SAAArB,UAASC,WAAWD,EAAOsB,aAAgBnB,kBAAkBH,IAAUM,SAASN,EAAM3T,OAEhGkV,QAAU,SAAAvB,UACZG,kBAAkBH,KAChBM,SAASN,IAAUhhB,QAAQghB,IAAUU,WAAWV,MAAYA,EAAM9uB,QACnEkG,SAAS4oB,KAAWhxB,OAAOkD,KAAK8tB,GAAO9uB,QAEtCswB,MAAQ,SAAAxB,MAENC,WAAWD,EAAOpyB,OAAOqF,YAClB,MAINqtB,SAASN,UACH,MAIPxc,EAASwc,EACRA,EAAMF,WAAW,YAAeE,EAAMF,WAAW,cAClDtc,EAAM,UAAApK,OAAa4mB,eAIXuB,QAAQ,IAAItuB,IAAIuQ,GAAQ9N,UAClC,MAAOvH,UACE,IAIfszB,KAAe,CACXC,gBAAiBvB,kBACjBtnB,OAAQzB,SACR2oB,OAAQK,SACR5c,OAAQ8c,SACRqB,QAASpB,UACTqB,SAAUloB,WACVmoB,MAAO7iB,QACP8iB,QAAStB,UACTuB,SAAUrB,WACVsB,QAASrB,UACTsB,SAAUpB,WACVzyB,MAAO2yB,QACPmB,cAAelB,gBACfmB,IAAKjB,MACLkB,MAAOf,QACP9tB,IAAKiuB,MACL1E,MAAOyE,SC3DLc,yBAA4B,eAE1BC,GAAY,UAENC,EAAUvzB,OAAOC,eAAe,GAAI,UAAW,CACjDC,IADiD,kBAE7CozB,GAAY,EACL,QAGf10B,OAAO4rB,iBAAiB,OAAQ,KAAM+I,GACtC30B,OAAO40B,oBAAoB,OAAQ,KAAMD,GAC3C,MAAOp0B,WAIFm0B,EAhBuB,GAoBlC,SAAgBG,eAAeT,EAAS5zB,EAAO2D,cAAUmpB,EAAiDrmB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAAjC6tB,IAAiC7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAAjBijB,EAAiBjjB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,MAEjGmtB,GAAa,qBAAsBA,IAAYvqB,KAAGqlB,MAAM1uB,IAAWqJ,KAAGmqB,SAAS7vB,QAK9E4wB,EAASv0B,EAAM0E,MAAM,KAIvByvB,EAAUzK,EAGVuK,2BACAE,EAAU,CAENG,QAAAA,EAEA5K,QAAAA,IAKR6K,EAAO9xB,QAAQ,SAAAiJ,GACPlJ,GAAQA,EAAKgyB,gBAAkB1H,GAE/BtqB,EAAKgyB,eAAepxB,KAAK,CAAEwwB,QAAAA,EAASloB,KAAAA,EAAM/H,SAAAA,EAAUwwB,QAAAA,IAGxDP,EAAQ9G,EAAS,mBAAqB,uBAAuBphB,EAAM/H,EAAUwwB,MAKrF,SAAgBM,GAAGb,OAASW,EAAwD9tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAA/C,GAAI9C,EAA2C8C,UAAA3D,OAAA,EAAA2D,UAAA,QAAAnG,EAAjCg0B,IAAiC7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAAjBijB,EAAiBjjB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAChF4tB,eAAe3zB,KAAKC,KAAMizB,EAASW,EAAQ5wB,GAAU,EAAM2wB,EAAS5K,GAIxE,SAAgBgL,IAAId,OAASW,EAAwD9tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAA/C,GAAI9C,EAA2C8C,UAAA3D,OAAA,EAAA2D,UAAA,QAAAnG,EAAjCg0B,IAAiC7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAAjBijB,EAAiBjjB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GACjF4tB,eAAe3zB,KAAKC,KAAMizB,EAASW,EAAQ5wB,GAAU,EAAO2wB,EAAS5K,GAIzE,SAAgBiL,KAAKf,cAASW,EAAwD9tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAA/C,GAAI9C,EAA2C8C,UAAA3D,OAAA,EAAA2D,UAAA,QAAAnG,EAAjCg0B,IAAiC7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAAjBijB,EAAiBjjB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAMlF4tB,eAAe3zB,KAAKC,KAAMizB,EAASW,EALd,SAAfK,IACFF,IAAId,EAASW,EAAQK,EAAcN,EAAS5K,8BADvBK,EAAS,IAAAlc,MAAAgnB,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAT/K,EAAS+K,GAAAruB,UAAAquB,GAE9BnxB,EAAS6C,MAAMuuB,EAAMhL,KAGgC,EAAMuK,EAAS5K,GAI5E,SAAgBsL,aAAapB,OAASloB,EAAyCjF,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAlC,GAAIrG,EAA8BqG,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAAbpG,EAAaoG,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,MAElE4C,KAAGuqB,QAAQA,KAAYvqB,KAAGqlB,MAAMhjB,QAK/B1L,EAAQ,IAAIN,YAAYgM,EAAM,CAChCtL,QAAAA,EACAC,OAAQO,OAAO+hB,OAAO,GAAItiB,EAAQ,CAC9B40B,KAAMt0B,SAKdizB,EAAQsB,cAAcl1B,IAI1B,SAAgBm1B,kBACRx0B,MAAQA,KAAK6zB,sBACRA,eAAe/xB,QAAQ,SAAA2yB,OAChBxB,EAAqCwB,EAArCxB,QAASloB,EAA4B0pB,EAA5B1pB,KAAM/H,EAAsByxB,EAAtBzxB,SAAUwwB,EAAYiB,EAAZjB,QACjCP,EAAQQ,oBAAoB1oB,EAAM/H,EAAUwwB,UAG3CK,eAAiB,IAK9B,SAAgBa,0BACL,IAAItJ,QAAQ,SAAAY,UACf2I,EAAKD,MAAQ5J,WAAWkB,EAAS,GAAK8H,GAAG/zB,KAAK40B,EAAMA,EAAKC,SAASC,UAAW,QAAS7I,KACxFE,KAAK,cC9GJ,SAAS4I,KAAKF,EAAUnR,OAErBsR,EAAUH,EAASzyB,OAASyyB,EAAW,CAACA,GAI9C1nB,MAAM8B,KAAK+lB,GACNC,UACAlzB,QAAQ,SAACmxB,EAASplB,OACTonB,EAAQpnB,EAAQ,EAAI4V,EAAQyR,WAAU,GAAQzR,EAG9CiI,EAASuH,EAAQkC,WACjBC,EAAUnC,EAAQoC,YAIxBJ,EAAMhwB,YAAYguB,GAKdmC,EACA1J,EAAO4J,aAAaL,EAAOG,GAE3B1J,EAAOzmB,YAAYgwB,KAMnC,SAAgBM,cAActC,EAASnvB,GAC9B4E,KAAGuqB,QAAQA,KAAYvqB,KAAGqlB,MAAMjqB,IAMrC7D,OAAOiD,QAAQY,GACV0xB,OAAO,SAAAC,OAAI10B,sBAAJ,UAAgB2H,KAAGiqB,gBAAgB5xB,KAC1Ce,QAAQ,SAAA4zB,6BAAErzB,EAAFszB,EAAA,GAAO50B,EAAP40B,EAAA,UAAkB1C,EAAQ2C,aAAavzB,EAAKtB,KAI7D,SAAgBgE,cAAcgG,EAAMjH,EAAY+xB,OAEtC5C,EAAUrzB,SAASmF,cAAcgG,UAGnCrC,KAAGoB,OAAOhG,IACVyxB,cAActC,EAASnvB,GAIvB4E,KAAG+L,OAAOohB,KACV5C,EAAQ6C,UAAYD,GAIjB5C,EAIX,SAAgB8C,YAAY9C,EAASrnB,GAC5BlD,KAAGuqB,QAAQA,IAAavqB,KAAGuqB,QAAQrnB,IAIxCA,EAAOupB,WAAWG,aAAarC,EAASrnB,EAAOypB,aAInD,SAAgBW,cAAcjrB,EAAM2gB,EAAQ5nB,EAAY+xB,GAC/CntB,KAAGuqB,QAAQvH,IAIhBA,EAAOzmB,YAAYF,cAAcgG,EAAMjH,EAAY+xB,IAIvD,SAAgBI,cAAchD,GACtBvqB,KAAGsqB,SAASC,IAAYvqB,KAAGoqB,MAAMG,GACjC/lB,MAAM8B,KAAKikB,GAASnxB,QAAQm0B,eAI3BvtB,KAAGuqB,QAAQA,IAAavqB,KAAGuqB,QAAQA,EAAQkC,aAIhDlC,EAAQkC,WAAWtK,YAAYoI,GAInC,SAAgBiD,aAAajD,MACpBvqB,KAAGuqB,QAAQA,WAIV9wB,EAAW8wB,EAAQkD,WAAnBh0B,OAECA,EAAS,GACZ8wB,EAAQpI,YAAYoI,EAAQmD,WAC5Bj0B,GAAU,EAKlB,SAAgBk0B,eAAeC,EAAUC,UAChC7tB,KAAGuqB,QAAQsD,IAAc7tB,KAAGuqB,QAAQsD,EAASpB,aAAgBzsB,KAAGuqB,QAAQqD,IAI7EC,EAASpB,WAAWqB,aAAaF,EAAUC,GAEpCD,GALI,KASf,SAAgBG,0BAA0BC,EAAKC,OAMtCjuB,KAAG+L,OAAOiiB,IAAQhuB,KAAGqlB,MAAM2I,SACrB,OAGL5yB,EAAa,GACb8yB,EAAWD,SAEjBD,EAAI3yB,MAAM,KAAKjC,QAAQ,SAAA+e,OAEbgW,EAAWhW,EAAErM,OACbsiB,EAAYD,EAASz1B,QAAQ,IAAK,IAIlC21B,EAHWF,EAASz1B,QAAQ,SAAU,IAGrB2C,MAAM,KACvB1B,EAAM00B,EAAM,GACZh2B,EAAQg2B,EAAM50B,OAAS,EAAI40B,EAAM,GAAG31B,QAAQ,QAAS,IAAM,UAGnDy1B,EAAS/V,OAAO,QAGrB,IAEGpY,KAAGoB,OAAO8sB,IAAaluB,KAAG+L,OAAOmiB,EAASI,SAC1CJ,EAASI,OAAT,IAAA3sB,OAAsBysB,IAG1BhzB,EAAWkzB,MAAQF,YAGlB,IAEDhzB,EAAWmG,GAAK4sB,EAASz1B,QAAQ,IAAK,cAGrC,IAED0C,EAAWzB,GAAOtB,KASvB+C,EAIX,SAAgBmzB,aAAahE,EAASiE,MAC7BxuB,KAAGuqB,QAAQA,QAIZroB,EAAOssB,EAENxuB,KAAGkqB,QAAQhoB,KACZA,GAAQqoB,EAAQiE,QAGhBtsB,EACAqoB,EAAQ2C,aAAa,SAAU,IAE/B3C,EAAQkE,gBAAgB,WAKhC,SAAgBC,YAAYnE,EAAS6D,EAAWO,MACxC3uB,KAAGsqB,SAASC,UACL/lB,MAAM8B,KAAKikB,GAASqE,IAAI,SAAAl4B,UAAKg4B,YAAYh4B,EAAG03B,EAAWO,QAG9D3uB,KAAGuqB,QAAQA,GAAU,KACjBrtB,EAAS,qBACQ,IAAVyxB,IACPzxB,EAASyxB,EAAQ,MAAQ,UAG7BpE,EAAQsE,UAAU3xB,GAAQkxB,GACnB7D,EAAQsE,UAAUC,SAASV,UAG/B,EAIX,SAAgBW,SAASxE,EAAS6D,UACvBpuB,KAAGuqB,QAAQA,IAAYA,EAAQsE,UAAUC,SAASV,GAI7D,SAAgBY,QAAQzE,EAAS4D,4BAIlB3pB,MAAM8B,KAAKpP,SAAS+3B,iBAAiBd,IAAW3e,SAASlY,OAUrDD,KAAKkzB,EAAS4D,GAIjC,SAAgBe,YAAYf,UACjB72B,KAAK40B,SAASC,UAAU8C,iBAAiBd,GAIpD,SAAgBgB,WAAWhB,UAChB72B,KAAK40B,SAASC,UAAUiD,cAAcjB,GAIjD,SAAgBkB,gBAAU9E,EAAgCntB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAtB,KAAMqmB,EAAgBrmB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,MACjD4C,KAAGuqB,QAAQA,QAIV+E,EAAYJ,YAAY73B,KAAKC,KAAM,2DACnC8W,EAAQkhB,EAAU,GAClBzM,EAAOyM,EAAUA,EAAU71B,OAAS,GAsB1CuxB,eAAe3zB,KAAKC,KAAMA,KAAK40B,SAASC,UAAW,UApBtC,SAAAx1B,MAES,QAAdA,EAAMgD,KAAmC,IAAlBhD,EAAM44B,aAK3BC,EAAUt4B,SAASu4B,cAErBD,IAAY3M,GAASlsB,EAAM+4B,SAIpBF,IAAYphB,GAASzX,EAAM+4B,WAElC7M,EAAK8M,QACLh5B,EAAMJ,mBALN6X,EAAMuhB,QACNh5B,EAAMJ,oBAQsDktB,GAAQ,IAIhF,SAAgBmM,eAASrF,EAAkCntB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAxB,KAAMyyB,EAAkBzyB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAClD4C,KAAGuqB,QAAQA,KAKhBA,EAAQoF,MAAM,CAAEG,eAAe,IAG3BD,GACAnB,YAAYnE,EAASjzB,KAAKy4B,OAAOC,WAAWH,WCpS7C,IAAMI,mBAAsB,eACzB1F,EAAUrzB,SAASmF,cAAc,QAEjC6uB,EAAS,CACXgF,iBAAkB,sBAClBC,cAAe,gBACfC,YAAa,gCACbC,WAAY,iBAGVhuB,EAAO9K,OAAOkD,KAAKywB,GAAQ/hB,KAAK,SAAAxS,eAAkCM,IAAzBszB,EAAQ3d,MAAMjW,aAEtDqJ,KAAG+L,OAAO1J,IAAQ6oB,EAAO7oB,GAZD,GAgBnC,SAAgBiuB,QAAQ/F,GACpBnI,WAAW,eAEHmM,aAAahE,GAAS,GACtBA,EAAQgG,aACRhC,aAAahE,GAAS,GACxB,MAAO7zB,MAGV,GC3BP,IAAM85B,QAAU,CACZC,OAAgCv5B,SAASw5B,aACzCC,OAAQx6B,OAAOitB,UAAUuB,UAAUnV,SAAS,QAC5CohB,SAAU,qBAAsB15B,SAASqV,gBAAgBK,QAAU,OAAO/P,KAAKumB,UAAUuB,WACzFkM,SAAU,kBAAkBh0B,KAAKumB,UAAU0N,UAC3CC,MAAO,uBAAuBl0B,KAAKumB,UAAU0N,WCA3CE,cAAgB,aACL,qBACA,iBACC,0BACD,qCACA,UAIXC,QAAU,CAEZC,MAAO,gBAAiBh6B,SAASmF,cAAc,SAC/C80B,MAAO,gBAAiBj6B,SAASmF,cAAc,SAI/CsN,MAPY,SAONtH,EAAM+uB,EAAUC,OACZC,EAAgBd,QAAQK,UAAYQ,GAAeJ,QAAQI,YAC3DE,EAAMN,QAAQ5uB,IAAsB,UAAb+uB,QAGtB,CACHG,IAAAA,EACAC,GAJOD,GAAON,QAAQQ,aAAwB,UAATpvB,IAAqBmuB,QAAQK,UAAYS,KAUtFI,MACQlB,QAAQK,WAMR7wB,KAAGmqB,SAAS9tB,cAAc,SAASs1B,8BAMnCz6B,SAAS06B,yBAA4Bv1B,cAAc,SAASw1B,0BASpEC,QAAS9xB,KAAGmqB,SAASh0B,OAAO47B,uCAI5BV,YAAa,gBAAiBn6B,SAASmF,cAAc,SAKrD21B,KAnDY,SAmDPzJ,MACGvoB,KAAGqlB,MAAMkD,UACF,MAGJ0J,iBAAa1J,EAAMltB,MAAM,QALxB,GAMJgH,EAAOkmB,MAGNjxB,KAAK46B,SAAWD,IAAc36B,KAAK+K,YAC7B,EAIP9K,OAAOkD,KAAKu2B,eAAexhB,SAASnN,KACpCA,GAAI,aAAAV,OAAiBqvB,cAAczI,GAA/B,iBAIGE,QAAQpmB,GAAQ/K,KAAK66B,MAAMC,YAAY/vB,GAAM3J,QAAQ,KAAM,KACpE,MAAOhC,UACE,IAKf27B,WAAY,eAAgBn7B,SAASmF,cAAc,SAGnDo1B,WAAa,eACHa,EAAQp7B,SAASmF,cAAc,gBACrCi2B,EAAMjwB,KAAO,QACS,UAAfiwB,EAAMjwB,KAHJ,GAQbkwB,MAAO,iBAAkBr7B,SAASqV,gBAGlCimB,aAAoC,IAAvBvC,mBAIbwC,cAAe,eAAgBt8B,QAAUA,OAAOu8B,WAAW,4BAA4B1D,SCzGrF2D,MAAQ,CACVC,WADU,6BAEDt7B,KAAK46B,QAIM1tB,MAAM8B,KAAKhP,KAAK66B,MAAMlD,iBAAiB,WAGxCnC,OAAO,SAAAxqB,OACZD,EAAOC,EAAOuwB,aAAa,gBAE7B7yB,KAAGqlB,MAAMhjB,IAIN4uB,QAAQe,KAAK36B,KAAK8B,EAAMkJ,KAbxB,IAkBfywB,kBArBU,kBAuBCH,MAAMC,WACRv7B,KAAKC,MACLs3B,IAAI,SAAAtsB,UAAUsmB,OAAOtmB,EAAOuwB,aAAa,WACzC/F,OAAOrE,UAGhBsK,OA7BU,cA8BDz7B,KAAK46B,aAIJc,EAAS17B,KAGfC,OAAOC,eAAew7B,EAAOb,MAAO,UAAW,CAC3C16B,IAD2C,eAIjC6K,EADUqwB,MAAMC,WAAWv7B,KAAK27B,GACf7pB,KAAK,SAAA7G,UAAUA,EAAOuwB,aAAa,SAAWG,EAAO1wB,gBAGrEA,GAAUsmB,OAAOtmB,EAAOuwB,aAAa,UAEhDx4B,IAT2C,SASvCkuB,OAKMjmB,EAHUqwB,MAAMC,WAAWv7B,KAAK27B,GAGf7pB,KAAK,SAAA7G,UAAUsmB,OAAOtmB,EAAOuwB,aAAa,WAAatK,OAGzEjmB,SAKgD0wB,EAAOb,MAApDc,EAbDC,EAaCD,YAAaE,EAbdD,EAacC,OAAQC,EAbtBF,EAasBE,QAASC,EAb/BH,EAa+BG,WAGtCL,EAAOb,MAAMrlB,IAAMxK,EAAOuwB,aAAa,QAGvB,SAAZO,GAAsBC,KAEtBL,EAAO1H,KAAK,iBAAkB,WAC1B0H,EAAOC,YAAcA,EAGhBE,GACDH,EAAOM,SAKfN,EAAOb,MAAMoB,QAIjB5H,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,iBAAiB,EAAO,CAC5DqB,QAASjL,UAQzBkL,eA1FU,WA2FDn8B,KAAK46B,UAKV3E,cAAcoF,MAAMC,WAAWv7B,KAAKC,YAK/B66B,MAAMjF,aAAa,MAAO51B,KAAKy4B,OAAO2D,iBAKtCvB,MAAMoB,YAGNI,MAAMC,IAAI,iCC/GvB,SAAgBC,OAAOzJ,UACdpqB,KAAGoqB,MAAMA,GAIPA,EAAM0C,OAAO,SAACf,EAAM5mB,UAAUilB,EAAM5tB,QAAQuvB,KAAU5mB,IAHlDilB,EAOf,SAAgB0J,QAAQ1J,EAAO/xB,UACtB2H,KAAGoqB,MAAMA,IAAWA,EAAM3wB,OAIxB2wB,EAAM2J,OAAO,SAACC,EAAMC,UAAU90B,KAAK+0B,IAAID,EAAO57B,GAAS8G,KAAK+0B,IAAIF,EAAO37B,GAAS47B,EAAOD,IAHnF,KCXR,SAASG,UAAU/yB,UACfgzB,KAAKC,MAAMD,KAAKE,UAAUlzB,IAIrC,SAAgBmzB,QAAQnzB,EAAQozB,UACrBA,EAAKn5B,MAAM,KAAK04B,OAAO,SAACU,EAAK96B,UAAQ86B,GAAOA,EAAI96B,IAAMyH,GAIjE,SAAgB2xB,iBAAO7vB,EAAyB9F,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAhB,sBAAOs3B,EAAS,IAAAlwB,MAAAgnB,EAAA,EAAAA,EAAA,EAAA,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAATiJ,EAASjJ,EAAA,GAAAruB,UAAAquB,OACvCiJ,EAAQj7B,cACFyJ,MAGLZ,EAASoyB,EAAQp8B,eAElB0H,KAAGoB,OAAOkB,IAIf/K,OAAOkD,KAAK6H,GAAQlJ,QAAQ,SAAAO,GACpBqG,KAAGoB,OAAOkB,EAAO3I,KACZpC,OAAOkD,KAAKyI,GAAQsM,SAAS7V,IAC9BpC,OAAO+hB,OAAOpW,EAAdyxB,gBAAA,GAAyBh7B,EAAM,KAGnCo5B,OAAO7vB,EAAOvJ,GAAM2I,EAAO3I,KAE3BpC,OAAO+hB,OAAOpW,EAAdyxB,gBAAA,GAAyBh7B,EAAM2I,EAAO3I,OAIvCo5B,OAAM51B,WAAN,EAAA,CAAO+F,GAAPvB,OAAkB+yB,KAfdxxB,ECvBf,IAAIzC,KAAKV,UAAwBW,EAC7B4M,OAAOnN,YAA0BO,EAGjCk0B,QAAUh9B,QAAO4T,OACjBmC,OAAOinB,QACP/6B,QAAQ+6B,QAAQl9B,UAChBgZ,IAAM,KACNC,IAAM,KAENkkB,YAAc,IAAID,QAAQlkB,OAASA,IAEvC,GAAItQ,gBAA+By0B,aAAernB,OAAoB,WAGpE,OAFAmD,IAAI9C,KAAkB,WAAY,EAE3B+mB,QAAQlkB,MAAQA,KAAOkkB,QAAQjkB,MAAQA,KAA4B,QAArBikB,QAAQlkB,IAAK,QAC/D,CACHkkB,QAAU,SAAgBrW,EAAG7d,GAC3B,IAAIo0B,EAAOx9B,gBAAgBs9B,QACvBG,EAAO7lB,UAASqP,GAChByW,OAAY/9B,IAANyJ,EACV,OAAQo0B,GAAQC,GAAQxW,EAAE3W,cAAgBgtB,SAAWI,EAAMzW,EACvD5P,mBAAkBkmB,YAChB,IAAIlnB,OAAKonB,IAASC,EAAMzW,EAAEjc,OAASic,EAAG7d,GACtCiN,QAAMonB,EAAOxW,aAAaqW,SAAWrW,EAAEjc,OAASic,EAAGwW,GAAQC,EAAM9hB,OAAO7b,KAAKknB,GAAK7d,GACpFo0B,EAAOx9B,KAAOuC,QAAO+6B,UAS3B,IAPA,IAAIK,MAAQ,SAAUt7B,GACpBA,KAAOi7B,SAAWn0B,KAAGm0B,QAASj7B,EAAK,CACjCuB,cAAc,EACdzD,IAAK,WAAc,OAAOkW,OAAKhU,IAC/BU,IAAK,SAAUsE,GAAMgP,OAAKhU,GAAOgF,MAG5BlE,OAAO6S,OAAKK,QAAOnU,IAAI,EAAGiB,OAAKhB,OAASD,KAAIy7B,MAAMx6B,OAAKjB,QAChEK,QAAM+N,YAAcgtB,QACpBA,QAAQl9B,UAAYmC,QACpB+U,UAAuBhX,QAAQ,SAAUg9B,SChCpC,SAASM,WAAWC,mBACbA,EAAV,KAAAxzB,OAAoBxC,KAAKyF,MAAsB,IAAhBzF,KAAKsC,WAIxC,SAAgB2zB,OAAO7M,8BAAU7H,EAAM,IAAAlc,MAAAgnB,EAAA,EAAAA,EAAA,EAAA,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAN/K,EAAM+K,EAAA,GAAAruB,UAAAquB,UAC/BzrB,KAAGqlB,MAAMkD,GACFA,EAGJA,EAAMzvB,WAAWJ,QAAQ,WAAY,SAACuY,EAAOzX,UAAMknB,EAAKlnB,GAAGV,aAItE,SAAgBu8B,cAAcC,EAASrrB,UACnB,IAAZqrB,GAAyB,IAARrrB,GAAa2e,OAAO9jB,MAAMwwB,IAAY1M,OAAO9jB,MAAMmF,GAC7D,GAGFqrB,EAAUrrB,EAAO,KAAKsrB,QAAQ,GAI3C,SAAgBC,iBAAWjN,EAAqCnrB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAA7B,GAAI+L,EAAyB/L,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAlB,GAAI1E,EAAc0E,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,UACjDmrB,EAAM7vB,QACT,IAAI8S,OAAOrC,EAAKrQ,WAAWJ,QAAQ,6BAA6B,QAAS,KACzEA,EAAQI,YAKhB,SAAgB28B,qBAAwBr4B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,IACnBtE,WAAWJ,QAAQ,SAAU,SAAAy0B,UAAQA,EAAK/U,OAAO,GAAGsd,cAAgBvI,EAAKwI,OAAO,GAAGC,gBAIpG,SAAgBC,mBACR9pB,GADiC3O,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,IACdtE,kBAGnBiT,EAASypB,WAAWzpB,EAAQ,IAAK,KAGjCA,EAASypB,WAAWzpB,EAAQ,IAAK,KAM1BypB,WAHPzpB,EAAS0pB,YAAY1pB,GAGK,IAAK,IAInC,SAAgB+pB,kBACR/pB,GADgC3O,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,IACbtE,kBAGnBiT,EAAS8pB,aAAa9pB,IAGRqM,OAAO,GAAGwd,cAAgB7pB,EAAO5R,MAAM,GAIzD,SAAgB47B,UAAUzzB,OAChB0zB,EAAW9+B,SAAS++B,yBACpB1L,EAAUrzB,SAASmF,cAAc,cACvC25B,EAASz5B,YAAYguB,GACrBA,EAAQ2L,UAAY5zB,EACb0zB,EAASG,WAAW/I,UAI/B,SAAgBgJ,QAAQ7L,OACdxP,EAAU7jB,SAASmF,cAAc,cACvC0e,EAAQxe,YAAYguB,GACbxP,EAAQmb,UDzCnBpnB,YAA0B,UEjC1B,IAAMunB,UAAY,CACd3E,IAAK,MACLI,QAAS,UACTa,MAAO,QACP2D,MAAO,QACPC,QAAS,WAGPC,KAAO,CACT/+B,IADS,eACLkC,EAAuByD,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAjB,GAAI2yB,EAAa3yB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,MACf4C,KAAGqlB,MAAM1rB,IAAQqG,KAAGqlB,MAAM0K,SACnB,OAGPhkB,EAASwoB,QAAQxE,EAAOyG,KAAM78B,MAE9BqG,KAAGqlB,MAAMtZ,UACLxU,OAAOkD,KAAK47B,WAAW7mB,SAAS7V,GACzB08B,UAAU18B,GAGd,OAGLjB,EAAU,cACEq3B,EAAO0G,mBACV1G,EAAO2G,cAGtBn/B,OAAOiD,QAAQ9B,GAASU,QAAQ,SAAA2zB,6BAAEpzB,EAAgBg9B,EAAA,GAAXt+B,EAAWs+B,EAAA,GAC9C5qB,EAASypB,WAAWzpB,EAAQpS,EAAKtB,KAG9B0T,ICnCT6qB,8BACU5D,gCACH6D,QAAU7D,EAAOjD,OAAO+G,QAAQD,aAChCl9B,IAAMq5B,EAAOjD,OAAO+G,QAAQn9B,qDAuBjCA,OACKi9B,EAAQ/L,YAAcvzB,KAAKu/B,eACrB,SAGL5yB,EAAQ9N,OAAO4gC,aAAaC,QAAQ1/B,KAAKqC,QAE3CqG,KAAGqlB,MAAMphB,UACF,SAGLgzB,EAAO7C,KAAKC,MAAMpwB,UAEjBjE,KAAG+L,OAAOpS,IAAQA,EAAIF,OAASw9B,EAAKt9B,GAAOs9B,8BAGlD71B,MAEKw1B,EAAQ/L,WAAcvzB,KAAKu/B,SAK3B72B,KAAGoB,OAAOA,QAKX01B,EAAUx/B,KAAKG,MAGfuI,KAAGqlB,MAAMyR,KACTA,EAAU,IAId/D,OAAO+D,EAAS11B,GAGhBjL,OAAO4gC,aAAaG,QAAQ5/B,KAAKqC,IAAKy6B,KAAKE,UAAUwC,kDAxD3C,iBAAkB3gC,eACb,SAOXA,OAAO4gC,aAAaG,QAJP,UAAA,WAKb/gC,OAAO4gC,aAAaI,WALP,YAON,EACT,MAAOzgC,UACE,YCxBnB,SAAwB0gC,MAAMt7B,OAAKu7B,EAAuBj6B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAR,cACvC,IAAIslB,QAAQ,SAACY,EAASU,WAEfsT,EAAU,IAAIC,oBAGd,oBAAqBD,UAI3BA,EAAQvV,iBAAiB,OAAQ,cACR,SAAjBsV,MAEI/T,EAAQ8Q,KAAKC,MAAMiD,EAAQE,eAC7B,MAAO9gC,GACL4sB,EAAQgU,EAAQE,mBAGpBlU,EAAQgU,EAAQG,YAIxBH,EAAQvV,iBAAiB,QAAS,iBACxB,IAAItrB,MAAM6gC,EAAQI,UAG5BJ,EAAQtqB,KAAK,MAAOlR,GAAK,GAGzBw7B,EAAQD,aAAeA,EAEvBC,EAAQK,OACV,MAAOjhC,GACLstB,EAAOttB,MC7BnB,SAAwBkhC,WAAW97B,EAAKyF,MAC/BvB,KAAG+L,OAAOjQ,QAKT+7B,EAAQ73B,KAAG+L,OAAOxK,GAGlBu2B,EAAS,kBAAsC,OAAhC5gC,SAAS6gC,eAAex2B,IAEvCy2B,EAAS,SAAC7L,EAAW/Q,GACvB+Q,EAAU+J,UAAY9a,EAGlByc,GAASC,KAKb5gC,SAASyF,KAAKs7B,sBAAsB,aAAc9L,QAIjD0L,IAAUC,IAAU,KACfI,EAAatB,QAAQ/L,UAGrBsB,EAAYj1B,SAASmF,cAAc,UACzC8vB,EAAUe,aAAa,SAAU,IAE7B2K,GACA1L,EAAUe,aAAa,KAAM3rB,GAI7B22B,EAAY,KACNC,EAAShiC,OAAO4gC,aAAaC,QAApB,GAAAr1B,OAhCR,QAgCQ,KAAAA,OAAyCJ,OAClC,OAAX42B,EAEG,KACJ/c,EAAOgZ,KAAKC,MAAM8D,GACxBH,EAAO7L,EAAW/Q,EAAKgd,UAK/BhB,MAAMt7B,GACD0nB,KAAK,SAAAhd,GACExG,KAAGqlB,MAAM7e,KAIT0xB,GACA/hC,OAAO4gC,aAAaG,QAApB,GAAAv1B,OAjDD,QAiDC,KAAAA,OACiBJ,GACb6yB,KAAKE,UAAU,CACX8D,QAAS5xB,KAKrBwxB,EAAO7L,EAAW3lB,MAErBihB,MAAM,gBCtEnBrlB,QAAQA,QAAQ9B,EAAG,OAAQ,CACzB+3B,MAAO,SAAe15B,GACpB,OAAQA,EAAK,EAAIQ,KAAKyF,MAAQzF,KAAKwF,MAAMhG,MCEtC,IAAM25B,SAAW,SAAAjgC,UAAS8G,KAAKk5B,MAAOhgC,EAAQ,GAAK,GAAM,GAAI,KACvDkgC,WAAa,SAAAlgC,UAAS8G,KAAKk5B,MAAOhgC,EAAQ,GAAM,GAAI,KACpDmgC,WAAa,SAAAngC,UAAS8G,KAAKk5B,MAAMhgC,EAAQ,GAAI,KAG1D,SAAgBogC,iBAAWC,EAAkDt7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAA3C,EAAGu7B,EAAwCv7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAAlBw7B,EAAkBx7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,OAEpE4C,KAAGsoB,OAAOoQ,UACJD,WAAW,KAAME,EAAcC,OAIpCxD,EAAS,SAAA/8B,SAAS,IAAAsJ,OAAItJ,GAAQ8B,OAAO,IAGvC0+B,EAAQP,SAASI,GACfI,EAAOP,WAAWG,GAClBK,EAAOP,WAAWE,UAIpBG,EADAF,GAAgBE,EAAQ,EACnB,GAAAl3B,OAAMk3B,EAAN,KAEG,aAIFD,GAAYF,EAAO,EAAI,IAAM,IAAvC/2B,OAA4Ck3B,GAA5Cl3B,OAAoDyzB,EAAO0D,GAA3D,KAAAn3B,OAAoEyzB,EAAO2D,ICA/E,IAAMC,SAAW,CAEbC,WAFa,eAIHC,EADM,IAAI19B,IAAIlE,KAAKy4B,OAAOoJ,QAAShjC,OAAO+F,UAC/Bk9B,OAASjjC,OAAO+F,SAASk9B,MAAS5I,QAAQC,OAASt6B,OAAOkjC,oBAEpE,CACHv9B,IAAKxE,KAAKy4B,OAAOoJ,QACjBD,KAAAA,IAKRI,aAba,2BAeApN,SAAS8M,SAAW7J,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUP,SAASje,cAGzEmR,SAASsN,QAAU,CACpBlG,KAAMpE,YAAY73B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQlG,MAC3DmG,MAAOtK,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQC,OAC3DC,QAASvK,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQE,SAC7DC,OAAQxK,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQG,QAC5DC,YAAazK,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQI,aACjEC,KAAM1K,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQK,MAC1DnI,IAAKvC,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQ9H,KACzDI,QAAS3C,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQ1H,SAC7DgI,SAAU3K,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQM,UAC9DC,SAAU5K,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQO,UAC9DC,WAAY7K,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUC,QAAQQ,kBAI/D9N,SAAS+N,SAAW9K,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUU,eAGhE/N,SAASgO,OAAS,CACnBC,KAAMhL,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUW,OAAOC,MACzDC,OAAQjL,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAUW,OAAOE,cAI1DlO,SAASrf,QAAU,CACpBwtB,OAAQlL,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAU1sB,QAAQwtB,QAC5DpH,YAAa9D,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAU1sB,QAAQomB,aACjEqH,SAAUnL,WAAW93B,KAAKC,KAAMA,KAAKy4B,OAAOwJ,UAAU1sB,QAAQytB,WAI9Dt6B,KAAGuqB,QAAQjzB,KAAK40B,SAAS+N,iBACpB/N,SAASrf,QAAQ0tB,YAAcjjC,KAAK40B,SAAS+N,SAAS7K,cAAvB,IAAAztB,OAC5BrK,KAAKy4B,OAAOC,WAAWwK,YAI5B,EACT,MAAOxiC,eAEA27B,MAAM8G,KAAK,kEAAmEziC,QAG9E0iC,sBAAqB,IAEnB,IAKfC,WApEa,SAoEFt4B,EAAMjH,OAEP+9B,EAAUH,SAASC,WAAW5hC,KAAKC,MACnCsjC,EAAQ,GAAAj5B,OAAOw3B,EAAQD,KAAqB,GAAdC,EAAQr9B,IAA9B,KAAA6F,OAA0CrK,KAAKy4B,OAAO8K,YAG9DC,EAAO5jC,SAAS6jC,gBALJ,6BAK+B,OACjDlO,cACIiO,EACA/H,OAAO33B,EAAY,CACf4/B,KAAM,eACN1L,UAAW,eAKb2L,EAAM/jC,SAAS6jC,gBAfH,6BAe8B,OAC1CvG,EAAI,GAAA7yB,OAAMi5B,EAAN,KAAAj5B,OAAkBU,SAKxB,SAAU44B,GACVA,EAAIC,eAAe,+BAAgC,OAAQ1G,GAI/DyG,EAAIC,eAAe,+BAAgC,aAAc1G,GAGjEsG,EAAKv+B,YAAY0+B,GAEVH,GAIXK,YAxGa,SAwGDxhC,OAAKyhC,EAAWh+B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,GACd+vB,EAAOqJ,KAAK/+B,IAAIkC,EAAKrC,KAAKy4B,eAMzB1zB,cAAc,OAJF9E,OAAO+hB,OAAO,GAAI8hB,EAAM,CACvC9M,MAAO,CAAC8M,EAAK9M,MAAOh3B,KAAKy4B,OAAOC,WAAWxB,QAAQ1B,OAAOrE,SAAS7tB,KAAK,OAGnCuyB,IAI7CkO,YAnHa,SAmHDlO,MACJntB,KAAGqlB,MAAM8H,UACF,SAGLmO,EAAQj/B,cAAc,OAAQ,CAChCiyB,MAAOh3B,KAAKy4B,OAAOC,WAAWuL,KAAKljC,eAGvCijC,EAAM/+B,YACFF,cACI,OACA,CACIiyB,MAAOh3B,KAAKy4B,OAAOC,WAAWuL,KAAKD,OAEvCnO,IAIDmO,GAIXE,aA1Ia,SA0IAC,EAAYL,OACfhgC,EAAa7D,OAAO+hB,OAAO,GAAI8hB,GACjC/4B,EAAOyzB,YAAY2F,GAEjBC,EAAQ,CACVnR,QAAS,SACT9G,QAAQ,EACRkY,MAAO,KACPb,KAAM,KACNc,aAAc,KACdC,YAAa,cAGhB,UAAW,OAAQ,SAASziC,QAAQ,SAAAO,GAC7BpC,OAAOkD,KAAKW,GAAYoU,SAAS7V,KACjC+hC,EAAM/hC,GAAOyB,EAAWzB,UACjByB,EAAWzB,MAKJ,WAAlB+hC,EAAMnR,SAAyBhzB,OAAOkD,KAAKW,GAAYoU,SAAS,UAChEpU,EAAWiH,KAAO,UAIlB9K,OAAOkD,KAAKW,GAAYoU,SAAS,SAC5BpU,EAAWkzB,MAAM9e,SAASlY,KAAKy4B,OAAOC,WAAW8L,WAClD1gC,EAAWkzB,OAAX,IAAA3sB,OAAwBrK,KAAKy4B,OAAOC,WAAW8L,UAGnD1gC,EAAWkzB,MAAQh3B,KAAKy4B,OAAOC,WAAW8L,QAItCL,OACC,OACDC,EAAMjY,QAAS,EACfiY,EAAMC,MAAQ,OACdD,EAAME,aAAe,QACrBF,EAAMZ,KAAO,OACbY,EAAMG,YAAc,kBAGnB,OACDH,EAAMjY,QAAS,EACfiY,EAAMC,MAAQ,OACdD,EAAME,aAAe,SACrBF,EAAMZ,KAAO,SACbY,EAAMG,YAAc,kBAGnB,WACDH,EAAMjY,QAAS,EACfiY,EAAMC,MAAQ,iBACdD,EAAME,aAAe,kBACrBF,EAAMZ,KAAO,eACbY,EAAMG,YAAc,wBAGnB,aACDH,EAAMjY,QAAS,EACfiY,EAAMC,MAAQ,kBACdD,EAAME,aAAe,iBACrBF,EAAMZ,KAAO,mBACbY,EAAMG,YAAc,4BAGnB,aACDzgC,EAAWkzB,OAAX,IAAA3sB,OAAwBrK,KAAKy4B,OAAOC,WAAW8L,QAA/C,cACAz5B,EAAO,OACPq5B,EAAMC,MAAQ,OACdD,EAAMZ,KAAO,qBAIT96B,KAAGqlB,MAAMqW,EAAMC,SACfD,EAAMC,MAAQt5B,GAEdrC,KAAGqlB,MAAMqW,EAAMZ,QACfY,EAAMZ,KAAOW,OAInBM,EAAS1/B,cAAcq/B,EAAMnR,gBAG/BmR,EAAMjY,QAENsY,EAAOx/B,YACHy8B,SAAS2B,WAAWtjC,KAAKC,KAAMokC,EAAMG,YAAa,CAC9CvN,MAAO,mBAGfyN,EAAOx/B,YACHy8B,SAAS2B,WAAWtjC,KAAKC,KAAMokC,EAAMZ,KAAM,CACvCxM,MAAO,uBAKfyN,EAAOx/B,YACHy8B,SAASmC,YAAY9jC,KAAKC,KAAMokC,EAAME,aAAc,CAChDtN,MAAO,oBAGfyN,EAAOx/B,YACHy8B,SAASmC,YAAY9jC,KAAKC,KAAMokC,EAAMC,MAAO,CACzCrN,MAAO,0BAIfyN,EAAOx/B,YAAYy8B,SAAS2B,WAAWtjC,KAAKC,KAAMokC,EAAMZ,OACxDiB,EAAOx/B,YAAYy8B,SAASmC,YAAY9jC,KAAKC,KAAMokC,EAAMC,SAI7D5I,OAAO33B,EAAY2yB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUC,QAAQn3B,GAAOjH,IAClFyxB,cAAckP,EAAQ3gC,GAGT,SAATiH,GACKrC,KAAGoqB,MAAM9yB,KAAK40B,SAASsN,QAAQn3B,WAC3B6pB,SAASsN,QAAQn3B,GAAQ,SAG7B6pB,SAASsN,QAAQn3B,GAAMtI,KAAKgiC,SAE5B7P,SAASsN,QAAQn3B,GAAQ05B,EAG3BA,GAIXC,YAjRa,SAiRD35B,EAAMjH,OAERmtB,EAAQlsB,cACV,QACA02B,OACIhF,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUW,OAAO73B,IACvD,CACIA,KAAM,QACN0C,IAAK,EACLkF,IAAK,IACLxD,KAAM,IACNpO,MAAO,EACP4jC,aAAc,MAEdjB,KAAM,sBACQxE,KAAK/+B,IAAI4K,EAAM/K,KAAKy4B,wBACjB,kBACA,oBACA,GAErB30B,gBAIH8wB,SAASgO,OAAO73B,GAAQkmB,EAG7ByQ,SAASkD,gBAAgB7kC,KAAKC,KAAMixB,GAE7BA,GAIX4T,eAlTa,SAkTE95B,EAAMjH,OACX6+B,EAAW59B,cACb,WACA02B,OACIhF,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAU1sB,QAAQxK,IACxD,CACI0C,IAAK,EACLkF,IAAK,IACL5R,MAAO,EACP2iC,KAAM,8BACS,GAEnB5/B,OAKK,WAATiH,EAAmB,CACnB43B,EAAS19B,YAAYF,cAAc,OAAQ,KAAM,UAE3C+/B,EAAY,CACdC,OAAQ,SACRhC,OAAQ,YACVh4B,GACIi6B,EAASF,EAAY5F,KAAK/+B,IAAI2kC,EAAW9kC,KAAKy4B,QAAU,GAE9DkK,EAAS7M,UAAT,KAAAzrB,OAA0B26B,EAAO1G,2BAGhC1J,SAASrf,QAAQxK,GAAQ43B,EAEvBA,GAIXsC,WArVa,SAqVFl6B,OACDjH,EAAa2yB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAU1sB,QAAQxK,IAErE8pB,EAAY9vB,cACd,MACA02B,OAAO33B,EAAY,CACfkzB,MAAO,GAAA3sB,OAAGrK,KAAKy4B,OAAOC,WAAWnjB,QAAQ6rB,KAAlC,KAAA/2B,OAA0CvG,EAAWkzB,MAAQlzB,EAAWkzB,MAAQ,IAAKxiB,oBAC9E0qB,KAAK/+B,IAAI4K,EAAM/K,KAAKy4B,UAEtC,qBAIC7D,SAASrf,QAAQxK,GAAQ8pB,EAEvBA,GAMXqQ,sBA1Wa,SA0WSC,EAAUp6B,cAE5B+oB,GACIqR,EACA,gBACA,SAAA9lC,MAES,CAAC,GAAI,GAAI,GAAI,IAAI6Y,SAAS7Y,EAAM+lC,SAKrC/lC,EAAMJ,iBACNI,EAAMgmC,kBAGa,YAAfhmC,EAAM0L,WAUFa,EANF05B,EAAgB5N,QAAQyN,EAAU,8BAGnCG,GAAiB,CAAC,GAAI,IAAIptB,SAAS7Y,EAAM+lC,OAC1C1D,SAAS6D,cAAcxlC,KAAK8B,EAAMkJ,GAAM,QAIpB,KAAhB1L,EAAM+lC,QACc,KAAhB/lC,EAAM+lC,OAAiBE,GAAiC,KAAhBjmC,EAAM+lC,OAC9Cx5B,EAASu5B,EAASK,mBAEb98B,KAAGuqB,QAAQrnB,KACZA,EAASu5B,EAAShQ,WAAWsQ,qBAGjC75B,EAASu5B,EAASO,uBAEbh9B,KAAGuqB,QAAQrnB,KACZA,EAASu5B,EAAShQ,WAAWwQ,mBAIrCrN,SAASv4B,KAAK8B,EAAM+J,GAAQ,OAIxC,GAKJkoB,GAAGqR,EAAU,QAAS,SAAA9lC,GACE,KAAhBA,EAAM+lC,OAIV1D,SAASkE,mBAAmB7lC,KAAK8B,EAAM,MAAM,MAKrDgkC,eAxaa,SAAApQ,cAwaI10B,EAA2D00B,EAA3D10B,MAAO+kC,EAAoDrQ,EAApDqQ,KAAM/6B,EAA8C0qB,EAA9C1qB,KAAMq0B,EAAwC3J,EAAxC2J,UAAO4E,MAAAA,OAAiC,IAAA+B,EAAzB,KAAyBA,MAAnBC,QAAAA,OAAmB,IAAAC,GAAAA,EAClEniC,EAAa2yB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUW,OAAO73B,IAEpEo6B,EAAWpgC,cACb,SACA02B,OAAO33B,EAAY,CACfiH,KAAM,SACN24B,KAAM,gBACN1M,MAAO,GAAA3sB,OAAGrK,KAAKy4B,OAAOC,WAAW8L,QAA1B,KAAAn6B,OAAqCvG,EAAWkzB,MAAQlzB,EAAWkzB,MAAQ,IAAKxiB,sBACvEwxB,EAChBjlC,MAAAA,KAIFmlC,EAAOnhC,cAAc,QAG3BmhC,EAAKtH,UAAYQ,EAEb12B,KAAGuqB,QAAQ+Q,IACXkC,EAAKjhC,YAAY++B,GAGrBmB,EAASlgC,YAAYihC,GAGrBjmC,OAAOC,eAAeilC,EAAU,UAAW,CACvCxhC,YAAY,EACZxD,IAFuC,iBAGc,SAA1CglC,EAAS5J,aAAa,iBAEjCx4B,IALuC,SAKnCijC,GAEIA,GACA94B,MAAM8B,KAAKm2B,EAAShQ,WAAWgR,UAC1B3Q,OAAO,SAAApJ,UAAQsL,QAAQtL,EAAM,4BAC7BtqB,QAAQ,SAAAsqB,UAAQA,EAAKwJ,aAAa,eAAgB,WAG3DuP,EAASvP,aAAa,eAAgBoQ,EAAU,OAAS,iBAI5DI,UAAUC,KACXlB,EACA,cACA,SAAA9lC,OACQqJ,KAAGyqB,cAAc9zB,IAA0B,KAAhBA,EAAM+lC,cAIrC/lC,EAAMJ,iBACNI,EAAMgmC,kBAENF,EAASa,SAAU,EAEXj7B,OACC,WACDqpB,EAAKkS,aAAehV,OAAOvwB,aAG1B,UACDqzB,EAAK8H,QAAUn7B,YAGd,QACDqzB,EAAKmS,MAAQC,WAAWzlC,GAOhC2gC,SAAS6D,cAAcxlC,KAAKq0B,EAAM,OAAQ1rB,KAAGyqB,cAAc9zB,MAE/D0L,GACA,GAGJ22B,SAASwD,sBAAsBnlC,KAAKC,KAAMmlC,EAAUp6B,GAEpD+6B,EAAK7gC,YAAYkgC,IAIrBhE,WA7fa,eA6fFC,EAA4Bt7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAArB,EAAGw7B,EAAkBx7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,UAE9B4C,KAAGsoB,OAAOoQ,GAORD,WAAWC,EAFCJ,SAAShhC,KAAKgjC,UAAY,EAET1B,GANzBF,GAUfqF,kBA1gBa,eA0gBK76B,EAA2C9F,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAlC,KAAMs7B,EAA4Bt7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAArB,EAAGw7B,EAAkBx7B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAEpD4C,KAAGuqB,QAAQrnB,IAAYlD,KAAGsoB,OAAOoQ,KAKtCx1B,EAAOkqB,UAAY4L,SAASP,WAAWC,EAAME,KAIjDoF,aArhBa,WAshBJ1mC,KAAKuzB,UAAU2G,KAKhBxxB,KAAGuqB,QAAQjzB,KAAK40B,SAASgO,OAAOE,SAChCpB,SAASiF,SAAS5mC,KAAKC,KAAMA,KAAK40B,SAASgO,OAAOE,OAAQ9iC,KAAK4mC,MAAQ,EAAI5mC,KAAK8iC,QAIhFp6B,KAAGuqB,QAAQjzB,KAAK40B,SAASsN,QAAQK,aAC5B3N,SAASsN,QAAQK,KAAKsE,QAAU7mC,KAAK4mC,OAAyB,IAAhB5mC,KAAK8iC,UAKhE6D,SAtiBa,SAsiBJ/6B,OAAQ7K,EAAW+E,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAH,EAChB4C,KAAGuqB,QAAQrnB,KAKhBA,EAAO7K,MAAQA,EAGf2gC,SAASkD,gBAAgB7kC,KAAKC,KAAM4L,KAIxCk7B,eAnjBa,SAmjBEznC,iBACNW,KAAKuzB,UAAU2G,IAAOxxB,KAAGrJ,MAAMA,QAIhC0B,EAAQ,KAkBR1B,SACQA,EAAM0L,UAEL,iBACA,cACA,SACDhK,EAAQg9B,cAAc/9B,KAAK27B,YAAa37B,KAAKgjC,UAG1B,eAAf3jC,EAAM0L,MACN22B,SAASiF,SAAS5mC,KAAKC,KAAMA,KAAK40B,SAASgO,OAAOC,KAAM9hC,aAM3D,cACA,YAjCO,SAAC6K,EAAQqlB,OACnBlwB,EAAQ2H,KAAGsoB,OAAOC,GAASA,EAAQ,EACnC0R,EAAWj6B,KAAGuqB,QAAQrnB,GAAUA,EAAS+oB,EAAKC,SAASrf,QAAQwtB,UAGjEr6B,KAAGuqB,QAAQ0P,GAAW,CACtBA,EAAS5hC,MAAQA,MAGXsjC,EAAQ1B,EAASoE,qBAAqB,QAAQ,GAChDr+B,KAAGuqB,QAAQoR,KACXA,EAAMlO,WAAW,GAAG6Q,UAAYjmC,IAuBhCkmC,CAAYjnC,KAAK40B,SAASrf,QAAQwtB,OAAwB,IAAhB/iC,KAAKknC,aAW/DtC,gBAvmBa,SAumBGh5B,OAENovB,EAAQtyB,KAAGrJ,MAAMuM,GAAUA,EAAOA,OAASA,KAG5ClD,KAAGuqB,QAAQ+H,IAAyC,UAA/BA,EAAMO,aAAa,YAKzC7D,QAAQsD,EAAOh7B,KAAKy4B,OAAOwJ,UAAUW,OAAOC,MAAO,CACnD7H,EAAMpF,aAAa,gBAAiB51B,KAAK27B,iBACnCA,EAAc+F,SAASP,WAAWnhC,KAAK27B,aACvCqH,EAAWtB,SAASP,WAAWnhC,KAAKgjC,UACpClF,EAASoB,KAAK/+B,IAAI,YAAaH,KAAKy4B,QAC1CuC,EAAMpF,aACF,iBACAkI,EAAO18B,QAAQ,gBAAiBu6B,GAAav6B,QAAQ,aAAc4hC,SAEpE,GAAItL,QAAQsD,EAAOh7B,KAAKy4B,OAAOwJ,UAAUW,OAAOE,QAAS,KACtDqE,EAAwB,IAAdnM,EAAMj6B,MACtBi6B,EAAMpF,aAAa,gBAAiBuR,GACpCnM,EAAMpF,aAAa,iBAAnB,GAAAvrB,OAAwC88B,EAAQlJ,QAAQ,GAAxD,WAEAjD,EAAMpF,aAAa,gBAAiBoF,EAAMj6B,OAIzCm4B,QAAQI,UAKb0B,EAAM1lB,MAAM8xB,YAAY,UAAxB,GAAA/8B,OAAuC2wB,EAAMj6B,MAAQi6B,EAAMroB,IAAO,IAAlE,QAIJ00B,kBA5oBa,SA4oBKhoC,iBAGTW,KAAKy4B,OAAO6O,SAASzE,MACrBn6B,KAAGuqB,QAAQjzB,KAAK40B,SAASgO,OAAOC,OAChCn6B,KAAGuqB,QAAQjzB,KAAK40B,SAASrf,QAAQ0tB,cAChB,IAAlBjjC,KAAKgjC,cAMLmE,EAAU,EACRI,EAAavnC,KAAK40B,SAAS+N,SAAS6E,wBACpCC,EAAO,GAAAp9B,OAAMrK,KAAKy4B,OAAOC,WAAWwK,QAA7B,aAEP/W,EAAS,SAAAA,GACXiL,YAAYsQ,EAAK9S,SAASrf,QAAQ0tB,YAAawE,EAAStb,OAIxDnsB,KAAKi7B,MACL9O,GAAO,WAKPzjB,KAAGrJ,MAAMA,GACT8nC,EAAW,IAAMI,EAAWI,OAAUtoC,EAAMuoC,MAAQL,EAAWM,UAC5D,CAAA,IAAIpQ,SAASz3B,KAAK40B,SAASrf,QAAQ0tB,YAAawE,UACnDN,EAAUX,WAAWxmC,KAAK40B,SAASrf,QAAQ0tB,YAAY3tB,MAAMuyB,KAAM,IAMnEV,EAAU,EACVA,EAAU,EACHA,EAAU,MACjBA,EAAU,KAIdzF,SAAS+E,kBAAkB1mC,KAAKC,KAAMA,KAAK40B,SAASrf,QAAQ0tB,YAAcjjC,KAAKgjC,SAAW,IAAOmE,QAG5FvS,SAASrf,QAAQ0tB,YAAY3tB,MAAMuyB,KAAxC,GAAAx9B,OAAkD88B,EAAlD,KAIIz+B,KAAGrJ,MAAMA,IAAU,CAAC,aAAc,cAAc6Y,SAAS7Y,EAAM0L,OAC/DohB,EAAsB,eAAf9sB,EAAM0L,SAKrB+8B,WApsBa,SAosBFzoC,OAED0oC,GAAUr/B,KAAGuqB,QAAQjzB,KAAK40B,SAASrf,QAAQytB,WAAahjC,KAAKy4B,OAAOuP,WAG1EtG,SAAS+E,kBAAkB1mC,KACvBC,KACAA,KAAK40B,SAASrf,QAAQomB,YACtBoM,EAAS/nC,KAAKgjC,SAAWhjC,KAAK27B,YAAc37B,KAAK27B,YACjDoM,GAIA1oC,GAAwB,eAAfA,EAAM0L,MAAyB/K,KAAK66B,MAAMoN,SAKvDvG,SAASoF,eAAe/mC,KAAKC,KAAMX,IAIvC6oC,eA1tBa,cA4tBJloC,KAAKuzB,UAAU2G,KAAQl6B,KAAKy4B,OAAOuP,aAAchoC,KAAK27B,iBAQvD37B,KAAKgjC,UAALn7B,KAAAsgC,IAAiB,EAAK,WACtBlR,aAAaj3B,KAAK40B,SAASrf,QAAQomB,aAAa,QAChD1E,aAAaj3B,KAAK40B,SAAS+N,UAAU,GAKrCj6B,KAAGuqB,QAAQjzB,KAAK40B,SAASgO,OAAOC,YAC3BjO,SAASgO,OAAOC,KAAKjN,aAAa,gBAAiB51B,KAAKgjC,cAI3DoF,EAAc1/B,KAAGuqB,QAAQjzB,KAAK40B,SAASrf,QAAQytB,WAGhDoF,GAAepoC,KAAKy4B,OAAO4P,iBAAmBroC,KAAK67B,QACpD6F,SAAS+E,kBAAkB1mC,KAAKC,KAAMA,KAAK40B,SAASrf,QAAQomB,YAAa37B,KAAKgjC,UAI9EoF,GACA1G,SAAS+E,kBAAkB1mC,KAAKC,KAAMA,KAAK40B,SAASrf,QAAQytB,SAAUhjC,KAAKgjC,UAI/EtB,SAAS2F,kBAAkBtnC,KAAKC,QAIpCsoC,iBAjwBa,SAiwBIC,EAASpc,GACtB8K,aAAaj3B,KAAK40B,SAAS4N,SAASN,QAAQqG,IAAWpc,IAI3Dqc,cAtwBa,SAswBCD,EAAS1T,EAAW5D,OACxBwX,EAAOzoC,KAAK40B,SAAS4N,SAASkG,OAAOH,GACvCxnC,EAAQ,KACR+kC,EAAOjR,KAEK,aAAZ0T,EACAxnC,EAAQf,KAAKsmC,iBACV,IACHvlC,EAAS2H,KAAGqlB,MAAMkD,GAAiBjxB,KAAKuoC,GAAbtX,EAGvBvoB,KAAGqlB,MAAMhtB,KACTA,EAAQf,KAAKy4B,OAAO8P,GAASI,UAI5BjgC,KAAGqlB,MAAM/tB,KAAKwzB,QAAQ+U,MAAcvoC,KAAKwzB,QAAQ+U,GAASrwB,SAASnX,oBAC/Ds7B,MAAM8G,KAAX,yBAAA94B,OAAyCtJ,EAAzC,UAAAsJ,OAAuDk+B,QAKtDvoC,KAAKy4B,OAAO8P,GAAS/U,QAAQtb,SAASnX,oBAClCs7B,MAAM8G,KAAX,sBAAA94B,OAAsCtJ,EAAtC,UAAAsJ,OAAoDk+B,OAMvD7/B,KAAGuqB,QAAQ6S,KACZA,EAAO2C,GAAQA,EAAK3Q,cAAc,kBAIjCpvB,KAAGuqB,QAAQ6S,IAKF9lC,KAAK40B,SAAS4N,SAASN,QAAQqG,GAASzQ,cAAxC,IAAAztB,OAA0DrK,KAAKy4B,OAAOC,WAAWuL,KAAKljC,QAC9F69B,UAAY8C,SAASkH,SAAS7oC,KAAKC,KAAMuoC,EAASxnC,OAGlD6K,EAASk6B,GAAQA,EAAKhO,cAAL,WAAAztB,OAA8BtJ,EAA9B,OAEnB2H,KAAGuqB,QAAQrnB,KACXA,EAAOo6B,SAAU,KAKzB4C,SAzzBa,SAyzBJL,EAASxnC,UACNwnC,OACC,eACgB,IAAVxnC,EAAcm+B,KAAK/+B,IAAI,SAAUH,KAAKy4B,QAAtC,GAAApuB,OAAmDtJ,EAAnD,eAEN,aACG2H,KAAGsoB,OAAOjwB,GAAQ,KACZsjC,EAAQnF,KAAK/+B,IAAL,gBAAAkK,OAAyBtJ,GAASf,KAAKy4B,eAEhD4L,EAAMliC,OAIJkiC,YAHOtjC,EAAV,YAMDo9B,YAAYp9B,OAElB,kBACM0hC,SAASmG,SAAS7oC,KAAKC,qBAGvB,OAKnB6oC,eAp1Ba,SAo1BErV,iBAEN9qB,KAAGuqB,QAAQjzB,KAAK40B,SAAS4N,SAASkG,OAAOxM,cAKxC4J,EAAO9lC,KAAK40B,SAAS4N,SAASkG,OAAOxM,QAAQpE,cAAc,iBAG7DpvB,KAAGoqB,MAAMU,UACJA,QAAQ0I,QAAUK,OAAO/I,GAASgC,OAAO,SAAA0G,UAAW4M,EAAKrQ,OAAOyD,QAAQ1I,QAAQtb,SAASgkB,UAI5F/P,GAAUzjB,KAAGqlB,MAAM/tB,KAAKwzB,QAAQ0I,UAAYl8B,KAAKwzB,QAAQ0I,QAAQ/5B,OAAS,KAChFu/B,SAAS4G,iBAAiBvoC,KAAKC,KAVlB,UAU8BmsB,GAG3C+J,aAAa4P,GAGbpE,SAASqH,UAAUhpC,KAAKC,MAGnBmsB,OAKC6c,EAAW,SAAA9M,OACPmI,EAAQnF,KAAK/+B,IAAL,gBAAAkK,OAAyB6xB,GAAW4M,EAAKrQ,eAElD4L,EAAMliC,OAIJu/B,SAASqC,YAAYhkC,KAAK+oC,EAAMzE,GAH5B,WAOV7Q,QAAQ0I,QACR14B,KAAK,SAACC,EAAGC,OACAulC,EAAUH,EAAKrQ,OAAOyD,QAAQ1I,eAC7ByV,EAAQ/jC,QAAQzB,GAAKwlC,EAAQ/jC,QAAQxB,GAAK,GAAK,IAEzD5B,QAAQ,SAAAo6B,GACLwF,SAASmE,eAAe9lC,KAAK+oC,EAAM,CAC/B/nC,MAAOm7B,EACP4J,KAAAA,EACA/6B,KA5CC,UA6CDq0B,MAAOsC,SAASkH,SAAS7oC,KAAK+oC,EAAM,UAAW5M,GAC/C8H,MAAOgF,EAAS9M,OAI5BwF,SAAS8G,cAAczoC,KAAKC,KAlDf,UAkD2B8lC,MAmD5CoD,gBA/7Ba,yBAi8BJxgC,KAAGuqB,QAAQjzB,KAAK40B,SAAS4N,SAASkG,OAAOjG,eAMxCqD,EAAO9lC,KAAK40B,SAAS4N,SAASkG,OAAOjG,SAAS3K,cAAc,iBAC5DqR,EAAS1G,SAAS2G,UAAUrpC,KAAKC,MACjCmsB,EAASgF,QAAQgY,EAAOhnC,WAG9Bu/B,SAAS4G,iBAAiBvoC,KAAKC,KANlB,WAM8BmsB,GAG3C+J,aAAa4P,GAGbpE,SAASqH,UAAUhpC,KAAKC,MAGnBmsB,OAKCqH,EAAU2V,EAAO7R,IAAI,SAACjE,EAAOtyB,SAAW,CAC1CA,MAAAA,EACAilC,QAASqD,EAAK5G,SAAS6G,SAAWD,EAAK/C,eAAiBvlC,EACxDq+B,MAAOqD,SAASmG,SAAS7oC,KAAKspC,EAAMhW,GACpC2Q,MAAO3Q,EAAMkW,UAAY7H,SAASqC,YAAYhkC,KAAKspC,EAAMhW,EAAMkW,SAASnL,eACxE0H,KAAAA,EACA/6B,KAAM,cAIVyoB,EAAQgW,QAAQ,CACZzoC,OAAQ,EACRilC,SAAUhmC,KAAKyiC,SAAS6G,QACxBlK,MAAOF,KAAK/+B,IAAI,WAAYH,KAAKy4B,QACjCqN,KAAAA,EACA/6B,KAAM,aAIVyoB,EAAQ1xB,QAAQ4/B,SAASmE,eAAeQ,KAAKrmC,OAE7C0hC,SAAS8G,cAAczoC,KAAKC,KAzCf,WAyC2B8lC,MAI5C2D,aAn/Ba,SAm/BAjW,iBAEJ9qB,KAAGuqB,QAAQjzB,KAAK40B,SAAS4N,SAASkG,OAAOnC,YAKxCT,EAAO9lC,KAAK40B,SAAS4N,SAASkG,OAAOnC,MAAMzO,cAAc,iBAG3DpvB,KAAGoqB,MAAMU,QACJA,QAAQ+S,MAAQ/S,GACdxzB,KAAK46B,SAAW56B,KAAK0pC,gBACvBlW,QAAQ+S,MAAQ,CAAC,GAAK,IAAM,EAAG,KAAM,IAAK,KAAM,SAIpD/S,QAAQ+S,MAAQvmC,KAAKwzB,QAAQ+S,MAAM/Q,OAAO,SAAA+Q,UAASoD,EAAKlR,OAAO8N,MAAM/S,QAAQtb,SAASquB,SAGrFpa,GAAUzjB,KAAGqlB,MAAM/tB,KAAKwzB,QAAQ+S,QAAUvmC,KAAKwzB,QAAQ+S,MAAMpkC,OAAS,EAC5Eu/B,SAAS4G,iBAAiBvoC,KAAKC,KAflB,QAe8BmsB,GAG3C+J,aAAa4P,GAGbpE,SAASqH,UAAUhpC,KAAKC,MAGnBmsB,SAKAqH,QAAQ+S,MAAMzkC,QAAQ,SAAAykC,GACvB7E,SAASmE,eAAe9lC,KAAK4pC,EAAM,CAC/B5oC,MAAOwlC,EACPT,KAAAA,EACA/6B,KAjCK,QAkCLq0B,MAAOsC,SAASkH,SAAS7oC,KAAK4pC,EAAM,QAASpD,OAIrD7E,SAAS8G,cAAczoC,KAAKC,KAtCf,QAsC2B8lC,MAI5CiD,UAniCa,eAoiCD7G,EAAYliC,KAAK40B,SAAS4N,SAA1BN,QACFuF,GAAW/+B,KAAGqlB,MAAMmU,IAAYjiC,OAAOmD,OAAO8+B,GAAS0H,KAAK,SAAAnF,UAAWA,EAAOvN,SAEpFD,aAAaj3B,KAAK40B,SAAS4N,SAASyB,MAAOwD,IAI/C7B,mBA3iCa,SA2iCM6C,OAAMlQ,EAAkBzyB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,OACnC9F,KAAK40B,SAAS4N,SAASqH,MAAM3S,YAI7BtrB,EAAS68B,EAER//B,KAAGuqB,QAAQrnB,KACZA,EAAS3L,OAAOmD,OAAOpD,KAAK40B,SAAS4N,SAASkG,QAAQ72B,KAAK,SAAA42B,UAASA,EAAKvR,cAGvE4S,EAAYl+B,EAAOksB,cAAc,sBAEvCQ,SAASv4B,KAAKC,KAAM8pC,EAAWvR,KAInCwR,WA5jCa,SA4jCF9Y,OACC4Y,EAAU7pC,KAAK40B,SAAS4N,SAAxBqH,MACFpF,EAASzkC,KAAK40B,SAASsN,QAAQM,YAGhC95B,KAAGuqB,QAAQ4W,IAAWnhC,KAAGuqB,QAAQwR,QAK9BvN,EAAW2S,EAAX3S,OACJ8S,EAAO9S,KAEPxuB,KAAGkqB,QAAQ3B,GACX+Y,EAAO/Y,OACJ,GAAIvoB,KAAGyqB,cAAclC,IAA0B,KAAhBA,EAAMmU,MACxC4E,GAAO,OACJ,GAAIthC,KAAGrJ,MAAM4xB,GAAQ,KAClBgZ,EAAaJ,EAAMrS,SAASvG,EAAMrlB,WAKpCq+B,IAAgBA,GAAchZ,EAAMrlB,SAAW64B,GAAUuF,SAMjEvF,EAAO7O,aAAa,gBAAiBoU,GAGrC/S,aAAa4S,GAAQG,GAGrB5S,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWuL,KAAKvuB,KAAMs0B,GAGnEA,GAAQthC,KAAGyqB,cAAclC,GACzByQ,SAASkE,mBAAmB7lC,KAAKC,KAAM,MAAM,GACrCgqC,GAAS9S,GAEjBoB,SAASv4B,KAAKC,KAAMykC,EAAQ/7B,KAAGyqB,cAAclC,MAKrDiZ,YA3mCa,SA2mCDC,OACFC,EAAQD,EAAIjV,WAAU,GAC5BkV,EAAM90B,MAAM+S,SAAW,WACvB+hB,EAAM90B,MAAM+0B,QAAU,EACtBD,EAAMjT,gBAAgB,UAGtBgT,EAAIhV,WAAWlwB,YAAYmlC,OAGrBzC,EAAQyC,EAAME,YACdC,EAASH,EAAMI,oBAGrBvU,cAAcmU,GAEP,CACHzC,MAAAA,EACA4C,OAAAA,IAKRhF,cAloCa,sBAkoCCx6B,EAA6BjF,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAtB,GAAIyyB,EAAkBzyB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GACjC8F,EAAShM,SAAS6gC,eAAT,iBAAAp2B,OAAyCrK,KAAKiK,GAA9C,KAAAI,OAAoDU,OAG9DrC,KAAGuqB,QAAQrnB,QAKVipB,EAAYjpB,EAAOupB,WACnB6I,EAAU9wB,MAAM8B,KAAK6lB,EAAUsR,UAAUt0B,KAAK,SAAAua,UAASA,EAAK8K,YAG9DyC,QAAQuB,cAAgBvB,QAAQwB,cAAe,CAE/CtG,EAAUvf,MAAMqyB,MAAhB,GAAAt9B,OAA2B2zB,EAAQsM,YAAnC,MACAzV,EAAUvf,MAAMi1B,OAAhB,GAAAlgC,OAA4B2zB,EAAQwM,aAApC,UAGMC,EAAO/I,SAASwI,YAAYnqC,KAAKC,KAAM4L,GAkB7CkoB,GAAG/zB,KAAKC,KAAM60B,EAAW8D,mBAfT,SAAV+R,EAAUrrC,GAERA,EAAMuM,SAAWipB,GAAc,CAAC,QAAS,UAAU3c,SAAS7Y,EAAMsrC,gBAKtE9V,EAAUvf,MAAMqyB,MAAQ,GACxB9S,EAAUvf,MAAMi1B,OAAS,GAGzBxW,IAAIh0B,KAAK6qC,EAAM/V,EAAW8D,mBAAoB+R,MAOlD7V,EAAUvf,MAAMqyB,MAAhB,GAAAt9B,OAA2BogC,EAAK9C,MAAhC,MACA9S,EAAUvf,MAAMi1B,OAAhB,GAAAlgC,OAA4BogC,EAAKF,OAAjC,MAIJtT,aAAa+G,GAAS,GAGtB/G,aAAarrB,GAAQ,GAGrB81B,SAASkE,mBAAmB7lC,KAAKC,KAAM4L,EAAQ2sB,KAInDsS,gBAzrCa,eA0rCHpG,EAASzkC,KAAK40B,SAASsN,QAAQ4I,SAGhCpiC,KAAGuqB,QAAQwR,IAKhBA,EAAO7O,aAAa,OAAQ51B,KAAK8qC,WAKrC55B,OAvsCa,SAusCN4S,cAEG+Q,EAAY9vB,cAAc,MAAO0xB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUP,SAASje,aAG5FzjB,KAAKy4B,OAAOiJ,SAASxpB,SAAS,YAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,YAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,WAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,WAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,SAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,SAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,iBAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,iBAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,YAAa,KACrCyqB,EAAW59B,cAAc,MAAO0xB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUU,cAGtFA,EAAS19B,YACLy8B,SAASgD,YAAY3kC,KAAKC,KAAM,OAAQ,CACpCiK,GAAE,aAAAI,OAAeyZ,EAAK7Z,OAK9B04B,EAAS19B,YAAYy8B,SAASmD,eAAe9kC,KAAKC,KAAM,WAKpDA,KAAKy4B,OAAO6O,SAASzE,KAAM,KACrBK,EAAUn+B,cACZ,OACA,CACIiyB,MAAOh3B,KAAKy4B,OAAOC,WAAWwK,SAElC,SAGJP,EAAS19B,YAAYi+B,QAChBtO,SAASrf,QAAQ0tB,YAAcC,OAGnCtO,SAAS+N,SAAWA,EACzB9N,EAAU5vB,YAAYjF,KAAK40B,SAAS+N,aAIpC3iC,KAAKy4B,OAAOiJ,SAASxpB,SAAS,iBAC9B2c,EAAU5vB,YAAYy8B,SAASuD,WAAWllC,KAAKC,KAAM,gBAIrDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,aAC9B2c,EAAU5vB,YAAYy8B,SAASuD,WAAWllC,KAAKC,KAAM,aAIrDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,SAAWlY,KAAKy4B,OAAOiJ,SAASxpB,SAAS,UAAW,KAC5E4qB,EAAS/9B,cAAc,MAAO,CAChCiyB,MAAO,oBAIPh3B,KAAKy4B,OAAOiJ,SAASxpB,SAAS,SAC9B4qB,EAAO79B,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,SAIpDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,UAAW,KAEnCpU,EAAa,CACf6O,IAAK,EACLxD,KAAM,IACNpO,MAAOf,KAAKy4B,OAAOqK,QAIvBA,EAAO79B,YACHy8B,SAASgD,YAAY3kC,KACjBC,KACA,SACAy7B,OAAO33B,EAAY,CACfmG,GAAE,eAAAI,OAAiByZ,EAAK7Z,aAK/B2qB,SAASkO,OAASA,EAG3BjO,EAAU5vB,YAAY69B,MAItB9iC,KAAKy4B,OAAOiJ,SAASxpB,SAAS,aAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,aAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,cAAgBxP,KAAGqlB,MAAM/tB,KAAKy4B,OAAO+J,UAAW,KACxEgC,EAAUz/B,cAAc,MAAO,CACjCiyB,MAAO,aACPE,OAAQ,KAGZsN,EAAQv/B,YACJy8B,SAASwC,aAAankC,KAAKC,KAAM,WAAY,kBACxB,0CACiB8jB,EAAK7Z,qBACtB,SAInB4/B,EAAQ9kC,cAAc,MAAO,CAC/BiyB,MAAO,wBACP/sB,GAAE,iBAAAI,OAAmByZ,EAAK7Z,IAC1BitB,OAAQ,KAGN6T,EAAQhmC,cAAc,OAEtBimC,EAAOjmC,cAAc,MAAO,CAC9BkF,GAAE,iBAAAI,OAAmByZ,EAAK7Z,GAAxB,WAIAg6B,EAAOl/B,cAAc,MAAO,CAC9B2+B,KAAM,SAGVsH,EAAK/lC,YAAYg/B,GACjB8G,EAAM9lC,YAAY+lC,QACbpW,SAAS4N,SAASkG,OAAOsC,KAAOA,OAGhCvS,OAAO+J,SAAS1gC,QAAQ,SAAAiJ,OAEnBo6B,EAAWpgC,cACb,SACA02B,OAAOhF,0BAA0BwU,EAAKxS,OAAOwJ,UAAUC,QAAQM,UAAW,CACtEz3B,KAAM,SACNisB,MAAK,GAAA3sB,OAAK4gC,EAAKxS,OAAOC,WAAW8L,QAA5B,KAAAn6B,OAAuC4gC,EAAKxS,OAAOC,WAAW8L,QAA9D,aACLd,KAAM,4BACW,EACjBxM,OAAQ,MAKhBwK,SAASwD,sBAAsBnlC,KAAKkrC,EAAM9F,EAAUp6B,GAGpD+oB,GAAGqR,EAAU,QAAS,WAClBzD,SAAS6D,cAAcxlC,KAAKkrC,EAAMlgC,GAAM,SAGtCm7B,EAAOnhC,cAAc,OAAQ,KAAMm6B,KAAK/+B,IAAI4K,EAAMkgC,EAAKxS,SAEvD13B,EAAQgE,cAAc,OAAQ,CAChCiyB,MAAOiU,EAAKxS,OAAOC,WAAWuL,KAAKljC,QAIvCA,EAAM69B,UAAY9a,EAAK/Y,GAEvBm7B,EAAKjhC,YAAYlE,GACjBokC,EAASlgC,YAAYihC,GACrBjC,EAAKh/B,YAAYkgC,OAGXsD,EAAO1jC,cAAc,MAAO,CAC9BkF,GAAE,iBAAAI,OAAmByZ,EAAK7Z,GAAxB,KAAAI,OAA8BU,GAChCmsB,OAAQ,KAINgU,EAAanmC,cAAc,SAAU,CACvCgG,KAAM,SACNisB,MAAK,GAAA3sB,OAAK4gC,EAAKxS,OAAOC,WAAW8L,QAA5B,KAAAn6B,OAAuC4gC,EAAKxS,OAAOC,WAAW8L,QAA9D,YAIT0G,EAAWjmC,YACPF,cACI,OACA,gBACmB,GAEnBm6B,KAAK/+B,IAAI4K,EAAMkgC,EAAKxS,UAK5ByS,EAAWjmC,YACPF,cACI,OACA,CACIiyB,MAAOiU,EAAKxS,OAAOC,WAAWxB,QAElCgI,KAAK/+B,IAAI,WAAY8qC,EAAKxS,UAKlC3E,GACI2U,EACA,UACA,SAAAppC,GAEwB,KAAhBA,EAAM+lC,QAKV/lC,EAAMJ,iBACNI,EAAMgmC,kBAGN3D,SAAS6D,cAAcxlC,KAAKkrC,EAAM,QAAQ,MAE9C,GAIJnX,GAAGoX,EAAY,QAAS,WACpBxJ,SAAS6D,cAAcxlC,KAAKkrC,EAAM,QAAQ,KAI9CxC,EAAKxjC,YAAYimC,GAGjBzC,EAAKxjC,YACDF,cAAc,MAAO,CACjB2+B,KAAM,UAIdqH,EAAM9lC,YAAYwjC,GAElBwC,EAAKrW,SAAS4N,SAASN,QAAQn3B,GAAQo6B,EACvC8F,EAAKrW,SAAS4N,SAASkG,OAAO39B,GAAQ09B,IAG1CoB,EAAM5kC,YAAY8lC,GAClBvG,EAAQv/B,YAAY4kC,GACpBhV,EAAU5vB,YAAYu/B,QAEjB5P,SAAS4N,SAASqH,MAAQA,OAC1BjV,SAAS4N,SAASyB,KAAOO,KAI9BxkC,KAAKy4B,OAAOiJ,SAASxpB,SAAS,QAAUyhB,QAAQS,KAChDvF,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,QAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,YAAcyhB,QAAQa,SACpD3F,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,YAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,YAAa,KACrCpU,EAAa,CACfmvB,QAAS,IACT7uB,KAAMpE,KAAK8qC,SACXl/B,OAAQ,UAGJk/B,EAAa9qC,KAAKy4B,OAAO0S,KAAzBL,UAEHpiC,KAAGlE,IAAIsmC,IAAa9qC,KAAKorC,SAC1B3P,OAAO33B,EAAY,CACf0/B,KAAI,QAAAn5B,OAAUrK,KAAK85B,UACnBuK,MAAOrkC,KAAK85B,WAIpBjF,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,WAAY8D,WAInE9D,KAAKy4B,OAAOiJ,SAASxpB,SAAS,eAC9B2c,EAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,eAIvDA,KAAKy4B,OAAOiJ,SAASxpB,SAAS,oBACzB0c,SAASC,UAAU5vB,YAAYy8B,SAASwC,aAAankC,KAAKC,KAAM,oBAGpE40B,SAAS8M,SAAW7M,EAGrB70B,KAAK46B,SACL8G,SAASmH,eAAe9oC,KAAKC,KAAMq7B,MAAMG,kBAAkBz7B,KAAKC,OAGpE0hC,SAAS+H,aAAa1pC,KAAKC,MAEpB60B,GAIXwW,OApgDa,yBAsgDLrrC,KAAKy4B,OAAO6H,WAAY,KAClBkD,EAAO9B,SAASC,WAAW5hC,KAAKC,MAGlCwjC,EAAK5B,MACLtB,WAAWkD,EAAKh/B,IAAK,oBAKxByF,GAAKpC,KAAKyF,MAAsB,IAAhBzF,KAAKsC,cAGtB0qB,EAAY,UACXD,SAAS8M,SAAW,SAGnB0C,EAAQ,CACVn6B,GAAIjK,KAAKiK,GACTqhC,SAAUtrC,KAAKy4B,OAAO0G,SACtBC,MAAOp/B,KAAKy4B,OAAO2G,OAEnBsB,GAAS,EAGTh4B,KAAGmqB,SAAS7yB,KAAKy4B,OAAOiJ,iBACnBjJ,OAAOiJ,SAAW1hC,KAAKy4B,OAAOiJ,SAAS3hC,KAAKC,KAAMokC,IAItDpkC,KAAKy4B,OAAOiJ,gBACRjJ,OAAOiJ,SAAW,IAGvBh5B,KAAGuqB,QAAQjzB,KAAKy4B,OAAOiJ,WAAah5B,KAAG+L,OAAOzU,KAAKy4B,OAAOiJ,UAE1D7M,EAAY70B,KAAKy4B,OAAOiJ,UAGxB7M,EAAY6M,SAASxwB,OAAOnR,KAAKC,KAAM,CACnCiK,GAAIjK,KAAKiK,GACTqhC,SAAUtrC,KAAKy4B,OAAO0G,SACtBoH,MAAOvmC,KAAKumC,MACZrK,QAASl8B,KAAKk8B,QACduG,SAAUA,SAASmG,SAAS7oC,KAAKC,QAIrC0gC,GAAS,OAwBT90B,EApBExK,EAAU,SAAA6vB,OACR/hB,EAAS+hB,SAEbhxB,OAAOiD,QAAQkhC,GAAOtiC,QAAQ,SAAAu9B,6BAAEh9B,EAAgBqzB,EAAA,GAAX30B,EAAW20B,EAAA,GAC5CxmB,EAASgvB,WAAWhvB,EAAD,IAAA7E,OAAahI,EAAb,KAAqBtB,KAGrCmO,MAIPwxB,IACIh4B,KAAG+L,OAAOzU,KAAKy4B,OAAOiJ,UACtB7M,EAAYzzB,EAAQyzB,GACbnsB,KAAGuqB,QAAQ4B,KAClBA,EAAU+J,UAAYx9B,EAAQyzB,EAAU+J,aAQ5Cl2B,KAAG+L,OAAOzU,KAAKy4B,OAAOwJ,UAAUP,SAAS7M,aACzCjpB,EAAShM,SAASk4B,cAAc93B,KAAKy4B,OAAOwJ,UAAUP,SAAS7M,YAI9DnsB,KAAGuqB,QAAQrnB,KACZA,EAAS5L,KAAK40B,SAASC,WAK3BjpB,EADqBlD,KAAGuqB,QAAQ4B,GAAa,wBAA0B,sBAClD,aAAcA,GAG9BnsB,KAAGuqB,QAAQjzB,KAAK40B,SAAS8M,WAC1BA,SAASM,aAAajiC,KAAKC,OAI1B0I,KAAGqlB,MAAM/tB,KAAK40B,SAASsN,SAAU,KAC5BqJ,EAAc,SAAA9G,OACV3N,EAAY0U,EAAK/S,OAAOC,WAAW+S,eACzCxrC,OAAOC,eAAeukC,EAAQ,UAAW,CACrC9gC,YAAY,EACZxD,IAFqC,kBAG1Bs3B,SAASgN,EAAQ3N,IAE5B/zB,IALqC,eAKjC8jC,EAAiB/gC,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GACjBsxB,YAAYqN,EAAQ3N,EAAW+P,OAM3C5mC,OAAOmD,OAAOpD,KAAK40B,SAASsN,SACvB1M,OAAOrE,SACPrvB,QAAQ,SAAA2iC,GACD/7B,KAAGoqB,MAAM2R,IAAW/7B,KAAGsqB,SAASyR,GAChCv3B,MAAM8B,KAAKy1B,GACNjP,OAAOrE,SACPrvB,QAAQypC,GAEbA,EAAY9G,QAMxBvL,QAAQG,QACRL,QAAQptB,GAIR5L,KAAKy4B,OAAO6O,SAAS5F,SAAU,OACG1hC,KAAKy4B,OAA/BC,EADuBgT,EACvBhT,WAAYuJ,EADWyJ,EACXzJ,UACdpL,EAAQ,GAAAxsB,OAAM43B,EAAUP,SAASje,QAAzB,KAAApZ,OAAoC43B,EAAU0J,OAA9C,MAAAthC,OAAyDquB,EAAWxB,QAC5EyU,EAAS/T,YAAY73B,KAAKC,KAAM62B,GAEtC3pB,MAAM8B,KAAK28B,GAAQ7pC,QAAQ,SAAAuiC,GACvBjN,YAAYiN,EAAOmH,EAAK/S,OAAOC,WAAWxB,QAAQ,GAClDE,YAAYiN,EAAOmH,EAAK/S,OAAOC,WAAWwK,SAAS,QCpqDnE,SAAgB0I,SAAS3a,OACjBzsB,EAAMysB,OAD+BnrB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAG/B,KACA+lC,EAASjsC,SAASmF,cAAc,KACtC8mC,EAAOznC,KAAOI,EACdA,EAAMqnC,EAAOznC,gBAIN,IAAIF,IAAIM,GACjB,MAAOpF,UACE,MAKf,SAAgB0sC,eAAe7a,OACrB3xB,EAAS,IAAIiC,uBAEfmH,KAAGoB,OAAOmnB,IACVhxB,OAAOiD,QAAQ+tB,GAAOnvB,QAAQ,SAAA2zB,6BAAEpzB,EAAgBg9B,EAAA,GAAXt+B,EAAWs+B,EAAA,GAC5C//B,EAAOyD,IAAIV,EAAKtB,KAIjBzB,ECbX,IAAMmjC,SAAW,CAEbsJ,MAFa,cAIJ/rC,KAAKuzB,UAAU2G,OAKfl6B,KAAKgsC,SAAWhsC,KAAKisC,WAAcjsC,KAAK46B,UAAYjB,QAAQoB,WAGzDryB,KAAGoqB,MAAM9yB,KAAKy4B,OAAOiJ,WACrB1hC,KAAKy4B,OAAOiJ,SAASxpB,SAAS,aAC9BlY,KAAKy4B,OAAO+J,SAAStqB,SAAS,aAE9BwpB,SAASwH,gBAAgBnpC,KAAKC,cAOjC0I,KAAGuqB,QAAQjzB,KAAK40B,SAAS6N,iBACrB7N,SAAS6N,SAAW19B,cAAc,MAAO0xB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUQ,WAE9F1M,YAAY/1B,KAAK40B,SAAS6N,SAAUziC,KAAK40B,SAASnR,UAKlDyV,QAAQC,MAAQt6B,OAAOqF,IAAK,KACtB0wB,EAAW50B,KAAK66B,MAAMlD,iBAAiB,SAE7CzqB,MAAM8B,KAAK4lB,GAAU9yB,QAAQ,SAAAuxB,OACnB7d,EAAM6d,EAAMkI,aAAa,OACzB/2B,EAAMonC,SAASp2B,GAGT,OAARhR,GACAA,EAAImC,WAAa9H,OAAO+F,SAASR,KAAKuC,UACtC,CAAC,QAAS,UAAUuR,SAAS1T,EAAIc,WAEjCw6B,MAAMtqB,EAAK,QACN0W,KAAK,SAAAnlB,GACFssB,EAAMuC,aAAa,MAAO/2B,OAAOqF,IAAI4C,gBAAgBC,MAExDopB,MAAM,WACH8F,cAAc5C,WAc5B6Y,EAAY3P,QADOzQ,UAAUogB,WAAa,CAACpgB,UAAUyd,UAAYzd,UAAUqgB,cAAgB,OACvD7U,IAAI,SAAAiS,UAAYA,EAASxlC,MAAM,KAAK,MAE1EwlC,GAAYvpC,KAAKw/B,QAAQr/B,IAAI,aAAeH,KAAKy4B,OAAOgK,SAAS8G,UAAY,QAAQjL,iBAGxE,SAAbiL,EACCA,iBAAY2C,EADQ,GAAA,OAIrBE,EAASpsC,KAAKw/B,QAAQr/B,IAAI,eACzBuI,KAAGkqB,QAAQwZ,KACTA,EAAWpsC,KAAKy4B,OAAOgK,SAAvB2J,QAGPnsC,OAAO+hB,OAAOhiB,KAAKyiC,SAAU,CACzB6G,SAAS,EACT8C,OAAAA,EACA7C,SAAAA,EACA2C,UAAAA,IAIAlsC,KAAK46B,QAAS,KACRyR,EAAcrsC,KAAKy4B,OAAOgK,SAAS/B,OAAS,uBAAyB,cAC3E5M,GAAG/zB,KAAKC,KAAMA,KAAK66B,MAAME,WAAYsR,EAAa5J,SAAS/B,OAAO2F,KAAKrmC,OAI3E8qB,WAAW2X,SAAS/B,OAAO2F,KAAKrmC,MAAO,KAI3C0gC,OA9Fa,sBA+FHyI,EAAS1G,SAAS2G,UAAUrpC,KAAKC,MAAM,KAEQA,KAAKyiC,SAAlD2J,EAHHE,EAGGF,OAAQ7C,EAHX+C,EAGW/C,SAAU/nB,EAHrB8qB,EAGqB9qB,KAAM+qB,EAH3BD,EAG2BC,iBAC1BC,EAAiBrb,QAAQgY,EAAOt3B,KAAK,SAAAwhB,UAASA,EAAMkW,WAAaA,KAGnEvpC,KAAK46B,SAAW56B,KAAKgsC,SACrB7C,EAAO3T,OAAO,SAAAnC,UAAU7R,EAAKrhB,IAAIkzB,KAAQvxB,QAAQ,SAAAuxB,GAC7CxxB,EAAKw6B,MAAMC,IAAI,cAAejJ,GAE9B7R,EAAKze,IAAIswB,EAAO,CACZsV,QAAwB,YAAftV,EAAMzmB,OAInBymB,EAAMzmB,KAAO,SAGbknB,GAAG/zB,KAAK8B,EAAMwxB,EAAO,YAAa,kBAAMoP,SAASgK,WAAW1sC,KAAK8B,QAKpE2qC,GAAkBxsC,KAAKupC,WAAaA,IAAcJ,EAAOjxB,SAASq0B,MACnE9J,SAASiK,YAAY3sC,KAAKC,KAAMupC,GAChC9G,SAAStW,OAAOpsB,KAAKC,KAAMosC,GAAUI,IAIzCpV,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAW+J,SAASlD,SAAU72B,KAAGqlB,MAAMob,KAGnFnpC,KAAKy4B,OAAOiJ,UAAY,IAAIxpB,SAAS,aAAelY,KAAKy4B,OAAO+J,SAAStqB,SAAS,aACnFwpB,SAASwH,gBAAgBnpC,KAAKC,OAMtCmsB,OAtIa,SAsIN8E,OAAO0C,IAAgB7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,MAErB9F,KAAKuzB,UAAU2G,QAIZoP,EAAYtpC,KAAKyiC,SAAjB6G,QACFqD,EAAc3sC,KAAKy4B,OAAOC,WAAW+J,SAAS2J,OAI9CA,EAAS1jC,KAAGiqB,gBAAgB1B,IAAUqY,EAAUrY,KAGlDmb,IAAW9C,EAAS,IAEf3V,SACI8O,SAAS2J,OAASA,OAClB5M,QAAQz8B,IAAI,CAAE0/B,SAAU2J,MAI5BpsC,KAAKupC,UAAY6C,IAAWzY,EAAS,KAChCwV,EAAS1G,SAAS2G,UAAUrpC,KAAKC,MACjCqzB,EAAQoP,SAASmK,UAAU7sC,KAAKC,KAAxB,CAA+BA,KAAKyiC,SAAS8G,UAA7Cl/B,OAAAwiC,mBAA0D7sC,KAAKyiC,SAASyJ,aAAY,eAG7FzJ,SAAS8G,SAAWlW,EAAMkW,cAG/B9G,SAAS1/B,IAAIhD,KAAKC,KAAMmpC,EAAOjkC,QAAQmuB,IAKvCrzB,KAAK40B,SAASsN,QAAQO,gBACjB7N,SAASsN,QAAQO,SAASoE,QAAUuF,GAI7ChV,YAAYp3B,KAAK40B,SAASC,UAAW8X,EAAaP,QAE7C3J,SAAS6G,QAAU8C,EAGxB1K,SAAS8G,cAAczoC,KAAKC,KAAM,YAGlCq0B,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAOuR,EAAS,kBAAoB,uBAMzErpC,IA5La,SA4LT8K,OAAO8lB,IAAgB7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GACjBqjC,EAAS1G,SAAS2G,UAAUrpC,KAAKC,UAGxB,IAAX6N,KAKCnF,KAAGsoB,OAAOnjB,MAKTA,KAASs7B,MAKXnpC,KAAKyiC,SAAS6D,eAAiBz4B,EAAO,MACjC40B,SAAS6D,aAAez4B,MACvBwlB,EAAQ8V,EAAOt7B,GACb07B,GAAalW,GAAS,IAAtBkW,cAGH9G,SAAS8J,iBAAmBlZ,EAGjCqO,SAAS8G,cAAczoC,KAAKC,KAAM,YAG7B2zB,SACI8O,SAAS8G,SAAWA,OACpB/J,QAAQz8B,IAAI,CAAEwmC,SAAAA,KAInBvpC,KAAK0pC,cACAoD,MAAMC,gBAAgBxD,GAI/BlV,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAO,kBAIxC4H,SAAStW,OAAOpsB,KAAKC,MAAM,EAAM2zB,GAE7B3zB,KAAK46B,SAAW56B,KAAKgsC,SAErBvJ,SAASgK,WAAW1sC,KAAKC,gBAnCpBq8B,MAAM8G,KAAK,kBAAmBt1B,aAL9BwuB,MAAM8G,KAAK,2BAA4Bt1B,QAL5C40B,SAAStW,OAAOpsB,KAAKC,MAAM,EAAO2zB,IAmD1C+Y,YApPa,SAoPDzb,OAAO0C,IAAgB7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,MAC1B4C,KAAG+L,OAAOwc,QAKTsY,EAAWtY,EAAMqN,mBAClBmE,SAAS8G,SAAWA,MAGnBJ,EAAS1G,SAAS2G,UAAUrpC,KAAKC,MACjCqzB,EAAQoP,SAASmK,UAAU7sC,KAAKC,KAAM,CAACupC,IAC7C9G,SAAS1/B,IAAIhD,KAAKC,KAAMmpC,EAAOjkC,QAAQmuB,GAAQM,aAVtC0I,MAAM8G,KAAK,4BAA6BlS,IAgBrDmY,UAtQa,sBAsQH1I,EAAgB56B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,UAEPoH,MAAM8B,MAAMhP,KAAK66B,OAAS,IAAIE,YAAc,IAItDvF,OAAO,SAAAnC,UAAUe,EAAKwG,SAAW8F,GAAUtM,EAAKqO,SAASjhB,KAAK1e,IAAIuwB,KAClEmC,OAAO,SAAAnC,SAAS,CAAC,WAAY,aAAanb,SAASmb,EAAM/V,SAIlEsvB,UAjRa,SAiRHV,OAIF7Y,SAJagE,EAAevxB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAC1BqjC,EAAS1G,SAAS2G,UAAUrpC,KAAKC,MACjCgtC,EAAgB,SAAA3Z,UAAS/B,QAAQqD,EAAK8N,SAASjhB,KAAKrhB,IAAIkzB,IAAU,IAAIsV,UACtEsE,EAAS//B,MAAM8B,KAAKm6B,GAAQ3lC,KAAK,SAACC,EAAGC,UAAMspC,EAActpC,GAAKspC,EAAcvpC,YAElFyoC,EAAUgB,MAAM,SAAA3D,WACZlW,EAAQ4Z,EAAOp7B,KAAK,SAAAwhB,UAASA,EAAMkW,WAAaA,OAI7ClW,IAAUgE,EAAQ4V,EAAO,QAAKttC,IAIzCwtC,gBA/Ra,kBAgSF1K,SAAS2G,UAAUrpC,KAAKC,MAAMA,KAAKsmC,eAI9CsC,SApSa,SAoSJvV,OACDiT,EAAejT,SAEd3qB,KAAG2qB,MAAMiT,IAAiB3M,QAAQoB,YAAc/6B,KAAKyiC,SAAS6G,UAC/DhD,EAAe7D,SAAS0K,gBAAgBptC,KAAKC,OAG7C0I,KAAG2qB,MAAMiT,GACJ59B,KAAGqlB,MAAMuY,EAAajC,OAItB37B,KAAGqlB,MAAMuY,EAAaiD,UAIpBrK,KAAK/+B,IAAI,UAAWH,KAAKy4B,QAHrBpF,EAAMkW,SAASnL,cAJfkI,EAAajC,MAUrBnF,KAAK/+B,IAAI,WAAYH,KAAKy4B,SAKrCgU,WA5Ta,SA4TFxb,MAEFjxB,KAAKuzB,UAAU2G,MAIfxxB,KAAGuqB,QAAQjzB,KAAK40B,SAAS6N,aAMzB/5B,KAAGiqB,gBAAgB1B,IAAW/jB,MAAM+C,QAAQghB,QAK7Cmc,EAAOnc,MAGNmc,EAAM,KACD/Z,EAAQoP,SAAS0K,gBAAgBptC,KAAKC,MAC5CotC,EAAOlgC,MAAM8B,MAAMqkB,GAAS,IAAIga,YAAc,IACzC/V,IAAI,SAAAlE,UAAOA,EAAIka,iBACfhW,IAAIwH,aAIPgC,EAAUsM,EAAK9V,IAAI,SAAAiW,UAAWA,EAAQ/4B,SAAQlR,KAAK,SACzCw9B,IAAY9gC,KAAK40B,SAAS6N,SAAS7D,UAEtC,CAET1I,aAAal2B,KAAK40B,SAAS6N,cACrB+K,EAAUzoC,cAAc,OAAQ0xB,0BAA0Bz2B,KAAKy4B,OAAOwJ,UAAUuL,UACtFA,EAAQ5O,UAAYkC,OACflM,SAAS6N,SAASx9B,YAAYuoC,GAGnCnZ,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAO,wBA1B/BwB,MAAM8G,KAAK,4BAA6BlS,aANxCoL,MAAM8G,KAAK,sCCvVtBsK,SAAW,CAEblO,SAAS,EAGTH,MAAO,GAGP/C,OAAO,EAGPqR,UAAU,EAGVC,WAAW,EAIX5T,aAAa,EAGboF,SAAU,GAGV2D,OAAQ,EACR8D,OAAO,EAGP5D,SAAU,KAIVqF,iBAAiB,EAGjBL,YAAY,EAGZ4F,cAAc,EAGdC,MAAO,OAGPC,aAAa,EAGbC,cAAc,EAGdC,YAAY,EAGZC,oBAAoB,EAGpB3N,YAAY,EACZiD,WAAY,OACZ1B,QAAS,qCAGTzF,WAAY,uCAGZF,QAAS,CACLyM,QAAS,IACTnV,QAAS,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,IAAK,IAAK,IAAK,IAAK,MAIhE0a,KAAM,CACF9B,QAAQ,GAMZ7F,MAAO,CACH4H,SAAU,EACV3a,QAAS,CAAC,GAAK,IAAM,EAAG,KAAM,IAAK,KAAM,IAI7C4a,SAAU,CACNlW,SAAS,EACT53B,QAAQ,GAIZgnC,SAAU,CACN5F,UAAU,EACVmB,MAAM,GAIVJ,SAAU,CACN2J,QAAQ,EACR7C,SAAU,OAGV7I,QAAQ,GAIZgC,WAAY,CACRnD,SAAS,EACT8O,UAAU,EACVC,WAAW,GAIf9O,QAAS,CACLD,SAAS,EACTl9B,IAAK,QAITq/B,SAAU,CACN,+BAMA,eACA,OACA,SACA,WACA,WACA,MACA,wBAIJc,SAAU,CAAC,WAAY,UAAW,SAGlCtD,KAAM,CACFkD,QAAS,UACTC,OAAQ,qBACRrG,KAAM,OACNmG,MAAO,QACPG,YAAa,sBACbO,KAAM,OACN0L,UAAW,8BACXxJ,OAAQ,SACRmC,SAAU,WACVvL,YAAa,eACbqH,SAAU,WACVF,OAAQ,SACRP,KAAM,OACNiM,OAAQ,SACRC,eAAgB,kBAChBC,gBAAiB,mBACjB5D,SAAU,WACV6D,gBAAiB,mBACjBC,eAAgB,kBAChBC,WAAY,qBACZpM,SAAU,WACVD,SAAU,WACVsM,SAAU,2BACVvI,MAAO,QACPwI,OAAQ,SACR7S,QAAS,UACTgS,KAAM,OACNc,MAAO,QACPC,IAAK,MACLze,IAAK,MACL0e,MAAO,QACPC,SAAU,WACV5P,QAAS,UACT6P,cAAe,KACfC,aAAc,MACJ,UACA,UACA,SACD,SACA,SACA,OAKblE,KAAM,CACFL,SAAU,KACV9L,MAAO,CACHsQ,IAAK,yCACLj6B,OAAQ,yCACR4kB,IAAK,2CAETgF,QAAS,CACLqQ,IAAK,qCACLrV,IACI,yGAERsV,UAAW,CACPD,IAAK,uDAKblJ,UAAW,CACPvD,KAAM,KACN7G,KAAM,KACNmG,MAAO,KACPC,QAAS,KACTC,OAAQ,KACRC,YAAa,KACbC,KAAM,KACNO,OAAQ,KACRL,SAAU,KACVqI,SAAU,KACVpI,WAAY,KACZtI,IAAK,KACLI,QAAS,KACT+L,MAAO,KACPrK,QAAS,KACTgS,KAAM,KACN3E,SAAU,MAId3V,OAAQ,SAIJ,WACA,UACA,UACA,UACA,UACA,iBACA,YACA,aACA,iBACA,aACA,eACA,OACA,QACA,QACA,UACA,SACA,UACA,aACA,uBAIA,kBACA,iBACA,kBACA,mBACA,iBACA,iBACA,gBACA,kDAUA,kBACA,mBACA,YACA,cACA,cACA,iBACA,gBACA,YAKJqO,UAAW,CACPuN,SAAU,6CACV3a,UAAW,QACX6M,SAAU,CACN7M,UAAW,KACXpR,QAAS,mBAEbkoB,OAAQ,cACRzJ,QAAS,CACLlG,KAAM,qBACNmG,MAAO,sBACPC,QAAS,wBACTC,OAAQ,uBACRC,YAAa,6BACbC,KAAM,qBACNE,SAAU,yBACVqI,SAAU,yBACVpI,WAAY,2BACZtI,IAAK,oBACLI,QAAS,wBACTgI,SAAU,yBACV0L,KAAM,sBAEVtL,OAAQ,CACJC,KAAM,qBACNC,OAAQ,uBACRyD,MAAO,sBACPgD,SAAU,yBACVrN,QAAS,yBAEb3mB,QAAS,CACLomB,YAAa,uBACbqH,SAAU,wBACVD,OAAQ,0BACRmL,KAAM,wBACNpL,OAAQ,0BAEZH,SAAU,kBACVF,SAAU,kBACV+K,QAAS,iBACTvJ,KAAM,CACF/H,QAAS,kCAKjBxD,WAAY,CACR3tB,KAAM,YACN+uB,SAAU,YACVD,MAAO,sBACPiT,MAAO,oBACP2C,eAAgB,+BAChBC,OAAQ,eACRC,cAAe,uBACfC,IAAK,YACLpL,QAAS,gBACTiH,eAAgB,yBAChBoE,QAAS,gBACThU,OAAQ,eACRiU,QAAS,gBACTC,QAAS,gBACTC,MAAO,cACP9M,QAAS,gBACTkK,KAAM,aACNlW,OAAQ,gBACR6W,aAAc,sBACdtU,MAAO,eACPwW,QAAS,iBACTC,YAAa,gBACbC,aAAc,sBACd56B,QAAS,CACL6rB,KAAM,cAEV6C,KAAM,CACFljC,MAAO,oBACPijC,MAAO,cACPtuB,KAAM,mBAEV+sB,SAAU,CACNlD,QAAS,yBACT6M,OAAQ,yBAEZ1J,WAAY,CACRnD,QAAS,2BACT8O,SAAU,6BAEdjU,IAAK,CACD7G,UAAW,sBACX6Y,OAAQ,oBAEZ5R,QAAS,CACLjH,UAAW,0BACX6Y,OAAQ,wBAEZ7T,SAAU,kBACV6X,kBAAmB,CAEfC,eAAgB,sBAChBC,oBAAqB,gCACrBC,eAAgB,uCAChBC,cAAe,sCAEfC,mBAAoB,0BACpBC,wBAAyB,sCAKjC5sC,WAAY,CACRgpC,MAAO,CACHhT,SAAU,qBACV7vB,GAAI,uBAKZ9G,KAAM,CACFwtC,OAAQ,MAKZf,IAAK,CACDrQ,SAAS,EACTqR,YAAa,GACbC,OAAQ,IAIZT,kBAAmB,CACf7Q,SAAS,EACT/pB,IAAK,IAITwpB,MAAO,CACH8R,QAAQ,EACRC,UAAU,EACV3R,OAAO,EACPmH,OAAO,EACPyK,aAAa,GAIjB/R,QAAS,CACLgS,UAAU,EACVC,IAAK,EACLC,SAAU,EACVC,eAAgB,EAChBC,eAAgB,IC1aXjX,IAAM,CACfgS,OAAQ,qBACRkF,SAAU,UCFDC,UAAY,CACrBlW,MAAO,QACP4D,QAAS,UACTD,MAAO,SAGEwS,MAAQ,CACjB5X,MAAO,QACPC,MAAO,SAOX,SAAgB4X,iBAAiBjtC,SAEzB,8EAA8Ee,KAAKf,GAC5E+sC,UAAUtS,QAIjB,wDAAwD15B,KAAKf,GACtD+sC,UAAUvS,MAGd,KC1BX,IAAM0S,KAAO,aAEQC,oCACLpS,EAAiBz5B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,gCACpBy5B,QAAU1gC,OAAOswB,SAAWoQ,EAE7Bv/B,KAAKu/B,cACAjD,IAAI,6EAMNt8B,KAAKu/B,QAAUz3B,SAAS1H,UAAUimC,KAAKtmC,KAAKovB,QAAQmN,IAAKnN,SAAWuiB,yCAKpE1xC,KAAKu/B,QAAUz3B,SAAS1H,UAAUimC,KAAKtmC,KAAKovB,QAAQgU,KAAMhU,SAAWuiB,0CAKrE1xC,KAAKu/B,QAAUz3B,SAAS1H,UAAUimC,KAAKtmC,KAAKovB,QAAQzuB,MAAOyuB,SAAWuiB,cCfrF,SAASE,cACA5xC,KAAKu/B,aAKJkF,EAASzkC,KAAK07B,OAAO9G,SAASsN,QAAQQ,WACxCh6B,KAAGuqB,QAAQwR,KACXA,EAAOoC,QAAU7mC,KAAKosC,QAI1B/X,aAAat0B,KAAKC,KAAK07B,OAAQ17B,KAAK4L,OAAQ5L,KAAKosC,OAAS,kBAAoB,kBAAkB,GAG3FlT,QAAQO,OACT1B,UAAUh4B,KAAKC,KAAK07B,OAAQ17B,KAAK4L,OAAQ5L,KAAKosC,SAItD,SAASyF,4BAAe1lB,EAAgBrmB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,MAEhCqmB,OACK2lB,eAAiB,CAClBx5B,EAAGzZ,OAAOkzC,SAAW,EACrBx5B,EAAG1Z,OAAOmzC,SAAW,GAGzBnzC,OAAOozC,SAASjyC,KAAK8xC,eAAex5B,EAAGtY,KAAK8xC,eAAev5B,GAI/D3Y,SAASyF,KAAKiQ,MAAM48B,SAAW/lB,EAAS,SAAW,GAGnDiL,YAAYp3B,KAAK4L,OAAQ5L,KAAK07B,OAAOjD,OAAOC,WAAWgK,WAAW2L,SAAUliB,GAGxE+M,QAAQO,MAAO,KACX0Y,EAAWvyC,SAASoF,KAAK8yB,cAAc,yBACrCsa,EAAW,qBAGZD,IACDA,EAAWvyC,SAASmF,cAAc,SACzB6wB,aAAa,OAAQ,gBAI5Byc,EAAc3pC,KAAG+L,OAAO09B,EAASrR,UAAYqR,EAASrR,QAAQ5oB,SAASk6B,GAEzEjmB,QACKmmB,iBAAmBD,EAEnBA,IACDF,EAASrR,SAAT,IAAAz2B,OAAwB+nC,KAErBpyC,KAAKsyC,kBACZH,EAASrR,QAAUqR,EAASrR,QACvB/8B,MAAM,KACNyxB,OAAO,SAAA+c,UAAQA,EAAK/9B,SAAW49B,IAC/B9uC,KAAK,MAIdwnB,WAAW,kBAAMkO,QAAQn3B,EAAK+J,SAAS,KAI3CgmC,SAAS7xC,KAAKC,UAGZwyC,iCACU9W,2CAEHA,OAASA,OAGTmC,OAAS2U,EAAW3U,YACpBuU,SAAWI,EAAWJ,cAGtBN,eAAiB,CAAEx5B,EAAG,EAAGC,EAAG,QAG5Bk6B,cAAsD,UAAtC/W,EAAOjD,OAAOiK,WAAW2L,SAI9Cva,GAAG/zB,KACCC,KAAK07B,OACL97B,SACgB,OAAhBI,KAAK69B,OAAkB,qBAAvB,GAAAxzB,OAAiDrK,KAAK69B,OAAtD,oBACA,WAEI+T,SAAS7xC,KAAKq0B,KAKtBN,GAAG/zB,KAAKC,KAAK07B,OAAQ17B,KAAK07B,OAAO9G,SAASC,UAAW,WAAY,SAAAx1B,GAEzDqJ,KAAGuqB,QAAQmB,EAAKsH,OAAO9G,SAAS8M,WAAatN,EAAKsH,OAAO9G,SAAS8M,SAASlK,SAASn4B,EAAMuM,SAI9FwoB,EAAKjI,gBAIJuU,mEAiFG9zB,EADJ5M,KAAKu/B,SAID3yB,EADA5M,KAAKyyC,cACE,oBACAD,EAAWE,OACX,SAEA,gBAGNhX,OAAOW,MAAMC,IAAlB,GAAAjyB,OAAyBuC,EAAzB,8BAEK8uB,OAAOW,MAAMC,IAAI,kDAI1BlF,YAAYp3B,KAAK07B,OAAO9G,SAASC,UAAW70B,KAAK07B,OAAOjD,OAAOC,WAAWgK,WAAWnD,QAASv/B,KAAKu/B,yCAK9Fv/B,KAAKu/B,UAKNrG,QAAQO,OAASz5B,KAAK07B,OAAOjD,OAAOiK,WAAW4L,eAC1C1iC,OAAO+mC,yBACJH,EAAWE,QAAU1yC,KAAKyyC,cAClCZ,eAAe9xC,KAAKC,MAAM,GAClBA,KAAK69B,OAELn1B,KAAGqlB,MAAM/tB,KAAK69B,cACjBjyB,OAAL,GAAAvB,OAAerK,KAAK69B,OAApB,WAAAxzB,OAAoCrK,KAAKoyC,kBAFpCxmC,OAAOgnC,uDAQX5yC,KAAKu/B,WAKNrG,QAAQO,OAASz5B,KAAK07B,OAAOjD,OAAOiK,WAAW4L,eAC1C1iC,OAAOinC,4BACPnX,OAAOM,YACT,IAAKwW,EAAWE,QAAU1yC,KAAKyyC,cAClCZ,eAAe9xC,KAAKC,MAAM,QACvB,GAAKA,KAAK69B,QAEV,IAAKn1B,KAAGqlB,MAAM/tB,KAAK69B,QAAS,KACzBiV,EAAyB,QAAhB9yC,KAAK69B,OAAmB,SAAW,OAClDj+B,SAAQ,GAAAyK,OAAIrK,KAAK69B,QAATxzB,OAAkByoC,GAAlBzoC,OAA2BrK,KAAKoyC,mBAHvCxyC,SAASmzC,kBAAoBnzC,SAASgvC,gBAAgB7uC,KAAKH,2CAS3DI,KAAKosC,YAGDxgB,YAFAC,mDA9HF2mB,EAAWE,SAAW1yC,KAAKyyC,qDAiC7BD,EAAWE,QAAU1yC,KAAK07B,OAAOjD,OAAOiK,WAAW2L,WACpDruC,KAAK07B,OAAOjD,OAAOiK,WAAWnD,SAC9Bv/B,KAAK07B,OAAOnI,UAAU2G,IACtBl6B,KAAK07B,OAAOsQ,+CAMXhsC,KAAKu/B,WAKLiT,EAAWE,QAAU1yC,KAAKyyC,cACpBhb,SAASz3B,KAAK4L,OAAQ5L,KAAK07B,OAAOjD,OAAOC,WAAWgK,WAAW2L,WAGzDruC,KAAK69B,OAAsCj+B,SAAQ,GAAAyK,OAAIrK,KAAK69B,QAATxzB,OAAkBrK,KAAKoyC,SAAvB,YAArCxyC,SAASozC,qBAErBhzC,KAAK4L,8CAKjBstB,QAAQO,OAASz5B,KAAK07B,OAAOjD,OAAOiK,WAAW4L,UAChDtuC,KAAK07B,OAAOb,MACZ76B,KAAK07B,OAAO9G,SAASC,oDArEvBj1B,SAASqzC,mBACTrzC,SAASszC,yBACTtzC,SAASuzC,sBACTvzC,SAASwzC,uDAYT1qC,KAAGmqB,SAASjzB,SAASgvC,sBACd,OAIP7tC,EAAQ,SACK,CAAC,SAAU,MAAO,MAE1B6oC,KAAK,SAAAyJ,YACN3qC,KAAGmqB,SAASjzB,SAAQ,GAAAyK,OAAIgpC,EAAJ,sBAA6B3qC,KAAGmqB,SAASjzB,SAAQ,GAAAyK,OAAIgpC,EAAJ,yBACrEtyC,EAAQsyC,GACD,KAMRtyC,yCAIgB,QAAhBf,KAAK69B,OAAmB,aAAe,sBCnKtDyV,UAAiBzrC,KAAK0rC,MAAQ,SAAcj7B,GAE1C,OAAmB,IAAXA,GAAKA,IAAWA,GAAKA,EAAIA,EAAIA,EAAI,GAAK,EAAI,GCGpD,SAAwBk7B,UAAUh+B,OAAKi+B,EAAc3tC,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAH,SACvC,IAAIslB,QAAQ,SAACY,EAASU,OACnBgnB,EAAQ,IAAIC,MAEZ7kB,EAAU,kBACL4kB,EAAME,cACNF,EAAMG,SACZH,EAAMI,cAAgBL,EAAWznB,EAAUU,GAAQgnB,IAGxDzzC,OAAO+hB,OAAO0xB,EAAO,CAAEE,OAAQ9kB,EAAS+kB,QAAS/kB,EAAStZ,IAAAA,MCblE1K,QAAQA,QAAQ9B,EAAG,OAAQ,CAAEuqC,KAAM9qC,YCWnC,IAAMyxB,GAAK,CACP6Z,aADO,WAEH3c,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOwJ,UAAUpN,UAAUzzB,QAAQ,IAAK,KAAK,GACvFg2B,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWwX,YAAalwC,KAAKuzB,UAAU2G,KAI5FkJ,qBAPO,WAO8Bt9B,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,IACnB9F,KAAK46B,aACVC,MAAMjF,aAAa,WAAY,SAE/BiF,MAAM1D,gBAAgB,aAKnC6c,MAhBO,8BAmBE5N,UAAUvL,SAGV76B,KAAKuzB,UAAU2G,eACXmC,MAAM8G,KAAX,0BAAA94B,OAA0CrK,KAAK85B,SAA/C,KAAAzvB,OAA2DrK,KAAK+K,YAGhEmvB,GAAGkJ,qBAAqBrjC,KAAKC,MAAM,GAOlC0I,KAAGuqB,QAAQjzB,KAAK40B,SAAS8M,YAE1BA,SAAS2J,OAAOtrC,KAAKC,WAGhBomC,UAAU1E,YAInBxH,GAAGkJ,qBAAqBrjC,KAAKC,MAGzBA,KAAK46B,SACL6H,SAASsJ,MAAMhsC,KAAKC,WAInB8iC,OAAS,UAGT8D,MAAQ,UAGRL,MAAQ,UAGR2H,KAAO,UAGPhS,QAAU,KAGfwF,SAASgF,aAAa3mC,KAAKC,MAG3B0hC,SAASoG,WAAW/nC,KAAKC,MAGzBk6B,GAAG+Z,aAAal0C,KAAKC,MAGrBo3B,YACIp3B,KAAK40B,SAASC,UACd70B,KAAKy4B,OAAOC,WAAW0B,IAAI7G,UAC3BoG,QAAQS,KAAOp6B,KAAK46B,SAAW56B,KAAKgsC,SAIxC5U,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAW8B,QAAQjH,UAAWoG,QAAQa,SAAWx6B,KAAK46B,SAGvGxD,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWe,MAAOP,QAAQO,OAG3ErC,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWuX,QAASjwC,KAAKi7B,YAGrEvG,OAAQ,EAGb5J,WAAW,WACPuJ,aAAat0B,KAAK8B,EAAMA,EAAKg5B,MAAO,UACrC,GAGHX,GAAGga,SAASn0C,KAAKC,MAGbA,KAAK0vC,QACLxV,GAAGia,UAAUp0C,KAAKC,KAAMA,KAAK0vC,QAAQ,GAAOvf,MAAM,cAKlDnwB,KAAKy4B,OAAOuK,UACZtB,SAASwG,eAAenoC,KAAKC,OAKrCk0C,SAjHO,eAmHC7P,EAAQnF,KAAK/+B,IAAI,OAAQH,KAAKy4B,WAG9B/vB,KAAG+L,OAAOzU,KAAKy4B,OAAO2G,SAAW12B,KAAGqlB,MAAM/tB,KAAKy4B,OAAO2G,SACtDiF,GAAK,KAAAh6B,OAASrK,KAAKy4B,OAAO2G,QAI9BlyB,MAAM8B,KAAKhP,KAAK40B,SAASsN,QAAQlG,MAAQ,IAAIl6B,QAAQ,SAAA2iC,GACjDA,EAAO7O,aAAa,aAAcyO,KAKlCrkC,KAAKorC,QAAS,KACR/1B,EAASwiB,WAAW93B,KAAKC,KAAM,cAEhC0I,KAAGuqB,QAAQ5d,cAKV+pB,EAAS12B,KAAGqlB,MAAM/tB,KAAKy4B,OAAO2G,OAA6B,QAApBp/B,KAAKy4B,OAAO2G,MACnDtB,EAASoB,KAAK/+B,IAAI,aAAcH,KAAKy4B,QAE3CpjB,EAAOugB,aAAa,QAASkI,EAAO18B,QAAQ,UAAWg+B,MAK/DgV,aAjJO,SAiJMC,GACTjd,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWiX,cAAe0E,IAK/EF,UAvJO,SAuJGzE,qBAAwB5pC,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,KAEf9F,KAAK0vC,aAKf7U,MAAMjF,aAAa,SAAU8Z,GAI9Bhb,MACK30B,KAAKC,MAELksB,KAAK,kBAAMsnB,UAAU9D,KACrBvf,MAAM,SAAAhrB,SAECuqC,IAAWtb,EAAKsb,QAChBxV,GAAGka,aAAar0C,KAAKq0B,GAAM,GAGzBjvB,IAET+mB,KAAK,cAEEwjB,IAAWtb,EAAKsb,aACV,IAAIvwC,MAAM,oDAGvB+sB,KAAK,kBACFjsB,OAAO+hB,OAAOoS,EAAKQ,SAAS8a,OAAOp6B,MAAO,CACtCg/B,gBAAe,QAAAjqC,OAAUqlC,EAAV,MAEf6E,eAAgB,KAEpBra,GAAGka,aAAar0C,KAAKq0B,GAAM,GACpBsb,KAjCRtkB,QAAQsB,OAAO,IAAIvtB,MAAM,wBAuCxC80C,aAjMO,SAiMM50C,cAET+3B,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWmX,QAAS7vC,KAAK6vC,SAC1EzY,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWmD,OAAQ77B,KAAK67B,QACzEzE,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWoX,QAAS9vC,KAAK8vC,SAG1E5iC,MAAM8B,KAAKhP,KAAK40B,SAASsN,QAAQlG,MAAQ,IAAIl6B,QAAQ,SAAA8J,GACjDA,EAAOi7B,QAAUlS,EAAKkb,UAItBnnC,KAAGrJ,MAAMA,IAAyB,eAAfA,EAAM0L,MAK7BmvB,GAAGsa,eAAez0C,KAAKC,OAI3By0C,aAtNO,SAsNMp1C,mBACJ0wC,QAAU,CAAC,UAAW,WAAW73B,SAAS7Y,EAAM0L,MAGrD2pC,aAAa10C,KAAK20C,OAAO5E,cAGpB4E,OAAO5E,QAAUjlB,WAAW,WAE7BsM,YAAYsQ,EAAK9S,SAASC,UAAW6S,EAAKjP,OAAOC,WAAWqX,QAASrI,EAAKqI,SAG1E7V,GAAGsa,eAAez0C,KAAK2nC,IACxB1nC,KAAK+vC,QAAU,IAAM,IAI5ByE,eAvOO,SAuOQnd,OACHqK,EAAa1hC,KAAK40B,SAAlB8M,YAEJA,GAAY1hC,KAAKy4B,OAAOsV,aAAc,KAEhC6G,EAAmB50C,KAAKi7B,OAASj7B,KAAK60C,aAAe,IAAOC,KAAK1qB,WAGlEoqB,eAAerjB,QAAQkG,GAASr3B,KAAK+vC,SAAW/vC,KAAK67B,QAAU6F,EAASmF,SAAWnF,EAASsO,OAAS4E,OChPtH,SAAgBG,eAAe9jB,OACvB4c,EAAQ5c,EAEPvoB,KAAG+L,OAAOo5B,IAAWnlC,KAAGiqB,gBAAgB3yB,KAAK8sC,SAC3Ce,EAAU7tC,KAAK8sC,MAAfe,OAGFnlC,KAAG+L,OAAOo5B,KACRA,EAAU7tC,KAAKy4B,OAAfoV,4BAGQA,EAAM9pC,MAAM,KAAKuzB,IAAIhG,WAC9B0jB,EAAW,IAZiBC,EAAA,GAAAA,EAAA,WAc7BrgB,SAASnR,QAAQnO,MAAM4/B,cAA5B,GAAA7qC,OAA+C2qC,EAA/C,KAGIh1C,KAAK0pC,SAAW1pC,KAAKuzB,UAAU2G,GAAI,KAE7Bib,GADS,IACUH,GAAV,SACVna,MAAMvlB,MAAM8/B,UAAjB,eAAA/qC,OAA4C8qC,EAA5C,YAGG,CAAEH,QAAAA,EAASnH,MAAAA,OCvBhBwH,gCACU3Z,gCACHA,OAASA,OACT4Z,QAAU,UACVC,WAAa,UACbC,YAAc,UAEdC,UAAYz1C,KAAKy1C,UAAUpP,KAAKrmC,WAChC+pC,WAAa/pC,KAAK+pC,WAAW1D,KAAKrmC,WAClC01C,YAAc11C,KAAK01C,YAAYrP,KAAKrmC,WACpC21C,WAAa31C,KAAK21C,WAAWtP,KAAKrmC,6DAIjCX,OACEq8B,EAAW17B,KAAX07B,OACA9G,EAAa8G,EAAb9G,SACF3d,EAAO5X,EAAM44B,QAAU54B,EAAM44B,QAAU54B,EAAM+lC,MAC7CyB,EAAyB,YAAfxnC,EAAM0L,KAChB6qC,EAAS/O,GAAW5vB,IAASjX,KAAKs1C,aAGpCj2C,EAAMw2C,QAAUx2C,EAAMy2C,SAAWz2C,EAAM02C,SAAW12C,EAAM+4B,WAMvD1vB,KAAGsoB,OAAO/Z,OAYX4vB,EAAS,KAIH3O,EAAUt4B,SAASu4B,iBACrBzvB,KAAGuqB,QAAQiF,GAAU,KACbsX,EAAa9T,EAAOjD,OAAOwJ,UAA3BuN,YAGJtX,IAFatD,EAASgO,OAAlBC,MAEgBnL,QAAQQ,EAASsX,aAIrB,KAAhBnwC,EAAM+lC,OAAgB1N,QAAQQ,EAAS,4CAMxB,CAAC,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAGrFhgB,SAASjB,KACxB5X,EAAMJ,iBACNI,EAAMgmC,mBAGFpuB,QACC,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,GAEI2+B,IA5Cbla,EAAOC,YAAeD,EAAOsH,SAAW,IAAO/rB,EAAO,gBAiD7C,QACA,GAEI2+B,GACDla,EAAOsa,wBAIV,GAEDta,EAAOua,eAAe,eAGrB,GAEDva,EAAOwa,eAAe,eAGrB,GAEIN,IACDla,EAAOkL,OAASlL,EAAOkL,kBAI1B,GAEDlL,EAAOya,qBAGN,GAEDza,EAAO2G,oBAGN,GAED3G,EAAOgH,WAAWvW,oBAGjB,GAEIypB,GACDla,EAAO0a,4BAIV,GAED1a,EAAOwS,MAAQxS,EAAOwS,KAqBjB,KAATj3B,IAAgBykB,EAAOgH,WAAW2T,aAAe3a,EAAOgH,WAAW0J,QACnE1Q,EAAOgH,WAAWvW,cAIjBmpB,QAAUr+B,YAEVq+B,QAAU,yCAKZj2C,GACPqiC,SAASqI,WAAWhqC,KAAKC,KAAK07B,OAAQr8B,4CAK9Bq8B,EAAW17B,KAAX07B,OACA9G,EAAa8G,EAAb9G,SAER8G,EAAOT,OAAQ,EAGf7D,YAAYxC,EAASC,UAAW6G,EAAOjD,OAAOC,WAAWuX,SAAS,uCAG1D5wC,OACAq8B,EAAW17B,KAAX07B,OACA9G,EAAa8G,EAAb9G,YAER8f,aAAa10C,KAAKu1C,YAGC,YAAfl2C,EAAM0L,MAAsC,IAAhB1L,EAAM+lC,OAKnB,YAAf/lC,EAAM0L,YACDyqC,YAAcn2C,EAAMi3C,eAKnBxf,EAMJyf,EAAal3C,EAAMi3C,UAAYt2C,KAAKw1C,aAAe,MAGtC,UAAfn2C,EAAM0L,MAAqBwrC,EATrBzf,EAAY4E,EAAOjD,OAAOC,WAAWH,SAE3CnB,YADgBQ,YAAY73B,KAAK27B,EAAjB,IAAArxB,OAA6BysB,IACxBA,GAAW,QAgB/Bye,WAAazqB,WAAW,eACnBoN,EAAUt4B,SAASu4B,cAGpBvD,EAASC,UAAU2C,SAASU,IAIjCd,YAAYx3B,SAASu4B,cAAeuD,EAAOjD,OAAOC,WAAWH,UAAU,IACxE,0CAIApM,IAAermB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GACV41B,EAAW17B,KAAX07B,OAGJA,EAAOjD,OAAO2V,SAAS9tC,QACvBozB,eAAe3zB,KAAK27B,EAAQ78B,OAAQ,gBAAiBmB,KAAKy1C,UAAWtpB,GAAQ,GAIjFuH,eAAe3zB,KAAK27B,EAAQ97B,SAASyF,KAAM,QAASrF,KAAK+pC,WAAY5d,GAGrE6H,KAAKj0B,KAAK27B,EAAQ97B,SAASyF,KAAM,aAAcrF,KAAK21C,YAGpDjiB,eAAe3zB,KAAK27B,EAAQ97B,SAASyF,KAAM,qBAAsBrF,KAAK01C,YAAavpB,GAAQ,GAAO,2CAK1FuP,EAAW17B,KAAX07B,OACAjD,EAA6BiD,EAA7BjD,OAAQ7D,EAAqB8G,EAArB9G,SAAU+f,EAAWjZ,EAAXiZ,QAGrBlc,EAAO2V,SAAS9tC,QAAUm4B,EAAO2V,SAASlW,SAC3CpE,GAAG/zB,KAAK27B,EAAQ9G,EAASC,UAAW,gBAAiB70B,KAAKy1C,WAAW,GAIzE3hB,GAAG/zB,KACC27B,EACA9G,EAASC,UACT,2EACA,SAAAx1B,OACYqiC,EAAa9M,EAAb8M,SAGJA,GAA2B,oBAAfriC,EAAM0L,OAClB22B,EAASmF,SAAU,EACnBnF,EAASsO,OAAQ,OAMjBwG,EAAQ,EAFC,CAAC,aAAc,YAAa,aAAat+B,SAAS7Y,EAAM0L,QAKjEmvB,GAAGsa,eAAez0C,KAAK27B,GAAQ,GAE/B8a,EAAQ9a,EAAOT,MAAQ,IAAO,KAIlCyZ,aAAaC,EAAOjT,UAGpBiT,EAAOjT,SAAW5W,WAAW,kBAAMoP,GAAGsa,eAAez0C,KAAK27B,GAAQ,IAAQ8a,SA2B5EC,EAAgB,SAAAC,OAEbA,SACM3B,eAAeh1C,KAAK27B,OAGzBib,EAAO/hB,EAASC,UAAU2S,wBACxBG,EAAkBgP,EAAlBhP,MAAO4C,EAAWoM,EAAXpM,cAERwK,eAAeh1C,KAAK27B,EAApB,GAAArxB,OAA+Bs9B,EAA/B,KAAAt9B,OAAwCkgC,KAG7CqM,EAAU,WACZ/3C,OAAO61C,aAAaC,EAAOiC,SAC3BjC,EAAOiC,QAAU/3C,OAAOisB,WAAW2rB,EAAe,KAGtD3iB,GAAG/zB,KAAK27B,EAAQ9G,EAASC,UAAW,iCAAkC,SAAAx1B,SAClCq8B,EAAOgH,WAA/B92B,EADmEirC,EACnEjrC,OAAQyqC,EAD2DQ,EAC3DR,eAGX3a,EAAO0P,SAAWx/B,IAAWgpB,EAASC,eAIrCiiB,EAAyB,oBAAfz3C,EAAM0L,OAGK0rC,EAAcK,GAXkCC,EAWnE/B,SA1CM,SAACnH,EAAOmH,EAAS7oB,MAC1BuP,EAAOgO,aAIN99B,EAAS8vB,EAAO9G,SAASnR,QAAQob,WAC9B0L,iBAAUsD,EAAM9pC,MAAM,KAAKuzB,IAAIhG,WANE,oBAORoK,EAAOoR,MAAMe,MAAM9pC,MAAM,KAAKuzB,IAAIhG,WAA7D0lB,EAPmCC,EAAA,GAOvBC,EAPuBD,EAAA,GAS1CrrC,EAAO0J,MAAM6hC,SAAWhrB,EAAM,GAAA9hB,OAAOkgC,EAAS2M,EAAeF,EAA/B,MAAgD,KAC9EprC,EAAO0J,MAAM8hC,OAASjrB,EAAS,SAAW,MAmC1CkrB,CAd2EN,EAW1DlJ,MAGAmH,EAAS8B,GAGrBT,IACGS,EACAhjB,GAAG/zB,KAAK27B,EAAQ78B,OAAQ,SAAU+3C,GAElC7iB,IAAIh0B,KAAK27B,EAAQ78B,OAAQ,SAAU+3C,kDAQvClb,EAAW17B,KAAX07B,OACA9G,EAAa8G,EAAb9G,YAGRd,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,4BAA6B,SAAAx7B,UAASqiC,SAASoG,WAAW/nC,KAAK27B,EAAQr8B,KAGrGy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,2CAA4C,SAAAx7B,UACtEqiC,SAASwG,eAAenoC,KAAK27B,EAAQr8B,KAKzCy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,qBAAsB,WAChD5D,aAAarC,EAASkO,QAASpH,EAAO4b,UACtCrgB,aAAarC,EAASsN,QAAQK,MAAO7G,EAAO4b,YAIhDxjB,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,QAAS,WAE/Ba,EAAOd,SAAWc,EAAOsQ,SAAWtQ,EAAOjD,OAAOuV,YAElDtS,EAAO0G,YAKftO,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,kCAAmC,SAAAx7B,UAC7DqiC,SAASoF,eAAe/mC,KAAK27B,EAAQr8B,KAIzCy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,eAAgB,SAAAx7B,UAASqiC,SAASgF,aAAa3mC,KAAK27B,EAAQr8B,KAG1Fy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,8CAA+C,SAAAx7B,UACzE66B,GAAG+Z,aAAal0C,KAAK27B,EAAQr8B,KAIjCy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,iCAAkC,SAAAx7B,UAAS66B,GAAGua,aAAa10C,KAAK27B,EAAQr8B,KAItGy0B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,UAAW,WAChCa,EAAOkU,KAKRlU,EAAOkU,IAAIrQ,UAAY7D,EAAOkU,IAAI2H,aAElC7b,EAAOkU,IAAI4H,eAAetrB,KAAK,kBAAMwP,EAAOkU,IAAI5T,SAAQ7L,MAAM,kBAAMuL,EAAOM,WAK/EN,EAAOnI,UAAU2G,IAAMwB,EAAOjD,OAAOqV,cAAgBpS,EAAO+b,QAAS,KAE/Dh0B,EAAUoU,WAAW93B,KAAK27B,EAAhB,IAAArxB,OAA4BqxB,EAAOjD,OAAOC,WAAWmB,YAGhEnxB,KAAGuqB,QAAQxP,UAKhBqQ,GAAG/zB,KAAK27B,EAAQ9G,EAASC,UAAW,QAAS,SAAAx1B,IACzB,CAACu1B,EAASC,UAAWpR,GAGxBvL,SAAS7Y,EAAMuM,SAAY6X,EAAQ+T,SAASn4B,EAAMuM,WAK3D8vB,EAAOT,OAASS,EAAOjD,OAAOsV,eAI9BrS,EAAOgc,OACP71C,EAAK87B,MAAMt+B,EAAOq8B,EAAO0G,QAAS,WAClCvgC,EAAK87B,MAAMt+B,EAAOq8B,EAAOM,KAAM,SAE/Bn6B,EAAK87B,MAAMt+B,EAAOq8B,EAAOsa,WAAY,YAM7Cta,EAAOnI,UAAU2G,IAAMwB,EAAOjD,OAAOwV,oBACrCna,GAAG/zB,KACC27B,EACA9G,EAASnR,QACT,cACA,SAAApkB,GACIA,EAAMJ,mBAEV,GAKR60B,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,eAAgB,WAE1Ca,EAAO8D,QAAQz8B,IAAI,CACf+/B,OAAQpH,EAAOoH,OACf8D,MAAOlL,EAAOkL,UAKtB9S,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,aAAc,WAExC6G,SAAS8G,cAAczoC,KAAK27B,EAAQ,SAGpCA,EAAO8D,QAAQz8B,IAAI,CAAEwjC,MAAO7K,EAAO6K,UAIvCzS,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,gBAAiB,SAAAx7B,GAE3CqiC,SAAS8G,cAAczoC,KAAK27B,EAAQ,UAAW,KAAMr8B,EAAMK,OAAOw8B,WAItEpI,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO,sBAAuB,WACjD6G,SAASmJ,gBAAgB9qC,KAAK27B,SAK5Bic,EAAcjc,EAAOjD,OAAO7E,OAAOvpB,OAAO,CAAC,QAAS,YAAY/G,KAAK,KAE3EwwB,GAAG/zB,KAAK27B,EAAQA,EAAOb,MAAO8c,EAAa,SAAAt4C,SACjBA,EAAhBK,OAAAA,OAD0C,IAAAk4C,EACjC,GADiCA,EAI7B,UAAfv4C,EAAM0L,OACNrL,EAASg8B,EAAOb,MAAMn6B,OAG1B2zB,aAAat0B,KAAK27B,EAAQ9G,EAASC,UAAWx1B,EAAM0L,MAAM,EAAMrL,mCAKlEL,EAAOw4C,EAAgBC,OACjBpc,EAAW17B,KAAX07B,OACFqc,EAAgBrc,EAAOjD,OAAO2N,UAAU0R,GAE1CE,GAAW,EADUtvC,KAAGmqB,SAASklB,KAKjCC,EAAWD,EAAch4C,KAAK27B,EAAQr8B,IAItC24C,GAAYtvC,KAAGmqB,SAASglB,IACxBA,EAAe93C,KAAK27B,EAAQr8B,gCAK/B4zB,EAASloB,EAAM8sC,EAAgBC,cAAkBnkB,IAAgB7tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,GAC1D41B,EAAW17B,KAAX07B,OACFqc,EAAgBrc,EAAOjD,OAAO2N,UAAU0R,GACxCG,EAAmBvvC,KAAGmqB,SAASklB,GAErCjkB,GAAG/zB,KACC27B,EACAzI,EACAloB,EACA,SAAA1L,UAAS+0B,EAAKuJ,MAAMt+B,EAAOw4C,EAAgBC,IAC3CnkB,IAAYskB,iDAMRvc,EAAW17B,KAAX07B,OACA9G,EAAa8G,EAAb9G,SAGFsjB,EAAahf,QAAQC,KAAO,SAAW,WAGzCvE,EAASsN,QAAQlG,MACjB9uB,MAAM8B,KAAK4lB,EAASsN,QAAQlG,MAAMl6B,QAAQ,SAAA2iC,GACtC9P,EAAK0R,KAAK5B,EAAQ,QAAS/I,EAAOsa,WAAY,eAKjD3P,KAAKzR,EAASsN,QAAQE,QAAS,QAAS1G,EAAO0G,QAAS,gBAGxDiE,KAAKzR,EAASsN,QAAQG,OAAQ,QAAS3G,EAAO2G,OAAQ,eAGtDgE,KAAKzR,EAASsN,QAAQI,YAAa,QAAS5G,EAAOya,QAAS,oBAG5D9P,KACDzR,EAASsN,QAAQK,KACjB,QACA,WACI7G,EAAOkL,OAASlL,EAAOkL,OAE3B,aAICP,KAAKzR,EAASsN,QAAQO,SAAU,QAAS,kBAAM/G,EAAO0a,wBAGtD/P,KACDzR,EAASsN,QAAQ4I,SACjB,QACA,WACIzW,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,aAE5C,iBAICwL,KACDzR,EAASsN,QAAQQ,WACjB,QACA,WACIhH,EAAOgH,WAAWvW,UAEtB,mBAICka,KACDzR,EAASsN,QAAQ9H,IACjB,QACA,WACIsB,EAAOtB,IAAM,UAEjB,YAICiM,KAAKzR,EAASsN,QAAQ1H,QAAS,QAASkB,EAAOlB,QAAS,gBAGxD6L,KAAKzR,EAASsN,QAAQM,SAAU,QAAS,SAAAnjC,GAE1CA,EAAMgmC,kBAEN3D,SAASqI,WAAWhqC,KAAK27B,EAAQr8B,UAMhCgnC,KACDzR,EAASsN,QAAQM,SACjB,QACA,SAAAnjC,OACU4X,EAAO5X,EAAM+lC,MAGd,CAAC,GAAI,IAAIltB,SAASjB,KAKV,KAATA,GAMJ5X,EAAMJ,iBAGNI,EAAMgmC,kBAGN3D,SAASqI,WAAWhqC,KAAK27B,EAAQr8B,IAX7BqiC,SAASkE,mBAAmB7lC,KAAK27B,EAAQ,MAAM,KAavD,MACA,QAIC2K,KAAKzR,EAAS4N,SAASyB,KAAM,UAAW,SAAA5kC,GACrB,KAAhBA,EAAM+lC,OACN1D,SAASqI,WAAWhqC,KAAK27B,EAAQr8B,UAKpCgnC,KAAKzR,EAASgO,OAAOC,KAAM,sBAAuB,SAAAxjC,OAC7Cs3C,EAAO/hB,EAAS+N,SAAS6E,wBACzBL,EAAW,IAAMwP,EAAKhP,OAAUtoC,EAAMuoC,MAAQ+O,EAAK9O,MACzDxoC,EAAM84C,cAAcviB,aAAa,aAAcuR,UAI9Cd,KAAKzR,EAASgO,OAAOC,KAAM,sDAAuD,SAAAxjC,OAC7EwjC,EAAOxjC,EAAM84C,cACblhC,EAAO5X,EAAM44B,QAAU54B,EAAM44B,QAAU54B,EAAM+lC,UAG/C18B,KAAGyqB,cAAc9zB,IAAoB,KAAT4X,GAAwB,KAATA,GAK/CykB,EAAOmZ,aAAeC,KAAK1qB,UAGrB4R,EAAO6G,EAAKuV,aAVA,kBAaZn3C,EAAO,CAAC,UAAW,WAAY,SAASiX,SAAS7Y,EAAM0L,MAGzDixB,GAAQ/6B,GACR4hC,EAAK1L,gBAjBS,kBAkBduE,EAAOM,SACC/6B,GAAQy6B,EAAOmU,UACvBhN,EAAKjN,aApBS,iBAoBe,IAC7B8F,EAAOyG,YAOXjJ,QAAQO,MAAO,KACTmJ,EAAShL,YAAY73B,KAAK27B,EAAQ,uBACxCxuB,MAAM8B,KAAK4zB,GAAQ9gC,QAAQ,SAAAmvB,UAAS0D,EAAK0R,KAAKpV,EAAOinB,EAAY,SAAA74C,UAAS25B,QAAQ35B,EAAMuM,iBAIvFy6B,KACDzR,EAASgO,OAAOC,KAChBqV,EACA,SAAA74C,OACUwjC,EAAOxjC,EAAM84C,cAGfE,EAASxV,EAAKtH,aAAa,cAE3B7yB,KAAGqlB,MAAMsqB,KACTA,EAASxV,EAAK9hC,OAGlB8hC,EAAK1L,gBAAgB,cAErBuE,EAAOC,YAAe0c,EAASxV,EAAKlwB,IAAO+oB,EAAOsH,UAEtD,aAICqD,KAAKzR,EAAS+N,SAAU,kCAAmC,SAAAtjC,UAC5DqiC,SAAS2F,kBAAkBtnC,KAAK27B,EAAQr8B,UAKvCgnC,KAAKzR,EAAS+N,SAAU,sBAAuB,SAAAtjC,OACxC+wC,EAAsB1U,EAAtB0U,kBAEJA,GAAqBA,EAAkBkI,QACvClI,EAAkBmI,UAAUl5C,UAK/BgnC,KAAKzR,EAAS+N,SAAU,mBAAoB,eACrCyN,EAAsB1U,EAAtB0U,kBAEJA,GAAqBA,EAAkBkI,QACvClI,EAAkBoI,SAAQ,GAAO,UAKpCnS,KAAKzR,EAAS+N,SAAU,uBAAwB,SAAAtjC,OACzC+wC,EAAsB1U,EAAtB0U,kBAEJA,GAAqBA,EAAkBkI,QACvClI,EAAkBqI,eAAep5C,UAIpCgnC,KAAKzR,EAAS+N,SAAU,mBAAoB,SAAAtjC,OACrC+wC,EAAsB1U,EAAtB0U,kBAEJA,GAAqBA,EAAkBkI,QACvClI,EAAkBsI,aAAar5C,KAKnC65B,QAAQI,UACRpsB,MAAM8B,KAAK4oB,YAAY73B,KAAK27B,EAAQ,wBAAwB55B,QAAQ,SAAAmxB,GAChE0B,EAAK0R,KAAKpT,EAAS,QAAS,SAAA5zB,UAASqiC,SAASkD,gBAAgB7kC,KAAK27B,EAAQr8B,EAAMuM,YAMrF8vB,EAAOjD,OAAOmV,eAAiBllC,KAAGuqB,QAAQ2B,EAASrf,QAAQytB,gBACtDqD,KAAKzR,EAASrf,QAAQomB,YAAa,QAAS,WAElB,IAAvBD,EAAOC,cAIXD,EAAOjD,OAAOuP,YAActM,EAAOjD,OAAOuP,WAE1CtG,SAASoG,WAAW/nC,KAAK27B,WAK5B2K,KACDzR,EAASgO,OAAOE,OAChBoV,EACA,SAAA74C,GACIq8B,EAAOoH,OAASzjC,EAAMuM,OAAO7K,OAEjC,eAICslC,KAAKzR,EAAS8M,SAAU,wBAAyB,SAAAriC,GAClDu1B,EAAS8M,SAASsO,OAAStU,EAAOT,OAAwB,eAAf57B,EAAM0L,YAIhDs7B,KAAKzR,EAAS8M,SAAU,oDAAqD,SAAAriC,GAC9Eu1B,EAAS8M,SAASmF,QAAU,CAAC,YAAa,cAAc3uB,SAAS7Y,EAAM0L,aAItEs7B,KAAKzR,EAAS8M,SAAU,UAAW,eAC5BjJ,EAA6BiD,EAA7BjD,OAAQ7D,EAAqB8G,EAArB9G,SAAU+f,EAAWjZ,EAAXiZ,OAG1Bvd,YAAYxC,EAAS8M,SAAUjJ,EAAOC,WAAWyX,cAAc,GAG/DjW,GAAGsa,eAAez0C,KAAK27B,GAAQ,GAG/B5Q,WAAW,WACPsM,YAAYxC,EAAS8M,SAAUjJ,EAAOC,WAAWyX,cAAc,IAChE,OAGGqG,EAAQ7hB,EAAKsG,MAAQ,IAAO,IAGlCyZ,aAAaC,EAAOjT,UAGpBiT,EAAOjT,SAAW5W,WAAW,kBAAMoP,GAAGsa,eAAez0C,KAAK27B,GAAQ,IAAQ8a,UAIzEnQ,KACDzR,EAASgO,OAAOE,OAChB,QACA,SAAAzjC,OAGUiiC,EAAWjiC,EAAMs5C,mDAGR,CAACt5C,EAAMu5C,QAASv5C,EAAMw5C,QAAQvhB,IAAI,SAAAv2B,UAAUugC,GAAYvgC,EAAQA,OAAxEuX,EANFwgC,EAAA,GAMKvgC,EANLugC,EAAA,GASCC,EAAYlxC,KAAK0rC,KAAK1rC,KAAK+0B,IAAItkB,GAAKzQ,KAAK+0B,IAAIrkB,GAAKD,EAAIC,GAG5DmjB,EAAOua,eAAe8C,EAAY,QAG1BjW,EAAWpH,EAAOb,MAAlBiI,QACW,IAAdiW,GAAmBjW,EAAS,IAAsB,IAAfiW,GAAoBjW,EAAS,IACjEzjC,EAAMJ,kBAGd,UACA,YCt2BRkK,KAAKV,UAAwBW,EAC7B4vC,OAASlxC,SAAS1H,UAClB64C,OAAS,wBACTnhC,OAAO,OAGXA,UAAQkhC,QAAUnwC,cAA6BM,KAAG6vC,OAAQlhC,OAAM,CAC9DlU,cAAc,EACdzD,IAAK,WACH,IACE,OAAQ,GAAKH,MAAM2Z,MAAMs/B,QAAQ,GACjC,MAAO75C,GACP,MAAO,OCJbqJ,UAAyB,QAAS,EAAG,SAAU6D,EAASoL,EAAOwhC,EAAQ/9B,GACrE,MAAO,CAGL,SAAeP,GACb,IAAIvR,EAAIiD,EAAQtM,MACZuH,EAAe5H,MAAVib,OAAsBjb,EAAYib,EAAOlD,GAClD,YAAc/X,IAAP4H,EAAmBA,EAAGxH,KAAK6a,EAAQvR,GAAK,IAAI6K,OAAO0G,GAAQlD,GAAOhV,OAAO2G,KAIlF,SAAUuR,GACR,IAAItJ,EAAM6J,EAAgB+9B,EAAQt+B,EAAQ5a,MAC1C,GAAIsR,EAAIrQ,KAAM,OAAOqQ,EAAIvQ,MACzB,IAAIqa,EAAK5R,UAASoR,GACd5R,EAAItG,OAAO1C,MACf,IAAKob,EAAG9a,OAAQ,OAAOib,oBAAWH,EAAIpS,GACtC,IAAIgf,EAAc5M,EAAGvC,QACrBuC,EAAG3B,UAAY,EAIf,IAHA,IAEIvK,EAFAgT,EAAI,GACJ8G,EAAI,EAEgC,QAAhC9Z,EAASqM,oBAAWH,EAAIpS,KAAc,CAC5C,IAAImwC,EAAWz2C,OAAOwM,EAAO,IAC7BgT,EAAE8G,GAAKmwB,EACU,KAAbA,IAAiB/9B,EAAG3B,UAAY2N,oBAAmBpe,EAAG4G,UAASwL,EAAG3B,WAAYuO,IAClFgB,IAEF,OAAa,IAANA,EAAU,KAAO9G,wDChC1Bva,EAAAC,QAII,WAMR,IAAIwxC,EAAU,aACVC,EAAgB,GAChBC,EAAoB,GACpBC,EAAsB,GAmD1B,SAASC,EAAQC,EAAUC,GAEzB,GAAKD,EAAL,CAEA,IAAIvyB,EAAIqyB,EAAoBE,GAM5B,GAHAH,EAAkBG,GAAYC,EAGzBxyB,EAGL,KAAOA,EAAE/kB,QACP+kB,EAAE,GAAGuyB,EAAUC,GACfxyB,EAAE5D,OAAO,EAAG,IAUhB,SAASq2B,EAAiBvwB,EAAMwwB,GAE1BxwB,EAAKrpB,OAAMqpB,EAAO,CAACywB,QAASzwB,IAG5BwwB,EAAaz3C,QAASinB,EAAK1oB,OAAS04C,GAASQ,IAC3CxwB,EAAKywB,SAAWT,GAAShwB,GASjC,SAAS0wB,EAAS5c,EAAM6c,EAAY3wB,EAAM4wB,GACxC,IAKIC,EACA76C,EANAuF,EAAM/E,SACNs6C,EAAQ9wB,EAAK8wB,MACbC,GAAY/wB,EAAKgxB,YAAc,GAAK,EACpCC,EAAmBjxB,EAAKkxB,QAAUlB,EAClCmB,EAAerd,EAAK97B,QAAQ,cAAe,IAI/C44C,EAAWA,GAAY,EAEnB,iBAAiBz0C,KAAK23B,IACxB+c,GAAQ,GAGR76C,EAAIuF,EAAII,cAAc,SACpBmsC,IAAM,aACR9xC,EAAEgF,KAAOm2C,GACA,+BAA+Bh1C,KAAK23B,IAE7C99B,EAAIuF,EAAII,cAAc,QACpByQ,IAAM+kC,IAGRn7C,EAAIuF,EAAII,cAAc,WACpByQ,IAAM0nB,EACR99B,EAAE86C,WAAkBv6C,IAAVu6C,GAA6BA,GAGzC96C,EAAEw0C,OAASx0C,EAAEy0C,QAAUz0C,EAAEo7C,aAAe,SAAUC,GAChD,IAAIvrC,EAASurC,EAAG1vC,KAAK,GAIrB,GAAIkvC,GAAS,cAAe76C,EAC1B,IACOA,EAAEs7C,MAAMC,QAAQx4C,SAAQ+M,EAAS,KACtC,MAAOoJ,GAGO,IAAVA,EAAErB,OAAY/H,EAAS,KAK/B,GAAc,KAAVA,IAEF8qC,GAAY,GAGGG,EACb,OAAOL,EAAS5c,EAAM6c,EAAY3wB,EAAM4wB,GAK5CD,EAAW7c,EAAMhuB,EAAQurC,EAAGv7C,oBAII,IAA9Bm7C,EAAiBnd,EAAM99B,IAAcuF,EAAIK,KAAKC,YAAY7F,GA+ChE,SAASw7C,EAAOC,EAAOC,EAAMjgC,GAC3B,IAAI4+B,EACArwB,EASJ,GANI0xB,GAAQA,EAAKtmC,OAAMilC,EAAWqB,GAGlC1xB,GAAQqwB,EAAW5+B,EAAOigC,IAAS,GAG/BrB,EAAU,CACZ,GAAIA,KAAYJ,EACd,KAAM,SAENA,EAAcI,IAAY,GArDhC,SAAmBoB,EAAOd,EAAY3wB,GAIpC,IAGI7hB,EACArF,EAJA64C,GAFJF,EAAQA,EAAMp4C,KAAOo4C,EAAQ,CAACA,IAEP14C,OACnBmW,EAAIyiC,EACJrB,EAAgB,GAqBpB,IAhBAnyC,EAAK,SAAS21B,EAAMhuB,EAAQhQ,GAM1B,GAJc,KAAVgQ,GAAewqC,EAAcj3C,KAAKy6B,GAIxB,KAAVhuB,EAAe,CACjB,IAAIhQ,EACC,OADiBw6C,EAAcj3C,KAAKy6B,KAI3C6d,GACiBhB,EAAWL,IAIzBx3C,EAAE,EAAGA,EAAIoW,EAAGpW,IAAK43C,EAASe,EAAM34C,GAAIqF,EAAI6hB,GA+B7C4xB,CAAUH,EAAO,SAAUnB,GAEzBC,EAAiBvwB,EAAMswB,GAGvBF,EAAQC,EAAUC,IACjBtwB,GAiDL,OAxCAwxB,EAAOlmB,MAAQ,SAAeumB,EAAM7xB,GAOlC,OAxOF,SAAmB8xB,EAAWnB,GAE5BmB,EAAYA,EAAUz4C,KAAOy4C,EAAY,CAACA,GAE1C,IAGI3zC,EACAkyC,EACArpB,EALAwpB,EAAe,GACf13C,EAAIg5C,EAAU/4C,OACd44C,EAAa74C,EAejB,IARAqF,EAAK,SAAUkyC,EAAUC,GACnBA,EAAcv3C,QAAQy3C,EAAan3C,KAAKg3C,KAE5CsB,GACiBhB,EAAWH,IAIvB13C,KACLu3C,EAAWyB,EAAUh5C,IAGrBkuB,EAAIkpB,EAAkBG,IAEpBlyC,EAAGkyC,EAAUrpB,IAKXmpB,EAAoBE,GAAYF,EAAoBE,IAAa,IACnEh3C,KAAK8E,GAkMT4zC,CAAUF,EAAM,SAAUrB,GAExBD,EAAiBvwB,EAAMwwB,KAGlBgB,GAQTA,EAAO35C,KAAO,SAAcw4C,GAC1BD,EAAQC,EAAU,KAOpBmB,EAAO1L,MAAQ,WACbmK,EAAgB,GAChBC,EAAoB,GACpBC,EAAsB,IAQxBqB,EAAOQ,UAAY,SAAmB3B,GACpC,OAAOA,KAAYJ,GAKduB,EA9RcS,KCEN,SAASC,WAAW92C,UACxB,IAAI4mB,QAAQ,SAACY,EAASU,GACzBkuB,WAAOp2C,EAAK,CACRq1C,QAAS7tB,EACTtrB,MAAOgsB,MCQnB,SAAS6uB,QAAQ/2C,MACTkE,KAAGqlB,MAAMvpB,UACF,QAGPkE,KAAGsoB,OAAOM,OAAO9sB,WACVA,SAIJA,EAAImV,MADG,mCACYzF,OAAOsnC,GAAKh3C,EAI1C,SAASi3C,oBAAoBzf,GACrBA,IAASh8B,KAAK8sC,MAAM4O,iBACf5O,MAAM4O,WAAY,GAEvB17C,KAAK66B,MAAMgB,SAAWG,SACjBnB,MAAMgB,QAAUG,EACrB3H,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAOmB,EAAO,OAAS,UAI5D,IAAMgD,MAAQ,CACV+M,MADU,sBAGN3U,YAAYp3B,KAAK40B,SAASnR,QAASzjB,KAAKy4B,OAAOC,WAAWoU,OAAO,GAGjEiI,eAAeh1C,KAAKC,MAGf0I,KAAGoB,OAAOjL,OAAO88C,OASlB3c,MAAMtK,MAAM30B,KAAKC,MARjBs7C,WAAWt7C,KAAKy4B,OAAO0S,KAAKnM,MAAMsQ,KAC7BpjB,KAAK,WACF8S,MAAMtK,MAAM30B,KAAK8B,KAEpBsuB,MAAM,SAAAzvB,GACHmB,EAAKw6B,MAAM8G,KAAK,2BAA4BziC,MAQ5Dg0B,MAvBU,sBAwBAgH,EAAS17B,KACTy4B,EAASiD,EAAOjD,OAAOuG,MAGvB1/B,EAASwsC,eACXrQ,OACI,GACA,CACIyS,KAAMxS,EAAOjD,OAAOyV,KAAK9B,OACzBsB,SAAUhS,EAAOgS,SACjB9G,MAAOlL,EAAOkL,MACdgV,QAAS,QACT7hB,aAAc/5B,KAAKy4B,OAAOiK,WAAW4L,WAEzC7V,IAKJztB,EAAS0wB,EAAOb,MAAMU,aAAa,OAGnC7yB,KAAGqlB,MAAM/iB,KACTA,EAAS0wB,EAAOb,MAAMU,aAAaG,EAAOjD,OAAO30B,WAAWgpC,MAAM7iC,SAGhEA,EAAKsxC,QAAQvwC,GAGbqK,EAAStQ,cAAc,UACvByQ,EAAMsoB,OAAOpC,EAAOjD,OAAO0S,KAAKnM,MAAM3pB,OAAQpL,EAAI3K,GACxD+V,EAAOugB,aAAa,MAAOpgB,GAC3BH,EAAOugB,aAAa,kBAAmB,IACvCvgB,EAAOugB,aAAa,oBAAqB,IACzCvgB,EAAOugB,aAAa,QAAS,gBAMvBnS,EAAU1e,cAAc,MAAO,CAAE2qC,OAHpBhU,EAAXgU,OAGuC1Y,MAAO0E,EAAOjD,OAAOC,WAAW+W,iBAC/EhsB,EAAQxe,YAAYoQ,GACpBqmB,EAAOb,MAAQxE,eAAe5S,EAASiY,EAAOb,OAG9CiF,MAAMhC,OAAOpC,EAAOjD,OAAO0S,KAAKnM,MAAM/E,IAAKhwB,GAAK,QAAQiiB,KAAK,SAAAiU,OACrDz3B,KAAGqlB,MAAMoS,QAKP37B,EAAM,IAAIN,IAAIi8B,EAAS,GAAG0b,iBAGhCr3C,EAAIL,SAAJ,GAAAkG,OAAkB7F,EAAIL,SAASJ,MAAM,KAAK,GAA1C,QAGAm2B,GAAGia,UAAUp0C,KAAK27B,EAAQl3B,EAAIJ,MAAM+rB,MAAM,iBAK9CuL,EAAOoR,MAAQ,IAAIjuC,OAAO88C,MAAMG,OAAOzmC,EAAQ,CAC3Cs4B,UAAWjS,EAAOjD,OAAOkV,UACzB/G,MAAOlL,EAAOkL,QAGlBlL,EAAOb,MAAMgB,QAAS,EACtBH,EAAOb,MAAMc,YAAc,EAGvBD,EAAOnI,UAAU2G,IACjBwB,EAAOoR,MAAMiP,mBAIjBrgB,EAAOb,MAAMmB,KAAO,kBAChByf,oBAAoB17C,KAAK27B,GAAQ,GAC1BA,EAAOoR,MAAM9Q,QAGxBN,EAAOb,MAAMsH,MAAQ,kBACjBsZ,oBAAoB17C,KAAK27B,GAAQ,GAC1BA,EAAOoR,MAAM3K,SAGxBzG,EAAOb,MAAMmhB,KAAO,WAChBtgB,EAAOyG,QACPzG,EAAOC,YAAc,OAInBA,EAAgBD,EAAOb,MAAvBc,YACN17B,OAAOC,eAAew7B,EAAOb,MAAO,cAAe,CAC/C16B,IAD+C,kBAEpCw7B,GAEX54B,IAJ+C,SAI3Cq+B,OAIQ0L,EAAiCpR,EAAjCoR,MAAOjS,EAA0Ba,EAA1Bb,MAAOgB,EAAmBH,EAAnBG,OAAQiH,EAAWpH,EAAXoH,OACxBmZ,EAAepgB,IAAWiR,EAAM4O,UAGtC7gB,EAAMoN,SAAU,EAChB5T,aAAat0B,KAAK27B,EAAQb,EAAO,WAGjCzP,QAAQY,QAAQiwB,GAAgBnP,EAAMoP,UAAU,IAE3ChwB,KAAK,kBAAM4gB,EAAMqP,eAAe/a,KAEhClV,KAAK,kBAAM+vB,GAAgBnP,EAAM3K,UAEjCjW,KAAK,kBAAM+vB,GAAgBnP,EAAMoP,UAAUpZ,KAC3C3S,MAAM,qBAOfoW,EAAQ7K,EAAOjD,OAAO8N,MAAM4H,SAChCluC,OAAOC,eAAew7B,EAAOb,MAAO,eAAgB,CAChD16B,IADgD,kBAErComC,GAEXxjC,IAJgD,SAI5CkuB,GACAyK,EAAOoR,MACFsP,gBAAgBnrB,GAChB/E,KAAK,WACFqa,EAAQtV,EACRoD,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,gBAE3C1K,MAAM,SAAAzvB,GAEgB,UAAfA,EAAMqB,MACN2/B,SAAS+H,aAAa1pC,KAAK27B,EAAQ,aAOjDoH,EAAWpH,EAAOjD,OAAlBqK,OACN7iC,OAAOC,eAAew7B,EAAOb,MAAO,SAAU,CAC1C16B,IAD0C,kBAE/B2iC,GAEX//B,IAJ0C,SAItCkuB,GACAyK,EAAOoR,MAAMoP,UAAUjrB,GAAO/E,KAAK,WAC/B4W,EAAS7R,EACToD,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,yBAM9C+L,EAAUlL,EAAOjD,OAAjBmO,MACN3mC,OAAOC,eAAew7B,EAAOb,MAAO,QAAS,CACzC16B,IADyC,kBAE9BymC,GAEX7jC,IAJyC,SAIrCkuB,OACM9E,IAASzjB,KAAGkqB,QAAQ3B,IAASA,EAEnCyK,EAAOoR,MAAMoP,UAAU/vB,EAAS,EAAIuP,EAAOjD,OAAOqK,QAAQ5W,KAAK,WAC3D0a,EAAQza,EACRkI,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,yBAqBhDwhB,EAfEnO,EAASxS,EAAOjD,OAAhByV,KACNjuC,OAAOC,eAAew7B,EAAOb,MAAO,OAAQ,CACxC16B,IADwC,kBAE7B+tC,GAEXnrC,IAJwC,SAIpCkuB,OACM9E,EAASzjB,KAAGkqB,QAAQ3B,GAASA,EAAQyK,EAAOjD,OAAOyV,KAAK9B,OAE9D1Q,EAAOoR,MAAMwP,QAAQnwB,GAAQD,KAAK,WAC9BgiB,EAAO/hB,OAOnBuP,EAAOoR,MACFyP,cACArwB,KAAK,SAAAnrB,GACFs7C,EAAat7C,EACb2gC,SAASmJ,gBAAgB9qC,KAAK27B,KAEjCvL,MAAM,SAAAzvB,GACH0zB,EAAKiI,MAAM8G,KAAKziC,KAGxBT,OAAOC,eAAew7B,EAAOb,MAAO,aAAc,CAC9C16B,IAD8C,kBAEnCk8C,KAKfp8C,OAAOC,eAAew7B,EAAOb,MAAO,QAAS,CACzC16B,IADyC,kBAE9Bu7B,EAAOC,cAAgBD,EAAOsH,YAK7C5X,QAAQoF,IAAI,CAACkL,EAAOoR,MAAM0P,gBAAiB9gB,EAAOoR,MAAM2P,mBAAmBvwB,KAAK,SAAAwwB,wBACpDA,EADkE,GACnF/U,EADmFgV,EAAA,GAC5EpS,EAD4EoS,EAAA,GAE1FjhB,EAAOoR,MAAMe,MAAb,GAAAxjC,OAAwBs9B,EAAxB,KAAAt9B,OAAiCkgC,GACjCwK,eAAeh1C,KAAKq0B,EAAMsH,EAAOoR,MAAMe,SAI3CnS,EAAOoR,MAAM8P,aAAalhB,EAAOjD,OAAOkV,WAAWzhB,KAAK,SAAA2wB,GACpDnhB,EAAOjD,OAAOkV,UAAYkP,IAI9BnhB,EAAOoR,MAAMgQ,gBAAgB5wB,KAAK,SAAAkT,GAC9B1D,EAAOjD,OAAO2G,MAAQA,EACtBlF,GAAGga,SAASn0C,KAAKq0B,KAIrBsH,EAAOoR,MAAMiQ,iBAAiB7wB,KAAK,SAAAnrB,GAC/B46B,EAAc56B,EACdszB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,gBAI5Ca,EAAOoR,MAAMkQ,cAAc9wB,KAAK,SAAAnrB,GAC5B26B,EAAOb,MAAMmI,SAAWjiC,EACxBszB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,oBAI5Ca,EAAOoR,MAAMmQ,gBAAgB/wB,KAAK,SAAAid,GAC9BzN,EAAOb,MAAME,WAAaoO,EAC1B1G,SAASsJ,MAAMhsC,KAAK27B,KAGxBA,EAAOoR,MAAMhZ,GAAG,YAAa,SAAA2B,WAAG2X,KACtB8P,QADsC,IAAAC,EAAT,GAASA,GAClB7lB,IAAI,SAAAlE,UAAOqL,UAAUrL,EAAIyC,QACnD4M,SAASgK,WAAW1sC,KAAK27B,EAAQwhB,KAGrCxhB,EAAOoR,MAAMhZ,GAAG,SAAU,YAEtB4H,EAAOoR,MAAMsQ,YAAYlxB,KAAK,SAAA2P,GAC1B4f,oBAAoB17C,KAAK27B,GAASG,GAC7BA,GACDxH,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,aAI5CnyB,KAAGuqB,QAAQyI,EAAOoR,MAAM7Z,UAAYyI,EAAOnI,UAAU2G,KACvCwB,EAAOoR,MAAM7Z,QAIrB2C,aAAa,YAAa,KAIxC8F,EAAOoR,MAAMhZ,GAAG,OAAQ,WACpB2nB,oBAAoB17C,KAAK27B,GAAQ,GACjCrH,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,aAG5Ca,EAAOoR,MAAMhZ,GAAG,QAAS,WACrB2nB,oBAAoB17C,KAAK27B,GAAQ,KAGrCA,EAAOoR,MAAMhZ,GAAG,aAAc,SAAAhQ,GAC1B4X,EAAOb,MAAMoN,SAAU,EACvBtM,EAAc7X,EAAKu5B,QACnBhpB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,gBAG5Ca,EAAOoR,MAAMhZ,GAAG,WAAY,SAAAhQ,GACxB4X,EAAOb,MAAMqM,SAAWpjB,EAAKqjB,QAC7B9S,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,YAGL,IAA/BzjB,SAAS0M,EAAKqjB,QAAS,KACvB9S,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,kBAK5Ca,EAAOoR,MAAMkQ,cAAc9wB,KAAK,SAAAnrB,GACxBA,IAAU26B,EAAOb,MAAMmI,WACvBtH,EAAOb,MAAMmI,SAAWjiC,EACxBszB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,uBAKpDa,EAAOoR,MAAMhZ,GAAG,SAAU,WACtB4H,EAAOb,MAAMoN,SAAU,EACvB5T,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,YAG5Ca,EAAOoR,MAAMhZ,GAAG,QAAS,WACrB4H,EAAOb,MAAMgB,QAAS,EACtBxH,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAG5Ca,EAAOoR,MAAMhZ,GAAG,QAAS,SAAAp0B,GACrBg8B,EAAOb,MAAMn6B,MAAQhB,EACrB20B,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAI5C/P,WAAW,kBAAMoP,GAAG8Z,MAAMj0C,KAAK27B,IAAS,KCrXhD,SAAS6f,UAAQ/2C,MACTkE,KAAGqlB,MAAMvpB,UACF,YAIJA,EAAImV,MADG,gEACYzF,OAAOsnC,GAAKh3C,EAI1C,SAASi3C,sBAAoBzf,GACrBA,IAASh8B,KAAK8sC,MAAM4O,iBACf5O,MAAM4O,WAAY,GAEvB17C,KAAK66B,MAAMgB,SAAWG,SACjBnB,MAAMgB,QAAUG,EACrB3H,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAOmB,EAAO,OAAS,UAI5D,IAAMiD,QAAU,CACZ8M,MADY,sBAGR3U,YAAYp3B,KAAK40B,SAASnR,QAASzjB,KAAKy4B,OAAOC,WAAWoU,OAAO,GAGjEiI,eAAeh1C,KAAKC,MAGhB0I,KAAGoB,OAAOjL,OAAOy+C,KAAO50C,KAAGmqB,SAASh0B,OAAOy+C,GAAGxB,QAC9C7c,QAAQvK,MAAM30B,KAAKC,OAGnBs7C,WAAWt7C,KAAKy4B,OAAO0S,KAAKlM,QAAQqQ,KAAKnf,MAAM,SAAAzvB,GAC3CmB,EAAKw6B,MAAM8G,KAAK,6BAA8BziC,KAKlD7B,OAAO0+C,wBAA0B1+C,OAAO0+C,yBAA2B,GAGnE1+C,OAAO0+C,wBAAwB96C,KAAK,WAChCw8B,QAAQvK,MAAM30B,KAAK8B,KAIvBhD,OAAO2+C,wBAA0B,WAC7B3+C,OAAO0+C,wBAAwBz7C,QAAQ,SAAAkB,GACnCA,SAOhBy6C,SApCY,SAoCHC,iBAIDh1C,KAAGmqB,SAAS7yB,KAAK8sC,MAAM6Q,cAAe,KAC9Bve,EAAUp/B,KAAK8sC,MAAM6Q,eAArBve,SAEJ12B,KAAGqlB,MAAMqR,eACJ3G,OAAO2G,MAAQA,OACpBlF,GAAGga,SAASn0C,KAAKC,UAMnBqC,EAAMrC,KAAKy4B,OAAOt1B,KAAKwtC,OACzBjoC,KAAG+L,OAAOpS,KAASqG,KAAGqlB,MAAM1rB,IAG5By9B,MAFYhC,OAAO99B,KAAKy4B,OAAO0S,KAAKlM,QAAQhF,IAAKyjB,EAASr7C,IAGrD6pB,KAAK,SAAAhd,GACExG,KAAGoB,OAAOoF,KACVklB,EAAKqE,OAAO2G,MAAQlwB,EAAOrO,MAAM,GAAG+8C,QAAQxe,MAC5ClF,GAAGga,SAASn0C,KAAKq0B,MAGxBjE,MAAM,eAKnBuE,MAnEY,eAoEFgH,EAAS17B,KAGT69C,EAAYniB,EAAOb,MAAMU,aAAa,SACvC7yB,KAAGqlB,MAAM8vB,KAAcA,EAAU9sB,WAAW,iBAK7C/lB,EAAS0wB,EAAOb,MAAMU,aAAa,OAGnC7yB,KAAGqlB,MAAM/iB,KACTA,EAAS0wB,EAAOb,MAAMU,aAAav7B,KAAKy4B,OAAO30B,WAAWgpC,MAAM7iC,SAI9DyzC,EAAUnC,UAAQvwC,GAClBf,EAAK2zB,WAAWlC,EAAO5B,UAMvBjF,EAAY9vB,cAAc,MAAO,CAAEkF,GAAAA,EAAIylC,OAH1BhU,EAAXgU,SAIRhU,EAAOb,MAAQxE,eAAexB,EAAW6G,EAAOb,WAG1CijB,EAAY,SAAAhgB,8CAAwC4f,EAAlC,KAAArzC,OAA6CyzB,EAA7C,gBAGxB0V,UAAUsK,EAAU,UAAW,KAC1B3tB,MAAM,kBAAMqjB,UAAUsK,EAAU,MAAO,OACvC3tB,MAAM,kBAAMqjB,UAAUsK,EAAU,SAChC5xB,KAAK,SAAAwnB,UAASxZ,GAAGia,UAAUp0C,KAAK27B,EAAQgY,EAAMl+B,OAC9C0W,KAAK,SAAA4xB,GAEGA,EAAU5lC,SAAS,YACpBwjB,EAAO9G,SAAS8a,OAAOp6B,MAAMi/B,eAAiB,WAGrDpkB,MAAM,kBAELsI,EAASiD,EAAOjD,OAAOwG,QAI7BvD,EAAOoR,MAAQ,IAAIjuC,OAAOy+C,GAAGxB,OAAO7xC,EAAI,CACpCyzC,QAAAA,EACA5b,KAAMrJ,EAAOwY,SAAW,wCAAqCtxC,EAC7Do+C,WAAYtiB,OACR,GACA,CACIiS,SAAUhS,EAAOjD,OAAOiV,SAAW,EAAI,EACvCsQ,GAAItiB,EAAOjD,OAAOulB,GAClBtc,SAAUhG,EAAOnI,UAAU2G,GAAK,EAAI,EACpC+jB,UAAW,EACXlkB,YAAc2B,EAAOjD,OAAOiK,WAAW4L,UAAgB,EAAJ,EAEnD4P,eAAgBxiB,EAAO+G,SAAS2J,OAAS,EAAI,EAC7C+R,aAAcziB,EAAOjD,OAAOgK,SAAS8G,SAErC6U,gBAAiBv/C,OAASA,OAAO+F,SAASR,KAAO,MAErDq0B,GAEJ7E,OAAQ,CACJyqB,QADI,SACIh/C,OAECq8B,EAAOb,MAAMn6B,MAAO,KACfuW,EAAO5X,EAAMykB,KAEbw6B,EACF,GACO,yOACA,2HACE,yIACA,2FACA,wFACPrnC,IAAS,2BAEfykB,EAAOb,MAAMn6B,MAAQ,CAAEuW,KAAAA,EAAMqnC,QAAAA,GAE7BjqB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAGhD0jB,qBApBI,SAoBiBl/C,OAEXilB,EAAWjlB,EAAMuM,OAGvB8vB,EAAOb,MAAM2jB,aAAel6B,EAASm6B,kBAErCpqB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,eAE5C6jB,QA7BI,SA6BIr/C,OAEAqJ,KAAGmqB,SAAS6I,EAAOb,MAAMmB,WAIvB1X,EAAWjlB,EAAMuM,OAGvBqzB,QAAQwe,SAAS19C,KAAK27B,EAAQgiB,GAG9BhiB,EAAOb,MAAMmB,KAAO,WAChByf,sBAAoB17C,KAAK27B,GAAQ,GACjCpX,EAASq6B,aAGbjjB,EAAOb,MAAMsH,MAAQ,WACjBsZ,sBAAoB17C,KAAK27B,GAAQ,GACjCpX,EAASs6B,cAGbljB,EAAOb,MAAMmhB,KAAO,WAChB13B,EAASu6B,aAGbnjB,EAAOb,MAAMmI,SAAW1e,EAAS04B,cACjCthB,EAAOb,MAAMgB,QAAS,EAGtBH,EAAOb,MAAMc,YAAc,EAC3B17B,OAAOC,eAAew7B,EAAOb,MAAO,cAAe,CAC/C16B,IAD+C,kBAEpCmxB,OAAOhN,EAASy4B,mBAE3Bh6C,IAJ+C,SAI3Cq+B,GAEI1F,EAAOG,SAAWH,EAAOoR,MAAM4O,WAC/BhgB,EAAOoR,MAAMvK,OAIjB7G,EAAOb,MAAMoN,SAAU,EACvB5T,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAGxCvW,EAAS+zB,OAAOjX,MAKxBnhC,OAAOC,eAAew7B,EAAOb,MAAO,eAAgB,CAChD16B,IADgD,kBAErCmkB,EAASm6B,mBAEpB17C,IAJgD,SAI5CkuB,GACA3M,EAAS83B,gBAAgBnrB,UAK3B6R,EAAWpH,EAAOjD,OAAlBqK,OACN7iC,OAAOC,eAAew7B,EAAOb,MAAO,SAAU,CAC1C16B,IAD0C,kBAE/B2iC,GAEX//B,IAJ0C,SAItCkuB,GACA6R,EAAS7R,EACT3M,EAAS43B,UAAmB,IAATpZ,GACnBzO,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,uBAK1C+L,EAAUlL,EAAOjD,OAAjBmO,MACN3mC,OAAOC,eAAew7B,EAAOb,MAAO,QAAS,CACzC16B,IADyC,kBAE9BymC,GAEX7jC,IAJyC,SAIrCkuB,OACM9E,EAASzjB,KAAGkqB,QAAQ3B,GAASA,EAAQ2V,EAC3CA,EAAQza,EACR7H,EAAS6H,EAAS,OAAS,YAC3BkI,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,mBAKhD56B,OAAOC,eAAew7B,EAAOb,MAAO,aAAc,CAC9C16B,IAD8C,kBAEnCmkB,EAASi4B,iBAKxBt8C,OAAOC,eAAew7B,EAAOb,MAAO,QAAS,CACzC16B,IADyC,kBAE9Bu7B,EAAOC,cAAgBD,EAAOsH,YAK7CtH,EAAOlI,QAAQ+S,MAAQjiB,EAASw6B,4BAG5BpjB,EAAOnI,UAAU2G,IACjBwB,EAAOb,MAAMjF,aAAa,YAAa,GAG3CvB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,cACxCxG,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,kBAGxCkkB,cAAcrjB,EAAOiZ,OAAOqK,WAG5BtjB,EAAOiZ,OAAOqK,UAAY73C,YAAY,WAElCu0B,EAAOb,MAAMqM,SAAW5iB,EAAS26B,0BAGC,OAA9BvjB,EAAOb,MAAMqkB,cAAyBxjB,EAAOb,MAAMqkB,aAAexjB,EAAOb,MAAMqM,WAC/E7S,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,YAI5Ca,EAAOb,MAAMqkB,aAAexjB,EAAOb,MAAMqM,SAGX,IAA1BxL,EAAOb,MAAMqM,WACb6X,cAAcrjB,EAAOiZ,OAAOqK,WAG5B3qB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,oBAE7C,KAGH/P,WAAW,kBAAMoP,GAAG8Z,MAAMj0C,KAAK27B,IAAS,MAE5CyjB,cAzKI,SAyKU9/C,OAEJilB,EAAWjlB,EAAMuM,cAGvBmzC,cAAcrjB,EAAOiZ,OAAO9E,SAEbnU,EAAOb,MAAMoN,SAAW,CAAC,EAAG,GAAG/vB,SAAS7Y,EAAMykB,QAIzD4X,EAAOb,MAAMoN,SAAU,EACvB5T,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAUpCx7B,EAAMykB,WACJ,EAEFuQ,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,cAGxCa,EAAOb,MAAMqM,SAAW5iB,EAAS26B,yBACjC5qB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,uBAIvC,EACD4gB,sBAAoB17C,KAAK27B,GAAQ,GAG7BA,EAAOb,MAAMqT,MAEb5pB,EAASu6B,YACTv6B,EAASq6B,aAETtqB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,oBAK3C,EAEGa,EAAOb,MAAMgB,SAAWH,EAAOoR,MAAM4O,UACrChgB,EAAOb,MAAMsH,SAEbsZ,sBAAoB17C,KAAK27B,GAAQ,GAEjCrH,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,WAGxCa,EAAOiZ,OAAO9E,QAAU1oC,YAAY,WAChCktB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,eACzC,IAKCa,EAAOb,MAAMmI,WAAa1e,EAAS04B,gBACnCthB,EAAOb,MAAMmI,SAAW1e,EAAS04B,cACjC3oB,aAAat0B,KAAK27B,EAAQA,EAAOb,MAAO,+BAM/C,EAEIa,EAAOkL,OACRlL,EAAOoR,MAAMsS,SAEjB3D,sBAAoB17C,KAAK27B,GAAQ,GAQzCrH,aAAat0B,KAAK27B,EAAQA,EAAO9G,SAASC,UAAW,eAAe,EAAO,CACvE5d,KAAM5X,EAAMykB,cCha9B+W,MAAQ,CAEVkR,MAFU,WAID/rC,KAAK66B,OAMVzD,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAW3tB,KAAK3J,QAAQ,MAAOpB,KAAK+K,OAAO,GAG5FqsB,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWoB,SAAS14B,QAAQ,MAAOpB,KAAK85B,WAAW,GAIhG95B,KAAKorC,SACLhU,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAW3tB,KAAK3J,QAAQ,MAAO,UAAU,GAI1FpB,KAAKgsC,eAEApX,SAASnR,QAAU1e,cAAc,MAAO,CACzCiyB,MAAOh3B,KAAKy4B,OAAOC,WAAWmB,QAIlC/E,KAAK90B,KAAK66B,MAAO76B,KAAK40B,SAASnR,cAG1BmR,SAAS8a,OAAS3qC,cAAc,MAAO,CACxCiyB,MAAOh3B,KAAKy4B,OAAOC,WAAWgX,cAG7B9a,SAASnR,QAAQxe,YAAYjF,KAAK40B,SAAS8a,SAGhD1vC,KAAK46B,QACLS,MAAMI,OAAO17B,KAAKC,MACXA,KAAKisC,UACZhN,QAAQ8M,MAAMhsC,KAAKC,MACZA,KAAK0pC,SACZ1K,MAAM+M,MAAMhsC,KAAKC,YAvCZq8B,MAAM8G,KAAK,6BCEtBkc,0BAMU3jB,2CACHA,OAASA,OACTjD,OAASiD,EAAOjD,OAAOmX,SACvBC,SAAU,OACV0H,aAAc,OACd3iB,SAAW,CACZC,UAAW,KACXyqB,iBAAkB,WAEjBC,QAAU,UACVC,OAAS,UACTC,UAAY,UACZ7rB,OAAS,QACT8rB,YAAc,UACdC,eAAiB,UAGjBnI,eAAiB,IAAIpsB,QAAQ,SAACY,EAASU,GAExC7qB,EAAKiyB,GAAG,SAAU9H,GAGlBnqB,EAAKiyB,GAAG,QAASpH,UAGhBuP,sEAkBDj8B,KAAKu/B,UAEA72B,KAAGoB,OAAOjL,OAAO8xC,SAAYjoC,KAAGoB,OAAOjL,OAAO8xC,OAAOiP,UAUjDlrB,QATL4mB,WAAWt7C,KAAK07B,OAAOjD,OAAO0S,KAAKoE,UAAUD,KACxCpjB,KAAK,WACFkI,EAAKM,UAERvE,MAAM,WAEHiE,EAAKyrB,QAAQ,QAAS,IAAI1gD,MAAM,qFAc3C2gD,iBAAiB,KAAO,gBAGxBtI,eAAetrB,KAAK,WACrByI,EAAKorB,iBAAiB,+BAIrB3Z,iBAGA4Z,mDAoCAprB,SAASC,UAAY9vB,cAAc,MAAO,CAC3CiyB,MAAOh3B,KAAK07B,OAAOjD,OAAOC,WAAWkX,WAEpClU,OAAO9G,SAASC,UAAU5vB,YAAYjF,KAAK40B,SAASC,WAGzD8b,OAAOiP,IAAIpd,SAASyd,aAAatP,OAAOiP,IAAIM,eAAeC,UAAUC,SAGrEzP,OAAOiP,IAAIpd,SAAS6d,UAAUrgD,KAAK07B,OAAOjD,OAAOmX,IAAIrG,eAIhD3U,SAAS0qB,iBAAmB,IAAI3O,OAAOiP,IAAIU,mBAAmBtgD,KAAK40B,SAASC,gBAG5E0rB,6DAOG1rB,EAAc70B,KAAK07B,OAAO9G,SAA1BC,mBAIC2qB,OAAS,IAAI7O,OAAOiP,IAAIY,UAAUxgD,KAAK40B,SAAS0qB,uBAGhDE,OAAO/0B,iBACRkmB,OAAOiP,IAAIa,sBAAsBC,KAAKC,mBACtC,SAAAthD,UAASqoC,EAAKkZ,mBAAmBvhD,KACjC,QAECmgD,OAAO/0B,iBAAiBkmB,OAAOiP,IAAIiB,aAAaH,KAAKI,SAAU,SAAApgD,UAASgnC,EAAKqZ,UAAUrgD,KAAQ,OAG9Fs/B,EAAU,IAAI2Q,OAAOiP,IAAIoB,WAC/BhhB,EAAQihB,SAAWjhD,KAAK6wC,OAIxB7Q,EAAQkhB,kBAAoBrsB,EAAUssB,YACtCnhB,EAAQohB,mBAAqBvsB,EAAUoE,aACvC+G,EAAQqhB,qBAAuBxsB,EAAUssB,YACzCnhB,EAAQshB,sBAAwBzsB,EAAUoE,aAG1C+G,EAAQuhB,wBAAyB,EAGjCvhB,EAAQwhB,oBAAoBxhD,KAAK07B,OAAOkL,YAEnC4Y,OAAOe,WAAWvgB,GACzB,MAAO5gC,QACA2hD,UAAU3hD,4DAQM0G,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,WAErBi5C,cAAc/+C,KAAK2/C,0BACd/qB,SAASC,UAAUsC,gBAAgB,wBAUvCwoB,eAAiBx4C,YANP,eACLi6B,EAAOD,WAAWt5B,KAAK8K,IAAIm2B,EAAKyW,QAAQkC,mBAAoB,IAC5Dpd,EAAK,GAAAh6B,OAAM60B,KAAK/+B,IAAI,gBAAiB2oC,EAAKpN,OAAOjD,QAA5C,OAAApuB,OAAyD+2B,GACpE0H,EAAKlU,SAASC,UAAUe,aAAa,kBAAmByO,IAGlB,gDAO3BhlC,iBAEVW,KAAKu/B,aAKJiD,EAAW,IAAImO,OAAOiP,IAAI8B,qBAGhClf,EAASmf,6CAA8C,EACvDnf,EAASof,kBAAmB,OAIvBrC,QAAUlgD,EAAMwiD,cAAc7hD,KAAK07B,OAAQ8G,QAG3Cid,UAAYz/C,KAAKu/C,QAAQuC,eAGzBp5C,KAAGqlB,MAAM/tB,KAAKy/C,iBACVA,UAAU39C,QAAQ,SAAAigD,MACF,IAAbA,IAAgC,IAAdA,GAAmBA,EAAW1Y,EAAK3N,OAAOsH,SAAU,KAChEgf,EAAc3Y,EAAK3N,OAAO9G,SAAS+N,YAErCj6B,KAAGuqB,QAAQ+uB,GAAc,KACnBC,EAAiB,IAAM5Y,EAAK3N,OAAOsH,SAAY+e,EAC/C3uB,EAAMruB,cAAc,OAAQ,CAC9BiyB,MAAOqS,EAAK3N,OAAOjD,OAAOC,WAAW0U,OAGzCha,EAAI9d,MAAMuyB,KAAV,GAAAx9B,OAAoB43C,EAAczgD,WAAlC,KACAwgD,EAAY/8C,YAAYmuB,YAOnCmsB,QAAQrD,UAAUl8C,KAAK07B,OAAOoH,aAI9Byc,QAAQ90B,iBAAiBkmB,OAAOiP,IAAIiB,aAAaH,KAAKI,SAAU,SAAApgD,UAAS2oC,EAAK0X,UAAUrgD,KAG7FT,OAAOkD,KAAKwtC,OAAOiP,IAAIsC,QAAQxB,MAAM5+C,QAAQ,SAAAiJ,GACzCs+B,EAAKkW,QAAQ90B,iBAAiBkmB,OAAOiP,IAAIsC,QAAQxB,KAAK31C,GAAO,SAAA1L,UAASgqC,EAAK8Y,UAAU9iD,YAIpFwgD,QAAQ,6CASPxgD,cACEw1B,EAAc70B,KAAK07B,OAAO9G,SAA1BC,UAIFutB,EAAK/iD,EAAMgjD,QACXC,EAASjjD,EAAMkjD,YAGfhuB,EAAgB,SAAAxpB,OACZ1L,EAAK,MAAAgL,OAASU,EAAK3J,QAAQ,KAAM,IAAIk9B,eAC3CjK,aAAat0B,KAAK4pC,EAAKjO,OAAQiO,EAAKjO,OAAOb,MAAOx7B,WAG9CA,EAAM0L,WACL4lC,OAAOiP,IAAIsC,QAAQxB,KAAK8B,YAGpB3C,QAAQ,UAGbtrB,EAAcl1B,EAAM0L,WAGf03C,eAAc,GAEdL,EAAGM,aAEJN,EAAGza,MAAQ9S,EAAUssB,YACrBiB,EAAG7X,OAAS1V,EAAUoE,yBAOzB0X,OAAOiP,IAAIsC,QAAQxB,KAAKiC,kBAKzBpuB,EAAcl1B,EAAM0L,WAyBf63C,qBAGJjS,OAAOiP,IAAIsC,QAAQxB,KAAKmC,wBAKzBtuB,EAAcl1B,EAAM0L,WAEf+3C,0BAIJnS,OAAOiP,IAAIsC,QAAQxB,KAAKqC,yBAMzBxuB,EAAcl1B,EAAM0L,WAEf03C,qBAEAO,2BAIJrS,OAAOiP,IAAIsC,QAAQxB,KAAKuC,aACxBtS,OAAOiP,IAAIsC,QAAQxB,KAAKwC,cACxBvS,OAAOiP,IAAIsC,QAAQxB,KAAKyC,cACxBxS,OAAOiP,IAAIsC,QAAQxB,KAAK0C,gBACxBzS,OAAOiP,IAAIsC,QAAQxB,KAAK2C,MACzB9uB,EAAcl1B,EAAM0L,iBAGnB4lC,OAAOiP,IAAIsC,QAAQxB,KAAK4C,IACrBhB,EAAOiB,cACF7nB,OAAOW,MAAM8G,KAAlB,uBAAA94B,OAA8Ci4C,EAAOiB,QAAQC,kDAanEnkD,QACDokD,cACA/nB,OAAOW,MAAM8G,KAAK,YAAa9jC,2CAUhC+hC,SADIvM,EAAc70B,KAAK07B,OAAO9G,SAA1BC,eAIH6G,OAAO5H,GAAG,QAAS,WACpB8W,EAAK4U,OAAOkE,yBAGXhoB,OAAO5H,GAAG,aAAc,WACzBsN,EAAOwJ,EAAKlP,OAAOC,mBAGlBD,OAAO5H,GAAG,SAAU,eACf6vB,EAAa/Y,EAAKlP,OAAOC,YAE3BjzB,KAAGqlB,MAAM6c,EAAK6U,YAIlB7U,EAAK6U,UAAU39C,QAAQ,SAACigD,EAAUl0C,GAC1BuzB,EAAO2gB,GAAYA,EAAW4B,IAC9B/Y,EAAK2U,QAAQqE,iBACbhZ,EAAK6U,UAAUn8B,OAAOzV,EAAO,QAOzChP,OAAO4rB,iBAAiB,SAAU,WAC1BmgB,EAAK2U,SACL3U,EAAK2U,QAAQsE,OAAOhvB,EAAUssB,YAAatsB,EAAUoE,aAAc0X,OAAOiP,IAAIkE,SAASC,oDASvFlvB,EAAc70B,KAAK07B,OAAO9G,SAA1BC,UAEH70B,KAAKw3C,qBACDwL,qBAIJxL,eACAtrB,KAAK,WAEF+e,EAAKrW,SAAS0qB,iBAAiB0E,iBAGtB/Y,EAAKsM,cAENtM,EAAKsU,QAAQ0E,KAAKpvB,EAAUssB,YAAatsB,EAAUoE,aAAc0X,OAAOiP,IAAIkE,SAASC,QAIrF9Y,EAAKsU,QAAQvQ,SAGjB/D,EAAKsM,aAAc,EACrB,MAAOgM,GAGLtY,EAAK8V,UAAUwC,MAGtBpzB,MAAM,2DAQNyE,SAASC,UAAUvf,MAAM4uC,OAAS,QAGlCrU,SAAU,EAGX7vC,KAAK07B,OAAOC,YAAc37B,KAAK07B,OAAOsH,eACjCtH,OAAOM,mDASXpH,SAASC,UAAUvf,MAAM4uC,OAAS,OAGlCrU,SAAU,OAGVnU,OAAOyG,yCAWRniC,KAAKu3C,kBACAyL,qBAIJnD,QAAQ,cAGR+C,4DAQApL,eACAtrB,KAAK,WAEEsf,EAAK+T,SACL/T,EAAK+T,QAAQ4E,UAIjB3Y,EAAKgM,eAAiB,IAAIpsB,QAAQ,SAAAY,GAC9Bwf,EAAK1X,GAAG,SAAU9H,GAClBwf,EAAK9P,OAAOW,MAAMC,IAAIkP,EAAK+T,WAI/B/T,EAAK+U,eAERpwB,MAAM,8CAOP9wB,qCAAU+pB,EAAM,IAAAlc,MAAAgnB,EAAA,EAAAA,EAAA,EAAA,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAN/K,EAAM+K,EAAA,GAAAruB,UAAAquB,OACdiwB,EAAWpkD,KAAK4zB,OAAOv0B,GAEzBqJ,KAAGoqB,MAAMsxB,IACTA,EAAStiD,QAAQ,SAAAgtB,GACTpmB,KAAGmqB,SAAS/D,IACZA,EAAQjpB,MAAMw+C,EAAMj7B,gCAYjC/pB,EAAO2D,UACD0F,KAAGoqB,MAAM9yB,KAAK4zB,OAAOv0B,WACjBu0B,OAAOv0B,GAAS,SAGpBu0B,OAAOv0B,GAAOoD,KAAKO,GAEjBhD,8CAWMohC,EAAMpyB,mBACd0sB,OAAOW,MAAMC,IAAlB,8BAAAjyB,OAAoD2E,SAE/C0wC,YAAc50B,WAAW,WAC1Bw5B,EAAKb,SACLa,EAAKvE,iBAAiB,uBACvB3e,4CAOUpyB,GACRtG,KAAGiqB,gBAAgB3yB,KAAK0/C,oBACpBhkB,OAAOW,MAAMC,IAAlB,8BAAAjyB,OAAoD2E,IAEpD0lC,aAAa10C,KAAK0/C,kBACbA,YAAc,0CAhjBfjnB,EAAWz4B,KAAXy4B,cAGJz4B,KAAK07B,OAAOd,SACZ56B,KAAK07B,OAAOsQ,SACZvT,EAAO8G,WACL72B,KAAGqlB,MAAM0K,EAAOmY,cAAgBloC,KAAGlE,IAAIi0B,EAAOoY,4CA+C5CpY,EAAWz4B,KAAXy4B,UAEJ/vB,KAAGlE,IAAIi0B,EAAOoY,eACPpY,EAAOoY,WAGZvxC,EAAS,CACXilD,eAAgB,2BAChBC,aAAc,2BACdC,OAAQ5lD,OAAO+F,SAAS+B,SACxB+9C,GAAI5P,KAAK1qB,MACTu6B,SAAU,IACVC,UAAW,IACXC,SAAU7kD,KAAK4wC,6BAGN,6CAEb,KAAAvmC,OAAkByhC,eAAexsC,aCvHrCoS,QAAQjJ,cAA4B,GACpCkJ,MAAM,YACNC,UAAS,EAETD,QAAO,IAAIzE,MAAM,GAAGyE,OAAK,WAAcC,UAAS,IACpD9G,QAAQA,QAAQxB,EAAIwB,QAAQO,EAAIuG,SAAQ,QAAS,CAC/CkzC,UAAW,SAAmBzzC,GAC5B,OAAOK,QAAM1R,KAAMqR,EAAYvL,UAAU3D,OAAS,EAAI2D,UAAU,QAAKnG,MAGzEkJ,kBAAiC8I,OCNjC,IAAMozC,SAAW,SAAAC,OACPC,EAAgB,UACPD,EAAcjhD,MAAM,sBAE5BjC,QAAQ,SAAAojD,OACLh2C,EAAS,GACDg2C,EAAMnhD,MAAM,cAEpBjC,QAAQ,SAAAqjD,MACLz8C,KAAGsoB,OAAO9hB,EAAOk2C,YAkBf,IAAK18C,KAAGqlB,MAAMo3B,EAAK3wC,SAAW9L,KAAGqlB,MAAM7e,EAAO2mB,MAAO,KAElDwvB,EAAYF,EAAK3wC,OAAOzQ,MAAM,2BACpBshD,EAHwC,MAGvDn2C,EAAO2mB,KAHgDyvB,EAAA,GAMpDD,EAAU,GAAI,sBAC6BA,EAAU,GAAGthD,MAAM,QAA7DmL,EAAOoJ,EADMitC,EAAA,GACHr2C,EAAOqJ,EADJgtC,EAAA,GACOr2C,EAAOqS,EADdgkC,EAAA,GACiBr2C,EAAOs2C,EADxBD,EAAA,SAxBY,KAExBE,EAAaN,EAAKxrC,MACpB,uGAGA8rC,IACAv2C,EAAOk2C,UACqB,GAAxB9zB,OAAOm0B,EAAW,IAAW,GACL,GAAxBn0B,OAAOm0B,EAAW,IAClBn0B,OAAOm0B,EAAW,IAClBn0B,OAAM,KAAAjnB,OAAMo7C,EAAW,KAC3Bv2C,EAAOw2C,QACqB,GAAxBp0B,OAAOm0B,EAAW,IAAW,GACL,GAAxBn0B,OAAOm0B,EAAW,IAClBn0B,OAAOm0B,EAAW,IAClBn0B,OAAM,KAAAjnB,OAAMo7C,EAAW,SAcnCv2C,EAAO2mB,MACPovB,EAAcxiD,KAAKyM,KAIpB+1C,GAcLU,wCAMUjqB,gCACHA,OAASA,OACTkqB,WAAa,QACbtN,QAAS,OACTuN,kBAAoB/Q,KAAK1qB,WACzB07B,WAAY,OACZC,aAAe,QAEfnxB,SAAW,CACZoxB,MAAO,GACPC,UAAW,SAGVhqB,sEASDj8B,KAAK07B,OAAO9G,SAASrf,QAAQ0tB,mBACxBvH,OAAO9G,SAASrf,QAAQ0tB,YAAY/L,OAASl3B,KAAKu/B,SAGtDv/B,KAAKu/B,cAIL2mB,gBAAgBh6B,KAAK,WAEtBrqB,EAAKskD,SAGLtkD,EAAKukD,+BAELvkD,EAAKy2C,QAAS,8DAMX,IAAIltB,QAAQ,SAAAY,OACPxW,EAAQ4e,EAAKsH,OAAOjD,OAAO2X,kBAA3B56B,OAEJ9M,KAAGqlB,MAAMvY,SACH,IAAIrW,MAAM,sDAOdknD,GAHO39C,KAAG+L,OAAOe,GAAO,CAACA,GAAOA,GAGhB8hB,IAAI,SAAArzB,UAAKmwB,EAAKkyB,aAAariD,KAEjDmnB,QAAQoF,IAAI61B,GAAUn6B,KAAK,WAEvBkI,EAAKwxB,WAAWpiD,KAAK,SAAC8U,EAAGC,UAAMD,EAAEiyB,OAAShyB,EAAEgyB,SAE5CnW,EAAKsH,OAAOW,MAAMC,IAAI,qBAAsBlI,EAAKwxB,YAEjD55B,6CAMCxnB,qBACF,IAAI4mB,QAAQ,SAAAY,GACf8T,MAAMt7B,GAAK0nB,KAAK,SAAAiU,OACNomB,EAAY,CACdC,OAAQzB,SAAS5kB,GACjBoK,OAAQ,KACRkc,UAAW,IAKVF,EAAUC,OAAO,GAAG3wB,KAAK9E,WAAW,OACrCw1B,EAAUE,UAAYjiD,EAAIkiD,UAAU,EAAGliD,EAAImiD,YAAY,KAAO,QAI5DC,EAAY,IAAIjT,MAEtBiT,EAAUhT,OAAS,WACf2S,EAAUhc,OAASqc,EAAUC,cAC7BN,EAAU5e,MAAQif,EAAU9S,aAE5Bnf,EAAKixB,WAAWnjD,KAAK8jD,GAErBv6B,KAGJ46B,EAAUpxC,IAAM+wC,EAAUE,UAAYF,EAAUC,OAAO,GAAG3wB,2CAK5Dx2B,MACDW,KAAKs4C,QAIL5vC,KAAGrJ,MAAMA,IAAW,CAAC,YAAa,aAAa6Y,SAAS7Y,EAAM0L,OAK9D/K,KAAK07B,OAAOb,MAAMmI,aAIJ,cAAf3jC,EAAM0L,UAEDo0B,SAAWn/B,KAAK07B,OAAOb,MAAMmI,UAAYhjC,KAAK07B,OAAO9G,SAASgO,OAAOC,KAAK9hC,MAAQ,SACpF,KAEGwmC,EAAavnC,KAAK07B,OAAO9G,SAAS+N,SAAS6E,wBAC3Csf,EAAc,IAAMvf,EAAWI,OAAUtoC,EAAMuoC,MAAQL,EAAWM,WACnE1I,SAAWn/B,KAAK07B,OAAOb,MAAMmI,UAAY8jB,EAAa,KAEvD9mD,KAAKm/B,SAAW,SAEXA,SAAW,GAGhBn/B,KAAKm/B,SAAWn/B,KAAK07B,OAAOb,MAAMmI,SAAW,SAExC7D,SAAWn/B,KAAK07B,OAAOb,MAAMmI,SAAW,QAG5C+jB,UAAY1nD,EAAMuoC,WAGlBhT,SAASoxB,MAAM5kB,KAAKtL,UAAYqL,WAAWnhC,KAAKm/B,eAIpD6nB,iEAIAC,sBAAqB,GAAO,0CAGtB5nD,IAEU,IAAjBA,EAAMolC,QAAqC,IAAjBplC,EAAMolC,cAC3BqhB,WAAY,EAEb9lD,KAAK07B,OAAOb,MAAMmI,gBACbkkB,0BAAyB,QACzBD,sBAAqB,GAAO,QAG5BD,qFAMRlB,WAAY,EAGbj+C,KAAKwF,KAAKrN,KAAKmnD,YAAct/C,KAAKwF,KAAKrN,KAAK07B,OAAOb,MAAMc,kBAEpDurB,0BAAyB,GAG9BlzB,KAAKj0B,KAAKC,KAAK07B,OAAQ17B,KAAK07B,OAAOb,MAAO,aAAc,WAE/C6M,EAAKoe,WACNpe,EAAKwf,0BAAyB,yDAWrCxrB,OAAO5H,GAAG,OAAQ,WACnBgV,EAAKme,sBAAqB,GAAO,UAGhCvrB,OAAO5H,GAAG,SAAU,WACrBgV,EAAKme,sBAAqB,UAGzBvrB,OAAO5H,GAAG,aAAc,WACzBgV,EAAKqe,SAAWre,EAAKpN,OAAOb,MAAMc,oDASjC/G,SAASoxB,MAAMnxB,UAAY9vB,cAAc,MAAO,CACjDiyB,MAAOh3B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBC,sBAItDzb,SAASoxB,MAAMzV,eAAiBxrC,cAAc,MAAO,CACtDiyB,MAAOh3B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBG,sBAEtD3b,SAASoxB,MAAMnxB,UAAU5vB,YAAYjF,KAAK40B,SAASoxB,MAAMzV,oBAGxDC,EAAgBzrC,cAAc,MAAO,CACvCiyB,MAAOh3B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBI,qBAGtD5b,SAASoxB,MAAM5kB,KAAOr8B,cAAc,OAAQ,GAAI,SACrDyrC,EAAcvrC,YAAYjF,KAAK40B,SAASoxB,MAAM5kB,WAEzCxM,SAASoxB,MAAMnxB,UAAU5vB,YAAYurC,QAGrC9U,OAAO9G,SAAS+N,SAAS19B,YAAYjF,KAAK40B,SAASoxB,MAAMnxB,gBAGzDD,SAASqxB,UAAUpxB,UAAY9vB,cAAc,MAAO,CACrDiyB,MAAOh3B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBK,0BAGtD/U,OAAO9G,SAASnR,QAAQxe,YAAYjF,KAAK40B,SAASqxB,UAAUpxB,uEAI7D70B,KAAK8lD,eACAsB,kCAEAH,sBAAqB,QACrBI,mCAKHC,EAAWtnD,KAAK4lD,WAAW,GAAGY,OAAO1B,UACvC,SAAAI,UAAS7b,EAAKlK,UAAY+lB,EAAME,WAAa/b,EAAKlK,UAAY+lB,EAAMQ,UAElE6B,EAAWD,GAAY,EACzBE,EAAe,OAEdP,qBAAqBM,GAGrBA,SAKA3B,WAAW9jD,QAAQ,SAACykD,EAAW14C,GAC5Bw7B,EAAK0c,aAAa7tC,SAASquC,EAAUC,OAAOc,GAAUzxB,QACtD2xB,EAAe35C,KAKnBy5C,IAAatnD,KAAKynD,oBACbA,aAAeH,OACf9T,UAAUgU,oDAKbA,EAAkB1hD,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAH,EACfwhD,EAAWtnD,KAAKynD,aAChBlB,EAAYvmD,KAAK4lD,WAAW4B,GAC1Bf,EAAcF,EAAdE,UACFvB,EAAQqB,EAAUC,OAAOc,GACzBI,EAAgBnB,EAAUC,OAAOc,GAAUzxB,KAC3C8xB,EAAWlB,EAAYiB,KAExB1nD,KAAK4nD,qBAAuB5nD,KAAK4nD,oBAAoBC,QAAQC,WAAaJ,OAyBtEK,UAAU/nD,KAAK4nD,oBAAqB1C,EAAOsC,EAAcF,EAAUI,GAAe,QAClFE,oBAAoBC,QAAQh6C,MAAQy5C,OACpCU,gBAAgBhoD,KAAK4nD,yBA3BgE,CAGtF5nD,KAAKioD,cAAgBjoD,KAAKkoD,oBACrBD,aAAarU,OAAS,UAMzBuU,EAAe,IAAIxU,MACzBwU,EAAa3yC,IAAMmyC,EACnBQ,EAAaN,QAAQh6C,MAAQy5C,EAC7Ba,EAAaN,QAAQC,SAAWJ,OAC3BU,qBAAuBV,OAEvBhsB,OAAOW,MAAMC,IAAlB,kBAAAjyB,OAAwCs9C,IAGxCQ,EAAavU,OAAS,kBAClBjK,EAAKoe,UAAUI,EAAcjD,EAAOsC,EAAcF,EAAUI,GAAe,SAC1EO,aAAeE,OACfH,gBAAgBG,sCASnBA,EAAcjD,EAAOsC,EAAcF,EAAUI,OAAeW,IAAiBviD,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,QAC9E41B,OAAOW,MAAMC,IAAlB,kBAAAjyB,OACsBq9C,EADtB,WAAAr9C,OAC6Ci9C,EAD7C,YAAAj9C,OACgEm9C,EADhE,cAAAn9C,OACyFg+C,SAEpFC,sBAAsBH,EAAcjD,GAErCmD,SACKE,sBAAsBtjD,YAAYkjD,QAClCP,oBAAsBO,EAEtBnoD,KAAK+lD,aAAa7tC,SAASwvC,SACvB3B,aAAatjD,KAAKilD,SAO1Bc,cAAclB,GAAU,GACxBp7B,KAAKlsB,KAAKwoD,cAAclB,GAAU,IAClCp7B,KAAKlsB,KAAKyoD,iBAAiBjB,EAAcW,EAAcjD,EAAOwC,4CAIvDgB,cAEZx7C,MAAM8B,KAAKhP,KAAKuoD,sBAAsBpiB,UAAUrkC,QAAQ,SAAA4xC,MAChB,QAAhCA,EAAMiV,QAAQrqB,mBAIZsqB,EAAche,EAAKsd,aAAe,IAAM,OAE1CxU,EAAMmU,QAAQh6C,QAAU66C,EAAab,QAAQh6C,QAAU6lC,EAAMmU,QAAQgB,SAAU,CAG/EnV,EAAMmU,QAAQgB,UAAW,MAEjBN,EAA0B3d,EAA1B2d,sBAERz9B,WAAW,WACPy9B,EAAsB19B,YAAY6oB,GAClC9I,EAAKlP,OAAOW,MAAMC,IAAlB,mBAAAjyB,OAAyCqpC,EAAMmU,QAAQC,YACxDc,6CAODtB,cAAUnR,IAAgBrwC,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,KAAAA,UAAA,UAC7B,IAAIslB,QAAQ,SAAAY,GACflB,WAAW,eACDg+B,EAAmB7d,EAAK2a,WAAW,GAAGY,OAAOc,GAAUzxB,QAEzDoV,EAAKmd,uBAAyBU,EAAkB,KAE5CC,EAEAA,EADA5S,EACkBlL,EAAK2a,WAAW,GAAGY,OAAO3jD,MAAMykD,GAEhCrc,EAAK2a,WAAW,GAAGY,OAAO3jD,MAAM,EAAGykD,GAAUtyB,cAG/Dg0B,GAAW,EAEfD,EAAgBjnD,QAAQ,SAAAojD,OACd+D,EAAmB/D,EAAMrvB,QAE3BozB,IAAqBH,IAEhB7d,EAAK8a,aAAa7tC,SAAS+wC,GAAmB,CAC/CD,GAAW,EACX/d,EAAKvP,OAAOW,MAAMC,IAAlB,8BAAAjyB,OAAoD4+C,QAG9CC,EADgBje,EAAK2a,WAAW,GAA9Ba,UACqBwC,EAEvBd,EAAe,IAAIxU,MACzBwU,EAAa3yC,IAAM0zC,EACnBf,EAAavU,OAAS,WAClB3I,EAAKvP,OAAOW,MAAMC,IAAlB,6BAAAjyB,OAAmD4+C,IAC9Che,EAAK8a,aAAa7tC,SAAS+wC,IAC5Bhe,EAAK8a,aAAatjD,KAAKwmD,GAG3Bj9B,QAOXg9B,GACDh9B,MAGT,gDAKMm9B,EAAqBhB,EAAcjD,EAAOwC,iBACnDyB,EAAsBnpD,KAAK4lD,WAAWzjD,OAAS,EAAG,KAE9CinD,EAAqBjB,EAAatB,cAElC7mD,KAAKkoD,eACLkB,EAAqBlE,EAAMM,GAG3B4D,EAAqBppD,KAAKqpD,sBAE1Bv+B,WAAW,WAEH0gB,EAAK4c,uBAAyBV,IAC9Blc,EAAK9P,OAAOW,MAAMC,IAAlB,qCAAAjyB,OAA2Dq9C,IAC3Dlc,EAAKgI,UAAU2V,EAAsB,KAE1C,yDAkDMh9B,EAAsCrmB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAAtBwjD,EAAsBxjD,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GACjDgxB,EAAY92B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBE,yBAC7D1b,SAASoxB,MAAMnxB,UAAU0C,UAAUpL,OAAO2K,EAAW3K,IAErDA,GAAUm9B,SACN7B,aAAe,UACfW,qBAAuB,6DAIXj8B,EAAgBrmB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,GAC/BgxB,EAAY92B,KAAK07B,OAAOjD,OAAOC,WAAW0X,kBAAkBM,6BAC7D9b,SAASqxB,UAAUpxB,UAAU0C,UAAUpL,OAAO2K,EAAW3K,GAEzDA,SACIs7B,aAAe,UACfW,qBAAuB,6DAK5BpoD,KAAK40B,SAASoxB,MAAMzV,eAAegZ,aAAe,UAE7CC,oBAAqB,6DAMzBxpD,KAAKwpD,mBAAoB,KACpBC,EAAa5hD,KAAKyF,MAAMtN,KAAKqpD,qBAAuBrpD,KAAK0pD,uBAC1D90B,SAASoxB,MAAMzV,eAAej7B,MAAMi1B,OAAzC,GAAAlgC,OAAqDrK,KAAKqpD,qBAA1D,WACKz0B,SAASoxB,MAAMzV,eAAej7B,MAAMqyB,MAAzC,GAAAt9B,OAAoDo/C,EAApD,WAGCE,0EAICC,EAAc5pD,KAAK07B,OAAO9G,SAAS+N,SAAS6E,wBAC5CqiB,EAAW7pD,KAAK07B,OAAO9G,SAASC,UAAU2S,wBACxC3S,EAAc70B,KAAK40B,SAASoxB,MAA5BnxB,UAGFi1B,EAASD,EAAShiB,KAAO+hB,EAAY/hB,KAAO,GAC5CkiB,EAASF,EAASG,MAAQJ,EAAY/hB,KAAOhT,EAAUo1B,YAAc,GAGvEC,EAAalqD,KAAK+mD,UAAY6C,EAAY/hB,KAAOhT,EAAUo1B,YAAc,EAEzEC,EAAaJ,IACbI,EAAaJ,GAGbI,EAAaH,IACbG,EAAaH,GAGjBl1B,EAAUvf,MAAMuyB,KAAhB,GAAAx9B,OAA0B6/C,EAA1B,+DAKKt1B,SAASqxB,UAAUpxB,UAAUvf,MAAMqyB,MAAxC,GAAAt9B,OAAmDrK,KAAK07B,OAAOb,MAAMovB,YAArE,WAEKr1B,SAASqxB,UAAUpxB,UAAUvf,MAAMi1B,OAAxC,GAAAlgC,OAAoDrK,KAAK07B,OAAOb,MAAMovB,YAAcjqD,KAAK0pD,iBAAzF,oDAIkBvB,EAAcjD,MAC3BllD,KAAKkoD,kBAKJiC,EAAanqD,KAAKqpD,qBAAuBnE,EAAMM,EAErD2C,EAAa7yC,MAAMi1B,OAAnB,GAAAlgC,OAA+BxC,KAAKyF,MAAM66C,EAAatB,cAAgBsD,GAAvE,MACAhC,EAAa7yC,MAAMqyB,MAAnB,GAAAt9B,OAA8BxC,KAAKyF,MAAM66C,EAAarU,aAAeqW,GAArE,MACAhC,EAAa7yC,MAAMuyB,KAAnB,IAAAx9B,OAA8B66C,EAAM5sC,EAAI6xC,EAAxC,MACAhC,EAAa7yC,MAAM80C,IAAnB,IAAA//C,OAA6B66C,EAAM3sC,EAAI4xC,EAAvC,8CA/hBOnqD,KAAK07B,OAAOd,SAAW56B,KAAK07B,OAAOsQ,SAAWhsC,KAAK07B,OAAOjD,OAAO2X,kBAAkB7Q,6DAmatFv/B,KAAK8lD,UACE9lD,KAAK40B,SAASqxB,UAAUpxB,UAG5B70B,KAAK40B,SAASoxB,MAAMzV,2DAIpBtwC,OAAOkD,KAAKnD,KAAK4lD,WAAW,GAAGY,OAAO,IAAItuC,SAAS,qDAItDlY,KAAKkoD,aACEloD,KAAK4lD,WAAW,GAAGY,OAAO,GAAGjlC,EAAIvhB,KAAK4lD,WAAW,GAAGY,OAAO,GAAGhB,EAGlExlD,KAAK4lD,WAAW,GAAGje,MAAQ3nC,KAAK4lD,WAAW,GAAGrb,2DAIjDvqC,KAAK8lD,UAEEj+C,KAAKyF,MAAMtN,KAAK07B,OAAOb,MAAMovB,YAAcjqD,KAAK0pD,kBAGpD7hD,KAAKyF,MAAMtN,KAAK07B,OAAOb,MAAMovB,YAAcjqD,KAAK0pD,iBAAmB,sDAItE1pD,KAAK8lD,UACE9lD,KAAKqqD,6BAGTrqD,KAAKsqD,2CAGQr3B,GAChBjzB,KAAK8lD,eACAuE,6BAA+Bp3B,OAE/Bq3B,6BAA+Br3B,WCthB1CjoB,OAAS,CAEXu/C,eAFW,SAEIx/C,EAAMjH,cACb4E,KAAG+L,OAAO3Q,GACVkyB,cAAcjrB,EAAM/K,KAAK66B,MAAO,CAC5BrlB,IAAK1R,IAEF4E,KAAGoqB,MAAMhvB,IAChBA,EAAWhC,QAAQ,SAAA+B,GACfmyB,cAAcjrB,EAAMlJ,EAAKg5B,MAAOh3B,MAO5C2mD,OAhBW,SAgBJv5B,cACEgM,QAAQhM,EAAO,mBAMpBoK,MAAMc,eAAep8B,KAAKC,WAGrBmkD,QAAQpkD,KACTC,KACA,WAEIo0B,EAAKZ,QAAQ0I,QAAU,GAGvBjG,cAAc7B,EAAKyG,OACnBzG,EAAKyG,MAAQ,KAGTnyB,KAAGuqB,QAAQmB,EAAKQ,SAASC,YACzBT,EAAKQ,SAASC,UAAUsC,gBAAgB,aAIpCiG,EAAkBnM,EAAlBmM,QAASryB,EAASkmB,EAATlmB,sBAC6BqyB,EAf5C,UAeOtD,SAAAA,OAfP,IAAA2wB,EAekBlZ,UAAUlW,MAf5BovB,EAemCj1C,EAfnCk1C,EAemCl1C,IAC/BmzC,EAAuB,UAAb7uB,EAAuB/uB,EAAO,MACxCjH,EAA0B,UAAbg2B,EAAuB,GAAK,CAAEtkB,IAAAA,GAEjDvV,OAAO+hB,OAAOoS,EAAM,CAChB0F,SAAAA,EACA/uB,KAAAA,EAEAwoB,UAAWoG,QAAQtnB,MAAMtH,EAAM+uB,EAAU1F,EAAKqE,OAAOsB,aAErDc,MAAO91B,cAAc4jD,EAAS7kD,KAIlCswB,EAAKQ,SAASC,UAAU5vB,YAAYmvB,EAAKyG,OAGrCnyB,KAAGkqB,QAAQ3B,EAAMyc,YACjBtZ,EAAKqE,OAAOiV,SAAWzc,EAAMyc,UAI7BtZ,EAAKwG,UACDxG,EAAKqE,OAAOkyB,aACZv2B,EAAKyG,MAAMjF,aAAa,cAAe,IAEvCxB,EAAKqE,OAAOiV,UACZtZ,EAAKyG,MAAMjF,aAAa,WAAY,IAEnCltB,KAAGqlB,MAAMkD,EAAMye,UAChBtb,EAAKsb,OAASze,EAAMye,QAEpBtb,EAAKqE,OAAOyV,KAAK9B,QACjBhY,EAAKyG,MAAMjF,aAAa,OAAQ,IAEhCxB,EAAKqE,OAAOmO,OACZxS,EAAKyG,MAAMjF,aAAa,QAAS,IAEjCxB,EAAKqE,OAAOsB,aACZ3F,EAAKyG,MAAMjF,aAAa,cAAe,KAK/CsE,GAAG6Z,aAAah0C,KAAKq0B,GAGjBA,EAAKwG,SACL5vB,OAAOu/C,eAAexqD,KAAKq0B,EAAM,SAAUgJ,GAI/ChJ,EAAKqE,OAAO2G,MAAQnO,EAAMmO,MAG1BvE,MAAMkR,MAAMhsC,KAAKq0B,GAGbA,EAAKwG,SAED36B,OAAOkD,KAAK8tB,GAAO/Y,SAAS,WAC5BlN,OAAOu/C,eAAexqD,KAAKq0B,EAAM,QAASnD,EAAMkY,SAKpD/U,EAAKwG,SAAYxG,EAAKgX,UAAYhX,EAAKb,UAAU2G,KAEjDA,GAAG8Z,MAAMj0C,KAAKq0B,GAIdA,EAAKwG,SACLxG,EAAKyG,MAAMoB,OAIX7H,EAAKgc,mBACLhc,EAAKgc,kBAAkBnU,OAI3B7H,EAAKsO,WAAWhC,WAEpB,SA7GKrE,MAAM8G,KAAK,2BCItBynB,2BACUh/C,EAAQ4nB,8CACXmhB,OAAS,QAGTjgB,OAAQ,OACRqb,SAAU,OACV8a,QAAS,OAGT5vB,MAAQtB,QAAQsB,WAGhBJ,MAAQjvB,EAGTlD,KAAG+L,OAAOzU,KAAK66B,cACVA,MAAQj7B,SAAS+3B,iBAAiB33B,KAAK66B,SAI3Ch8B,OAAOisD,QAAU9qD,KAAK66B,iBAAiBiwB,QAAWpiD,KAAGsqB,SAAShzB,KAAK66B,QAAUnyB,KAAGoqB,MAAM9yB,KAAK66B,eAEvFA,MAAQ76B,KAAK66B,MAAM,SAIvBpC,OAASgD,OACV,GACAgS,SACAmd,EAAKnd,SACLja,GAAW,GACV,sBAEcsJ,KAAKC,MAAMl7B,EAAKg5B,MAAMU,aAAa,qBAC5C,MAAOn8B,SACE,IAJd,SAUAw1B,SAAW,CACZC,UAAW,KACX4N,SAAU,KACVP,QAAS,GACT3sB,QAAS,GACTotB,SAAU,GACVC,OAAQ,GACRJ,SAAU,CACNqH,MAAO,KACP5F,KAAM,KACNyE,OAAQ,GACRxG,QAAS,UAKZO,SAAW,CACZ2J,OAAQ,KACR9F,cAAe,EACf9kB,KAAM,IAAIkQ,cAITgR,WAAa,CACd0J,QAAQ,QAIP5Y,QAAU,CACX+S,MAAO,GACPrK,QAAS,SAKRG,MAAQ,IAAIsV,QAAQ3xC,KAAKy4B,OAAO4D,YAGhCA,MAAMC,IAAI,SAAUt8B,KAAKy4B,aACzB4D,MAAMC,IAAI,UAAW3C,UAGtBjxB,KAAGiqB,gBAAgB3yB,KAAK66B,QAAWnyB,KAAGuqB,QAAQjzB,KAAK66B,UAMnD76B,KAAK66B,MAAMvG,UACN+H,MAAM8G,KAAK,gCAKfnjC,KAAKy4B,OAAO8G,WAOZ5F,QAAQtnB,QAAQ4nB,SAMfmQ,EAAQpqC,KAAK66B,MAAM3F,WAAU,GACnCkV,EAAMsD,UAAW,OACZ9Y,SAASvkB,SAAW+5B,MAInBr/B,EAAO/K,KAAK66B,MAAM8tB,QAAQrqB,cAG5BjpB,EAAS,KACT7Q,EAAM,YAGFuG,OACC,SAEDsK,EAASrV,KAAK66B,MAAM/C,cAAc,UAG9BpvB,KAAGuqB,QAAQ5d,OAEX7Q,EAAMonC,SAASv2B,EAAOkmB,aAAa,aAC9BzB,SAAW2X,iBAAiBjtC,EAAIhD,iBAGhCozB,SAASC,UAAY70B,KAAK66B,WAC1BA,MAAQxlB,OAGRuf,SAASC,UAAUiC,UAAY,GAGhCtyB,EAAIgB,OAAOrD,OAAQ,KACb4oD,EAAS,CAAC,IAAK,QAEjBA,EAAO7yC,SAAS1T,EAAIH,aAAalE,IAAI,oBAChCs4B,OAAOiV,UAAW,GAEvBqd,EAAO7yC,SAAS1T,EAAIH,aAAalE,IAAI,gBAChCs4B,OAAOyV,KAAK9B,QAAS,GAK1BpsC,KAAKisC,gBACAxT,OAAOsB,YAAcgxB,EAAO7yC,SAAS1T,EAAIH,aAAalE,IAAI,qBAC1Ds4B,OAAOwG,QAAQ+e,GAAKx5C,EAAIH,aAAalE,IAAI,YAEzCs4B,OAAOsB,aAAc,aAK7BD,SAAW95B,KAAK66B,MAAMU,aAAav7B,KAAKy4B,OAAO30B,WAAWgpC,MAAMhT,eAGhEe,MAAM1D,gBAAgBn3B,KAAKy4B,OAAO30B,WAAWgpC,MAAMhT,aAIxDpxB,KAAGqlB,MAAM/tB,KAAK85B,YAAc75B,OAAOkD,KAAKouC,WAAWr5B,SAASlY,KAAK85B,2BAC5DuC,MAAM37B,MAAM,uCAKhBqK,KAAOymC,MAAM3X,gBAIjB,YACA,aACI9uB,KAAOA,OACP+uB,SAAWyX,UAAUlW,MAGtBr7B,KAAK66B,MAAMud,aAAa,sBACnB3f,OAAOkyB,aAAc,GAE1B3qD,KAAK66B,MAAMud,aAAa,mBACnB3f,OAAOiV,UAAW,IAEvB1tC,KAAK66B,MAAMud,aAAa,gBAAkBp4C,KAAK66B,MAAMud,aAAa,8BAC7D3f,OAAOsB,aAAc,GAE1B/5B,KAAK66B,MAAMud,aAAa,gBACnB3f,OAAOmO,OAAQ,GAEpB5mC,KAAK66B,MAAMud,aAAa,eACnB3f,OAAOyV,KAAK9B,QAAS,kCAMzB/P,MAAM37B,MAAM,uCAKpB6yB,UAAYoG,QAAQtnB,MAAMrS,KAAK+K,KAAM/K,KAAK85B,SAAU95B,KAAKy4B,OAAOsB,aAGhE/5B,KAAKuzB,UAAU0G,UAKfpG,eAAiB,QAGjBuS,UAAY,IAAIiP,UAAUr1C,WAG1Bw/B,QAAU,IAAIF,QAAQt/B,WAGtB66B,MAAMvG,KAAOt0B,KAGb0I,KAAGuqB,QAAQjzB,KAAK40B,SAASC,kBACrBD,SAASC,UAAY9vB,cAAc,MAAO,CAAEimD,SAAU,IAC3Dl2B,KAAK90B,KAAK66B,MAAO76B,KAAK40B,SAASC,YAInCqF,GAAG6Z,aAAah0C,KAAKC,MAGrB66B,MAAMkR,MAAMhsC,KAAKC,MAGbA,KAAKy4B,OAAO4D,OACZvI,GAAG/zB,KAAKC,KAAMA,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAO7E,OAAOtwB,KAAK,KAAM,SAAAjE,GACjEwC,EAAKw6B,MAAMC,IAAX,UAAAjyB,OAAyBhL,EAAM0L,UAMnC/K,KAAK46B,SAAY56B,KAAKorC,UAAYprC,KAAKuzB,UAAU2G,KACjDA,GAAG8Z,MAAMj0C,KAAKC,WAIbomC,UAAUvR,iBAGVuR,UAAU9lC,cAGVoiC,WAAa,IAAI8P,WAAWxyC,MAG7BA,KAAKy4B,OAAOmX,IAAIrQ,eACXqQ,IAAM,IAAIyP,IAAIr/C,OAInBA,KAAKy4B,OAAOiV,eACP1R,YAIJ6Y,aAAe,EAGhB70C,KAAKy4B,OAAO2X,kBAAkB7Q,eACzB6Q,kBAAoB,IAAIuV,kBAAkB3lD,aAhE1Cq8B,MAAM37B,MAAM,sCA7GZ27B,MAAM37B,MAAM,sCAPZ27B,MAAM37B,MAAM,8CAZZ27B,MAAM37B,MAAM,uGAuOhBgI,KAAGmqB,SAAS7yB,KAAK66B,MAAMmB,MAKrBh8B,KAAK66B,MAAMmB,OAJP,qCAWNh8B,KAAK6vC,SAAYnnC,KAAGmqB,SAAS7yB,KAAK66B,MAAMsH,aAIxCtH,MAAMsH,2CAmCJlR,IAEQvoB,KAAGkqB,QAAQ3B,GAASA,GAASjxB,KAAK6vC,cAGxC7T,YAEAmG,uCAQLniC,KAAK46B,cACAuH,aACAC,WACE15B,KAAGmqB,SAAS7yB,KAAK66B,MAAMmhB,YACzBnhB,MAAMmhB,8CAQVrgB,YAAc,iCAOhBwD,QACExD,YAAc37B,KAAK27B,aAAejzB,KAAGsoB,OAAOmO,GAAYA,EAAWn/B,KAAKy4B,OAAO0G,0CAOhFA,QACCxD,YAAc37B,KAAK27B,aAAejzB,KAAGsoB,OAAOmO,GAAYA,EAAWn/B,KAAKy4B,OAAO0G,iDAgIzEhwB,OACL2zB,EAAS9iC,KAAK66B,MAAM+L,MAAQ,EAAI5mC,KAAK8iC,YACtCA,OAASA,GAAUp6B,KAAGsoB,OAAO7hB,GAAQA,EAAO,0CAOtCA,QACN8mC,gBAAgB9mC,0CAwRV8hB,GACXwR,SAAStW,OAAOpsB,KAAKC,KAAMixB,GAAO,qCAwF9B0I,QAAQa,cACHK,MAAMowB,wEAQJ9+B,MAEPnsB,KAAKuzB,UAAU2G,KAAOl6B,KAAKy3C,QAAS,KAE9ByT,EAAWzzB,SAASz3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWqV,cAGpE1W,OAA0B,IAAXlL,OAAyBxsB,GAAawsB,EAGrDg/B,EAAS/zB,YAAYp3B,KAAK40B,SAASC,UAAW70B,KAAKy4B,OAAOC,WAAWqV,aAAc1W,MAGrF8zB,GAAUnrD,KAAKy4B,OAAOiJ,SAASxpB,SAAS,cAAgBxP,KAAGqlB,MAAM/tB,KAAKy4B,OAAO+J,WAC7Ed,SAASqI,WAAWhqC,KAAKC,MAAM,GAI/BmrD,IAAWD,EAAU,KACfE,EAAYD,EAAS,iBAAmB,gBAC9C92B,aAAat0B,KAAKC,KAAMA,KAAK66B,MAAOuwB,UAGhCD,SAGL,6BAQR9rD,EAAO2D,GACN8wB,GAAG/zB,KAAKC,KAAMA,KAAK40B,SAASC,UAAWx1B,EAAO2D,gCAQ7C3D,EAAO2D,GACRgxB,KAAKj0B,KAAKC,KAAMA,KAAK40B,SAASC,UAAWx1B,EAAO2D,+BAQhD3D,EAAO2D,GACP+wB,IAAI/zB,KAAK40B,SAASC,UAAWx1B,EAAO2D,mCAUhCA,cAAUqoD,EAAcvlD,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,IAAAA,UAAA,MACvB9F,KAAK00B,WAIJzzB,EAAO,WAETrB,SAASyF,KAAKiQ,MAAM48B,SAAW,GAG/B9d,EAAK0Y,MAAQ,KAGTue,GACIprD,OAAOkD,KAAKixB,EAAKQ,UAAUzyB,SAE3B8zB,cAAc7B,EAAKQ,SAASsN,QAAQlG,MACpC/F,cAAc7B,EAAKQ,SAAS6N,UAC5BxM,cAAc7B,EAAKQ,SAAS8M,UAC5BzL,cAAc7B,EAAKQ,SAASnR,SAG5B2Q,EAAKQ,SAASsN,QAAQlG,KAAO,KAC7B5H,EAAKQ,SAAS6N,SAAW,KACzBrO,EAAKQ,SAAS8M,SAAW,KACzBtN,EAAKQ,SAASnR,QAAU,MAIxB/a,KAAGmqB,SAAS7vB,IACZA,MAIJwxB,gBAAgBz0B,KAAKq0B,GAGrBiC,eAAejC,EAAKQ,SAASvkB,SAAU+jB,EAAKQ,SAASC,WAGrDR,aAAat0B,KAAKq0B,EAAMA,EAAKQ,SAASvkB,SAAU,aAAa,GAGzD3H,KAAGmqB,SAAS7vB,IACZA,EAASjD,KAAKq0B,EAAKQ,SAASvkB,UAIhC+jB,EAAKM,OAAQ,EAGb5J,WAAW,WACPsJ,EAAKQ,SAAW,KAChBR,EAAKyG,MAAQ,MACd,YAKNmhB,OAGDh8C,KAAK46B,SAEL8Z,aAAa10C,KAAK20C,OAAO5E,SAGzB7V,GAAGkJ,qBAAqBrjC,KAAKC,MAAM,GAGnCiB,KACOjB,KAAKisC,WAEZ8S,cAAc/+C,KAAK20C,OAAOqK,WAC1BD,cAAc/+C,KAAK20C,OAAO9E,SAGP,OAAf7vC,KAAK8sC,OAAkBpkC,KAAGmqB,SAAS7yB,KAAK8sC,MAAMqX,eACzCrX,MAAMqX,UAIfljD,KACOjB,KAAK0pC,UAGO,OAAf1pC,KAAK8sC,YACAA,MAAMwe,SAASp/B,KAAKjrB,GAI7B6pB,WAAW7pB,EAAM,wCAQhB8J,UACE4uB,QAAQe,KAAK36B,KAAKC,KAAM+K,0CAhyBxBomB,QAAQnxB,KAAK85B,WAAayX,UAAUlW,8CAIpClK,QAAQnxB,KAAKisC,WAAajsC,KAAK0pC,kDAI/BvY,QAAQnxB,KAAK85B,WAAayX,UAAUtS,gDAIpC9N,QAAQnxB,KAAK85B,WAAayX,UAAUvS,8CAIpC7N,QAAQnxB,KAAK+K,OAASymC,MAAM3X,8CAI5B1I,QAAQnxB,KAAK+K,OAASymC,MAAM5X,8CA8B5BzI,QAAQnxB,KAAK00B,QAAU10B,KAAK67B,SAAW77B,KAAK03C,6CAO5CvmB,QAAQnxB,KAAK66B,MAAMgB,+CAOnB1K,QAAQnxB,KAAK67B,QAA+B,IAArB77B,KAAK27B,kDAO5BxK,QAAQnxB,KAAK66B,MAAM6c,yCAyDdzmB,MAEPjxB,KAAKgjC,cAKJuoB,EAAe7iD,KAAGsoB,OAAOC,IAAUA,EAAQ,OAG5C4J,MAAMc,YAAc4vB,EAAe1jD,KAAK4F,IAAIwjB,EAAOjxB,KAAKgjC,UAAY,OAGpE3G,MAAMC,IAAX,cAAAjyB,OAA6BrK,KAAK27B,YAAlC,qCAOOrK,OAAOtxB,KAAK66B,MAAMc,kDAOjBuL,EAAalnC,KAAK66B,MAAlBqM,gBAGJx+B,KAAGsoB,OAAOkW,GACHA,EAMPA,GAAYA,EAAS/kC,QAAUnC,KAAKgjC,SAAW,EACxCkE,EAAS+H,IAAI,GAAKjvC,KAAKgjC,SAG3B,yCAOA7R,QAAQnxB,KAAK66B,MAAMoN,8CAQpBujB,EAAehlB,WAAWxmC,KAAKy4B,OAAOuK,UAGtCyoB,GAAgBzrD,KAAK66B,OAAS,IAAImI,SAClCA,EAAYt6B,KAAGsoB,OAAOy6B,IAAiBA,IAAiBC,EAAAA,EAAeD,EAAJ,SAGlED,GAAgBxoB,+BAOhBjiC,OACH+hC,EAAS/hC,EAIT2H,KAAG+L,OAAOquB,KACVA,EAASxR,OAAOwR,IAIfp6B,KAAGsoB,OAAO8R,KACXA,EAAS9iC,KAAKw/B,QAAQr/B,IAAI,WAIzBuI,KAAGsoB,OAAO8R,KACRA,EAAW9iC,KAAKy4B,OAAhBqK,QAIHA,EAlBQ,IAmBRA,EAnBQ,GAsBRA,EArBQ,IAsBRA,EAtBQ,QA0BPrK,OAAOqK,OAASA,OAGhBjI,MAAMiI,OAASA,GAGfp6B,KAAGqlB,MAAMhtB,IAAUf,KAAK4mC,OAAS9D,EAAS,SACtC8D,OAAQ,0BAQVtV,OAAOtxB,KAAK66B,MAAMiI,oCAwBnBP,OACFpW,EAASoW,EAGR75B,KAAGkqB,QAAQzG,KACZA,EAASnsB,KAAKw/B,QAAQr/B,IAAI,UAIzBuI,KAAGkqB,QAAQzG,KACZA,EAASnsB,KAAKy4B,OAAOmO,YAIpBnO,OAAOmO,MAAQza,OAGf0O,MAAM+L,MAAQza,yBAOZgF,QAAQnxB,KAAK66B,MAAM+L,+CAQrB5mC,KAAK46B,YAIN56B,KAAKy3C,UAMLtmB,QAAQnxB,KAAK66B,MAAM8wB,cACnBx6B,QAAQnxB,KAAK66B,MAAM+wB,8BACnBz6B,QAAQnxB,KAAK66B,MAAMgxB,aAAe7rD,KAAK66B,MAAMgxB,YAAY1pD,sCAQvD8uB,OACFsV,EAAQ,KAER79B,KAAGsoB,OAAOC,KACVsV,EAAQtV,GAGPvoB,KAAGsoB,OAAOuV,KACXA,EAAQvmC,KAAKw/B,QAAQr/B,IAAI,UAGxBuI,KAAGsoB,OAAOuV,KACXA,EAAQvmC,KAAKy4B,OAAO8N,MAAM4H,UAI1B5H,EAAQ,KACRA,EAAQ,IAERA,EAAQ,IACRA,EAAQ,GAGPvmC,KAAKy4B,OAAO8N,MAAM/S,QAAQtb,SAASquB,SAMnC9N,OAAO8N,MAAM4H,SAAW5H,OAGxB1L,MAAM2jB,aAAejY,QARjBlK,MAAM8G,KAAX,sBAAA94B,OAAsCk8B,EAAtC,6BAeGjV,OAAOtxB,KAAK66B,MAAM2jB,4CAQjBvtB,OACFwH,EAASz4B,KAAKy4B,OAAOyD,QACrB1I,EAAUxzB,KAAKwzB,QAAQ0I,WAExB1I,EAAQrxB,YAIT+5B,EAAU,EACTxzB,KAAGqlB,MAAMkD,IAAUK,OAAOL,GAC3BjxB,KAAKw/B,QAAQr/B,IAAI,WACjBs4B,EAAO0V,SACP1V,EAAOkQ,SACT92B,KAAKnJ,KAAGsoB,QAEN86B,GAAgB,MAEft4B,EAAQtb,SAASgkB,GAAU,KACtBn7B,EAAQy7B,QAAQhJ,EAAS0I,QAC1BG,MAAM8G,KAAX,+BAAA94B,OAA+C6xB,EAA/C,YAAA7xB,OAAiEtJ,EAAjE,aACAm7B,EAAUn7B,EAGV+qD,GAAgB,EAIpBrzB,EAAO0V,SAAWjS,OAGbrB,MAAMqB,QAAUA,EAGjB4vB,QACKtsB,QAAQz8B,IAAI,CAAEm5B,QAAAA,4BAQhBl8B,KAAK66B,MAAMqB,mCAQbjL,OACC9E,EAASzjB,KAAGkqB,QAAQ3B,GAASA,EAAQjxB,KAAKy4B,OAAOyV,KAAK9B,YACvD3T,OAAOyV,KAAK9B,OAASjgB,OACrB0O,MAAMqT,KAAO/hB,yBAkDXgF,QAAQnxB,KAAK66B,MAAMqT,mCAOnBjd,GACPjmB,OAAOw/C,OAAOzqD,KAAKC,KAAMixB,0BAOlBjxB,KAAK66B,MAAMwhB,gDAOVvR,EAAa9qC,KAAKy4B,OAAO0S,KAAzBL,gBAEDpiC,KAAGlE,IAAIsmC,GAAYA,EAAW9qC,KAAKgL,oCAOnCimB,GACFjxB,KAAKgsC,QAKV9R,GAAGia,UAAUp0C,KAAKC,KAAMixB,GAAO,GAAOd,MAAM,mBAJnCkM,MAAM8G,KAAK,2DAWfnjC,KAAKgsC,QAIHhsC,KAAK66B,MAAMU,aAAa,UAHpB,oCAUFtK,OACH9E,EAASzjB,KAAGkqB,QAAQ3B,GAASA,EAAQjxB,KAAKy4B,OAAOiV,cAClDjV,OAAOiV,SAAWvhB,yBAOhBgF,QAAQnxB,KAAKy4B,OAAOiV,6CAedzc,GACbwR,SAAS1/B,IAAIhD,KAAKC,KAAMixB,GAAO,yBAOGjxB,KAAKyiC,SAA/B6G,EADOgD,EACPhD,QAAShD,EADFgG,EACEhG,oBACVgD,EAAUhD,GAAgB,iCAQxBrV,GACTwR,SAASiK,YAAY3sC,KAAKC,KAAMixB,GAAO,0BAO/BwR,SAAS0K,gBAAgBptC,KAAKC,OAAS,IAAIupC,mCAQ/CtY,MAEC0I,QAAQS,SAKPjO,EAASzjB,KAAGkqB,QAAQ3B,GAASA,GAASjxB,KAAKo6B,IAI7C1xB,KAAGmqB,SAAS7yB,KAAK66B,MAAMR,iCAClBQ,MAAMR,0BAA0BlO,EAASiO,IAAIgS,OAAShS,IAAIkX,UAI/D5oC,KAAGmqB,SAAS7yB,KAAK66B,MAAMkxB,4BAClB/rD,KAAKo6B,KAAOjO,OACR0O,MAAMkxB,0BACJ/rD,KAAKo6B,MAAQjO,GACpBvsB,SAASosD,gDASZryB,QAAQS,IAKR1xB,KAAGqlB,MAAM/tB,KAAK66B,MAAMoxB,wBAKlBjsD,KAAK66B,QAAUj7B,SAASssD,wBAJpBlsD,KAAK66B,MAAMoxB,yBAA2B7xB,IAAIgS,OAL1C,yCAuMErhC,EAAM+uB,EAAUqyB,UACtBxyB,QAAQtnB,MAAMtH,EAAM+uB,EAAUqyB,sCAQvB3nD,EAAKyF,UACZq2B,WAAW97B,EAAKyF,iCAQd4sB,OAAUrD,EAAc1tB,UAAA3D,OAAA,QAAAxC,IAAAmG,UAAA,GAAAA,UAAA,GAAJ,GACzBivB,EAAU,YAEVrsB,KAAG+L,OAAOoiB,GACV9B,EAAU7nB,MAAM8B,KAAKpP,SAAS+3B,iBAAiBd,IACxCnuB,KAAGsqB,SAAS6D,GACnB9B,EAAU7nB,MAAM8B,KAAK6nB,GACdnuB,KAAGoqB,MAAM+D,KAChB9B,EAAU8B,EAASrB,OAAO9sB,KAAGuqB,UAG7BvqB,KAAGqlB,MAAMgH,GACF,KAGJA,EAAQuC,IAAI,SAAA80B,UAAK,IAAIxB,EAAKwB,EAAG54B,cAI5Co3B,KAAKnd,SAAW5Q,UAAU4Q","file":"plyr.polyfilled.min.mjs","sourcesContent":["// Polyfill for creating CustomEvents on IE9/10/11\n\n// code pulled from:\n// https://github.com/d4tocchini/customevent-polyfill\n// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill\n\n(function() {\n if (typeof window === 'undefined') {\n return;\n }\n\n try {\n var ce = new window.CustomEvent('test', { cancelable: true });\n ce.preventDefault();\n if (ce.defaultPrevented !== true) {\n // IE has problems with .preventDefault() on custom events\n // http://stackoverflow.com/questions/23349191\n throw new Error('Could not prevent default');\n }\n } catch (e) {\n var CustomEvent = function(event, params) {\n var evt, origPrevent;\n params = params || {\n bubbles: false,\n cancelable: false,\n detail: undefined\n };\n\n evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(\n event,\n params.bubbles,\n params.cancelable,\n params.detail\n );\n origPrevent = evt.preventDefault;\n evt.preventDefault = function() {\n origPrevent.call(this);\n try {\n Object.defineProperty(this, 'defaultPrevented', {\n get: function() {\n return true;\n }\n });\n } catch (e) {\n this.defaultPrevented = true;\n }\n };\n return evt;\n };\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent; // expose definition to window\n }\n})();\n","(function(global) {\r\n /**\r\n * Polyfill URLSearchParams\r\n *\r\n * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js\r\n */\r\n\r\n var checkIfIteratorIsSupported = function() {\r\n try {\r\n return !!Symbol.iterator;\r\n } catch (error) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var iteratorSupported = checkIfIteratorIsSupported();\r\n\r\n var createIterator = function(items) {\r\n var iterator = {\r\n next: function() {\r\n var value = items.shift();\r\n return { done: value === void 0, value: value };\r\n }\r\n };\r\n\r\n if (iteratorSupported) {\r\n iterator[Symbol.iterator] = function() {\r\n return iterator;\r\n };\r\n }\r\n\r\n return iterator;\r\n };\r\n\r\n /**\r\n * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing\r\n * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.\r\n */\r\n var serializeParam = function(value) {\r\n return encodeURIComponent(value).replace(/%20/g, '+');\r\n };\r\n\r\n var deserializeParam = function(value) {\r\n return decodeURIComponent(value).replace(/\\+/g, ' ');\r\n };\r\n\r\n var polyfillURLSearchParams = function() {\r\n\r\n var URLSearchParams = function(searchString) {\r\n Object.defineProperty(this, '_entries', { writable: true, value: {} });\r\n var typeofSearchString = typeof searchString;\r\n\r\n if (typeofSearchString === 'undefined') {\r\n // do nothing\r\n } else if (typeofSearchString === 'string') {\r\n if (searchString !== '') {\r\n this._fromString(searchString);\r\n }\r\n } else if (searchString instanceof URLSearchParams) {\r\n var _this = this;\r\n searchString.forEach(function(value, name) {\r\n _this.append(name, value);\r\n });\r\n } else if ((searchString !== null) && (typeofSearchString === 'object')) {\r\n if (Object.prototype.toString.call(searchString) === '[object Array]') {\r\n for (var i = 0; i < searchString.length; i++) {\r\n var entry = searchString[i];\r\n if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {\r\n this.append(entry[0], entry[1]);\r\n } else {\r\n throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\\'s input');\r\n }\r\n }\r\n } else {\r\n for (var key in searchString) {\r\n if (searchString.hasOwnProperty(key)) {\r\n this.append(key, searchString[key]);\r\n }\r\n }\r\n }\r\n } else {\r\n throw new TypeError('Unsupported input\\'s type for URLSearchParams');\r\n }\r\n };\r\n\r\n var proto = URLSearchParams.prototype;\r\n\r\n proto.append = function(name, value) {\r\n if (name in this._entries) {\r\n this._entries[name].push(String(value));\r\n } else {\r\n this._entries[name] = [String(value)];\r\n }\r\n };\r\n\r\n proto.delete = function(name) {\r\n delete this._entries[name];\r\n };\r\n\r\n proto.get = function(name) {\r\n return (name in this._entries) ? this._entries[name][0] : null;\r\n };\r\n\r\n proto.getAll = function(name) {\r\n return (name in this._entries) ? this._entries[name].slice(0) : [];\r\n };\r\n\r\n proto.has = function(name) {\r\n return (name in this._entries);\r\n };\r\n\r\n proto.set = function(name, value) {\r\n this._entries[name] = [String(value)];\r\n };\r\n\r\n proto.forEach = function(callback, thisArg) {\r\n var entries;\r\n for (var name in this._entries) {\r\n if (this._entries.hasOwnProperty(name)) {\r\n entries = this._entries[name];\r\n for (var i = 0; i < entries.length; i++) {\r\n callback.call(thisArg, entries[i], name, this);\r\n }\r\n }\r\n }\r\n };\r\n\r\n proto.keys = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push(name);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.values = function() {\r\n var items = [];\r\n this.forEach(function(value) {\r\n items.push(value);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.entries = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n if (iteratorSupported) {\r\n proto[Symbol.iterator] = proto.entries;\r\n }\r\n\r\n proto.toString = function() {\r\n var searchArray = [];\r\n this.forEach(function(value, name) {\r\n searchArray.push(serializeParam(name) + '=' + serializeParam(value));\r\n });\r\n return searchArray.join('&');\r\n };\r\n\r\n\r\n global.URLSearchParams = URLSearchParams;\r\n };\r\n\r\n if (!('URLSearchParams' in global) || (new URLSearchParams('?a=1').toString() !== 'a=1')) {\r\n polyfillURLSearchParams();\r\n }\r\n\r\n var proto = URLSearchParams.prototype;\r\n\r\n if (typeof proto.sort !== 'function') {\r\n proto.sort = function() {\r\n var _this = this;\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n if (!_this._entries) {\r\n _this.delete(name);\r\n }\r\n });\r\n items.sort(function(a, b) {\r\n if (a[0] < b[0]) {\r\n return -1;\r\n } else if (a[0] > b[0]) {\r\n return +1;\r\n } else {\r\n return 0;\r\n }\r\n });\r\n if (_this._entries) { // force reset because IE keeps keys index\r\n _this._entries = {};\r\n }\r\n for (var i = 0; i < items.length; i++) {\r\n this.append(items[i][0], items[i][1]);\r\n }\r\n };\r\n }\r\n\r\n if (typeof proto._fromString !== 'function') {\r\n Object.defineProperty(proto, '_fromString', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function(searchString) {\r\n if (this._entries) {\r\n this._entries = {};\r\n } else {\r\n var keys = [];\r\n this.forEach(function(value, name) {\r\n keys.push(name);\r\n });\r\n for (var i = 0; i < keys.length; i++) {\r\n this.delete(keys[i]);\r\n }\r\n }\r\n\r\n searchString = searchString.replace(/^\\?/, '');\r\n var attributes = searchString.split('&');\r\n var attribute;\r\n for (var i = 0; i < attributes.length; i++) {\r\n attribute = attributes[i].split('=');\r\n this.append(\r\n deserializeParam(attribute[0]),\r\n (attribute.length > 1) ? deserializeParam(attribute[1]) : ''\r\n );\r\n }\r\n }\r\n });\r\n }\r\n\r\n // HTMLAnchorElement\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n\r\n(function(global) {\r\n /**\r\n * Polyfill URL\r\n *\r\n * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js\r\n */\r\n\r\n var checkIfURLIsSupported = function() {\r\n try {\r\n var u = new URL('b', 'http://a');\r\n u.pathname = 'c%20d';\r\n return (u.href === 'http://a/c%20d') && u.searchParams;\r\n } catch (e) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var polyfillURL = function() {\r\n var _URL = global.URL;\r\n\r\n var URL = function(url, base) {\r\n if (typeof url !== 'string') url = String(url);\r\n\r\n // Only create another document if the base is different from current location.\r\n var doc = document, baseElement;\r\n if (base && (global.location === void 0 || base !== global.location.href)) {\r\n doc = document.implementation.createHTMLDocument('');\r\n baseElement = doc.createElement('base');\r\n baseElement.href = base;\r\n doc.head.appendChild(baseElement);\r\n try {\r\n if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);\r\n } catch (err) {\r\n throw new Error('URL unable to set base ' + base + ' due to ' + err);\r\n }\r\n }\r\n\r\n var anchorElement = doc.createElement('a');\r\n anchorElement.href = url;\r\n if (baseElement) {\r\n doc.body.appendChild(anchorElement);\r\n anchorElement.href = anchorElement.href; // force href to refresh\r\n }\r\n\r\n if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {\r\n throw new TypeError('Invalid URL');\r\n }\r\n\r\n Object.defineProperty(this, '_anchorElement', {\r\n value: anchorElement\r\n });\r\n\r\n\r\n // create a linked searchParams which reflect its changes on URL\r\n var searchParams = new URLSearchParams(this.search);\r\n var enableSearchUpdate = true;\r\n var enableSearchParamsUpdate = true;\r\n var _this = this;\r\n ['append', 'delete', 'set'].forEach(function(methodName) {\r\n var method = searchParams[methodName];\r\n searchParams[methodName] = function() {\r\n method.apply(searchParams, arguments);\r\n if (enableSearchUpdate) {\r\n enableSearchParamsUpdate = false;\r\n _this.search = searchParams.toString();\r\n enableSearchParamsUpdate = true;\r\n }\r\n };\r\n });\r\n\r\n Object.defineProperty(this, 'searchParams', {\r\n value: searchParams,\r\n enumerable: true\r\n });\r\n\r\n var search = void 0;\r\n Object.defineProperty(this, '_updateSearchParams', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function() {\r\n if (this.search !== search) {\r\n search = this.search;\r\n if (enableSearchParamsUpdate) {\r\n enableSearchUpdate = false;\r\n this.searchParams._fromString(this.search);\r\n enableSearchUpdate = true;\r\n }\r\n }\r\n }\r\n });\r\n };\r\n\r\n var proto = URL.prototype;\r\n\r\n var linkURLWithAnchorAttribute = function(attributeName) {\r\n Object.defineProperty(proto, attributeName, {\r\n get: function() {\r\n return this._anchorElement[attributeName];\r\n },\r\n set: function(value) {\r\n this._anchorElement[attributeName] = value;\r\n },\r\n enumerable: true\r\n });\r\n };\r\n\r\n ['hash', 'host', 'hostname', 'port', 'protocol']\r\n .forEach(function(attributeName) {\r\n linkURLWithAnchorAttribute(attributeName);\r\n });\r\n\r\n Object.defineProperty(proto, 'search', {\r\n get: function() {\r\n return this._anchorElement['search'];\r\n },\r\n set: function(value) {\r\n this._anchorElement['search'] = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperties(proto, {\r\n\r\n 'toString': {\r\n get: function() {\r\n var _this = this;\r\n return function() {\r\n return _this.href;\r\n };\r\n }\r\n },\r\n\r\n 'href': {\r\n get: function() {\r\n return this._anchorElement.href.replace(/\\?$/, '');\r\n },\r\n set: function(value) {\r\n this._anchorElement.href = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'pathname': {\r\n get: function() {\r\n return this._anchorElement.pathname.replace(/(^\\/?)/, '/');\r\n },\r\n set: function(value) {\r\n this._anchorElement.pathname = value;\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'origin': {\r\n get: function() {\r\n // get expected port from protocol\r\n var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];\r\n // add port to origin if, expected port is different than actual port\r\n // and it is not empty f.e http://foo:8080\r\n // 8080 != 80 && 8080 != ''\r\n var addPortToOrigin = this._anchorElement.port != expectedPort &&\r\n this._anchorElement.port !== '';\r\n\r\n return this._anchorElement.protocol +\r\n '//' +\r\n this._anchorElement.hostname +\r\n (addPortToOrigin ? (':' + this._anchorElement.port) : '');\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'password': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'username': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n });\r\n\r\n URL.createObjectURL = function(blob) {\r\n return _URL.createObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n URL.revokeObjectURL = function(url) {\r\n return _URL.revokeObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n global.URL = URL;\r\n\r\n };\r\n\r\n if (!checkIfURLIsSupported()) {\r\n polyfillURL();\r\n }\r\n\r\n if ((global.location !== void 0) && !('origin' in global.location)) {\r\n var getOrigin = function() {\r\n return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');\r\n };\r\n\r\n try {\r\n Object.defineProperty(global.location, 'origin', {\r\n get: getOrigin,\r\n enumerable: true\r\n });\r\n } catch (e) {\r\n setInterval(function() {\r\n global.location.origin = getOrigin();\r\n }, 100);\r\n }\r\n }\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var core = module.exports = { version: '2.6.3' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar TO_STRING = 'toString';\nvar $toString = Function[TO_STRING];\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","module.exports = {};\n","module.exports = false;\n","var core = require('./_core');\nvar global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\n\n(module.exports = function (key, value) {\n return store[key] || (store[key] = value !== undefined ? value : {});\n})('versions', []).push({\n version: core.version,\n mode: require('./_library') ? 'pure' : 'global',\n copyright: '© 2019 Denis Pushkarev (zloirock.ru)'\n});\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","'use strict';\nvar $defineProperty = require('./_object-dp');\nvar createDesc = require('./_property-desc');\n\nmodule.exports = function (object, index, value) {\n if (index in object) $defineProperty.f(object, index, createDesc(0, value));\n else object[index] = value;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","'use strict';\nvar ctx = require('./_ctx');\nvar $export = require('./_export');\nvar toObject = require('./_to-object');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar toLength = require('./_to-length');\nvar createProperty = require('./_create-property');\nvar getIterFn = require('./core.get-iterator-method');\n\n$export($export.S + $export.F * !require('./_iter-detect')(function (iter) { Array.from(iter); }), 'Array', {\n // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)\n from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {\n var O = toObject(arrayLike);\n var C = typeof this == 'function' ? this : Array;\n var aLen = arguments.length;\n var mapfn = aLen > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var index = 0;\n var iterFn = getIterFn(O);\n var length, result, step, iterator;\n if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);\n // if object isn't iterable or it's array with default iterator - use simple case\n if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {\n for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {\n createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);\n }\n } else {\n length = toLength(O.length);\n for (result = new C(length); length > index; index++) {\n createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);\n }\n }\n result.length = index;\n return result;\n }\n});\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","// 22.1.3.31 Array.prototype[@@unscopables]\nvar UNSCOPABLES = require('./_wks')('unscopables');\nvar ArrayProto = Array.prototype;\nif (ArrayProto[UNSCOPABLES] == undefined) require('./_hide')(ArrayProto, UNSCOPABLES, {});\nmodule.exports = function (key) {\n ArrayProto[UNSCOPABLES][key] = true;\n};\n","'use strict';\n// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(5);\nvar KEY = 'find';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n find: function find(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","exports.f = {}.propertyIsEnumerable;\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)\nvar $keys = require('./_object-keys-internal');\nvar hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype');\n\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {\n return $keys(O, hiddenKeys);\n};\n","module.exports = '\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003' +\n '\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';\n","var $export = require('./_export');\nvar defined = require('./_defined');\nvar fails = require('./_fails');\nvar spaces = require('./_string-ws');\nvar space = '[' + spaces + ']';\nvar non = '\\u200b\\u0085';\nvar ltrim = RegExp('^' + space + space + '*');\nvar rtrim = RegExp(space + space + '*$');\n\nvar exporter = function (KEY, exec, ALIAS) {\n var exp = {};\n var FORCE = fails(function () {\n return !!spaces[KEY]() || non[KEY]() != non;\n });\n var fn = exp[KEY] = FORCE ? exec(trim) : spaces[KEY];\n if (ALIAS) exp[ALIAS] = fn;\n $export($export.P + $export.F * FORCE, 'String', exp);\n};\n\n// 1 -> String#trimLeft\n// 2 -> String#trimRight\n// 3 -> String#trim\nvar trim = exporter.trim = function (string, TYPE) {\n string = String(defined(string));\n if (TYPE & 1) string = string.replace(ltrim, '');\n if (TYPE & 2) string = string.replace(rtrim, '');\n return string;\n};\n\nmodule.exports = exporter;\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","'use strict';\nvar global = require('./_global');\nvar has = require('./_has');\nvar cof = require('./_cof');\nvar inheritIfRequired = require('./_inherit-if-required');\nvar toPrimitive = require('./_to-primitive');\nvar fails = require('./_fails');\nvar gOPN = require('./_object-gopn').f;\nvar gOPD = require('./_object-gopd').f;\nvar dP = require('./_object-dp').f;\nvar $trim = require('./_string-trim').trim;\nvar NUMBER = 'Number';\nvar $Number = global[NUMBER];\nvar Base = $Number;\nvar proto = $Number.prototype;\n// Opera ~12 has broken Object#toString\nvar BROKEN_COF = cof(require('./_object-create')(proto)) == NUMBER;\nvar TRIM = 'trim' in String.prototype;\n\n// 7.1.3 ToNumber(argument)\nvar toNumber = function (argument) {\n var it = toPrimitive(argument, false);\n if (typeof it == 'string' && it.length > 2) {\n it = TRIM ? it.trim() : $trim(it, 3);\n var first = it.charCodeAt(0);\n var third, radix, maxCode;\n if (first === 43 || first === 45) {\n third = it.charCodeAt(2);\n if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix\n } else if (first === 48) {\n switch (it.charCodeAt(1)) {\n case 66: case 98: radix = 2; maxCode = 49; break; // fast equal /^0b[01]+$/i\n case 79: case 111: radix = 8; maxCode = 55; break; // fast equal /^0o[0-7]+$/i\n default: return +it;\n }\n for (var digits = it.slice(2), i = 0, l = digits.length, code; i < l; i++) {\n code = digits.charCodeAt(i);\n // parseInt parses a string to a first unavailable symbol\n // but ToNumber should return NaN if a string contains unavailable symbols\n if (code < 48 || code > maxCode) return NaN;\n } return parseInt(digits, radix);\n }\n } return +it;\n};\n\nif (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) {\n $Number = function Number(value) {\n var it = arguments.length < 1 ? 0 : value;\n var that = this;\n return that instanceof $Number\n // check on 1..constructor(foo) case\n && (BROKEN_COF ? fails(function () { proto.valueOf.call(that); }) : cof(that) != NUMBER)\n ? inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it);\n };\n for (var keys = require('./_descriptors') ? gOPN(Base) : (\n // ES3:\n 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +\n // ES6 (in case, if modules with ES6 Number statics required before):\n 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +\n 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger'\n ).split(','), j = 0, key; keys.length > j; j++) {\n if (has(Base, key = keys[j]) && !has($Number, key)) {\n dP($Number, key, gOPD(Base, key));\n }\n }\n $Number.prototype = proto;\n proto.constructor = $Number;\n require('./_redefine')(global, NUMBER, $Number);\n}\n","// most Object methods by ES6 should accept primitives\nvar $export = require('./_export');\nvar core = require('./_core');\nvar fails = require('./_fails');\nmodule.exports = function (KEY, exec) {\n var fn = (core.Object || {})[KEY] || Object[KEY];\n var exp = {};\n exp[KEY] = exec(fn);\n $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp);\n};\n","// 19.1.2.14 Object.keys(O)\nvar toObject = require('./_to-object');\nvar $keys = require('./_object-keys');\n\nrequire('./_object-sap')('keys', function () {\n return function keys(it) {\n return $keys(toObject(it));\n };\n});\n","// 7.2.8 IsRegExp(argument)\nvar isObject = require('./_is-object');\nvar cof = require('./_cof');\nvar MATCH = require('./_wks')('match');\nmodule.exports = function (it) {\n var isRegExp;\n return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');\n};\n","// helper for String#{startsWith, endsWith, includes}\nvar isRegExp = require('./_is-regexp');\nvar defined = require('./_defined');\n\nmodule.exports = function (that, searchString, NAME) {\n if (isRegExp(searchString)) throw TypeError('String#' + NAME + \" doesn't accept regex!\");\n return String(defined(that));\n};\n","var MATCH = require('./_wks')('match');\nmodule.exports = function (KEY) {\n var re = /./;\n try {\n '/./'[KEY](re);\n } catch (e) {\n try {\n re[MATCH] = false;\n return !'/./'[KEY](re);\n } catch (f) { /* empty */ }\n } return true;\n};\n","// 21.1.3.7 String.prototype.includes(searchString, position = 0)\n'use strict';\nvar $export = require('./_export');\nvar context = require('./_string-context');\nvar INCLUDES = 'includes';\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(INCLUDES), 'String', {\n includes: function includes(searchString /* , position = 0 */) {\n return !!~context(this, searchString, INCLUDES)\n .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","'use strict';\n// https://github.com/tc39/Array.prototype.includes\nvar $export = require('./_export');\nvar $includes = require('./_array-includes')(true);\n\n$export($export.P, 'Array', {\n includes: function includes(el /* , fromIndex = 0 */) {\n return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n\nrequire('./_add-to-unscopables')('includes');\n","// 7.2.9 SameValue(x, y)\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare\n return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;\n};\n","'use strict';\n\nvar classof = require('./_classof');\nvar builtinExec = RegExp.prototype.exec;\n\n // `RegExpExec` abstract operation\n// https://tc39.github.io/ecma262/#sec-regexpexec\nmodule.exports = function (R, S) {\n var exec = R.exec;\n if (typeof exec === 'function') {\n var result = exec.call(R, S);\n if (typeof result !== 'object') {\n throw new TypeError('RegExp exec method returned something other than an Object or null');\n }\n return result;\n }\n if (classof(R) !== 'RegExp') {\n throw new TypeError('RegExp#exec called on incompatible receiver');\n }\n return builtinExec.call(R, S);\n};\n","'use strict';\n// 21.2.5.3 get RegExp.prototype.flags\nvar anObject = require('./_an-object');\nmodule.exports = function () {\n var that = anObject(this);\n var result = '';\n if (that.global) result += 'g';\n if (that.ignoreCase) result += 'i';\n if (that.multiline) result += 'm';\n if (that.unicode) result += 'u';\n if (that.sticky) result += 'y';\n return result;\n};\n","'use strict';\n\nvar regexpFlags = require('./_flags');\n\nvar nativeExec = RegExp.prototype.exec;\n// This always refers to the native implementation, because the\n// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,\n// which loads this file before patching the method.\nvar nativeReplace = String.prototype.replace;\n\nvar patchedExec = nativeExec;\n\nvar LAST_INDEX = 'lastIndex';\n\nvar UPDATES_LAST_INDEX_WRONG = (function () {\n var re1 = /a/,\n re2 = /b*/g;\n nativeExec.call(re1, 'a');\n nativeExec.call(re2, 'a');\n return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0;\n})();\n\n// nonparticipating capturing group, copied from es5-shim's String#split patch.\nvar NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;\n\nvar PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED;\n\nif (PATCH) {\n patchedExec = function exec(str) {\n var re = this;\n var lastIndex, reCopy, match, i;\n\n if (NPCG_INCLUDED) {\n reCopy = new RegExp('^' + re.source + '$(?!\\\\s)', regexpFlags.call(re));\n }\n if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX];\n\n match = nativeExec.call(re, str);\n\n if (UPDATES_LAST_INDEX_WRONG && match) {\n re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex;\n }\n if (NPCG_INCLUDED && match && match.length > 1) {\n // Fix browsers whose `exec` methods don't consistently return `undefined`\n // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/\n // eslint-disable-next-line no-loop-func\n nativeReplace.call(match[0], reCopy, function () {\n for (i = 1; i < arguments.length - 2; i++) {\n if (arguments[i] === undefined) match[i] = undefined;\n }\n });\n }\n\n return match;\n };\n}\n\nmodule.exports = patchedExec;\n","'use strict';\nvar regexpExec = require('./_regexp-exec');\nrequire('./_export')({\n target: 'RegExp',\n proto: true,\n forced: regexpExec !== /./.exec\n}, {\n exec: regexpExec\n});\n","'use strict';\nrequire('./es6.regexp.exec');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar fails = require('./_fails');\nvar defined = require('./_defined');\nvar wks = require('./_wks');\nvar regexpExec = require('./_regexp-exec');\n\nvar SPECIES = wks('species');\n\nvar REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {\n // #replace needs built-in support for named groups.\n // #match works fine because it just return the exec results, even if it has\n // a \"grops\" property.\n var re = /./;\n re.exec = function () {\n var result = [];\n result.groups = { a: '7' };\n return result;\n };\n return ''.replace(re, '$<a>') !== '7';\n});\n\nvar SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = (function () {\n // Chrome 51 has a buggy \"split\" implementation when RegExp#exec !== nativeExec\n var re = /(?:)/;\n var originalExec = re.exec;\n re.exec = function () { return originalExec.apply(this, arguments); };\n var result = 'ab'.split(re);\n return result.length === 2 && result[0] === 'a' && result[1] === 'b';\n})();\n\nmodule.exports = function (KEY, length, exec) {\n var SYMBOL = wks(KEY);\n\n var DELEGATES_TO_SYMBOL = !fails(function () {\n // String methods call symbol-named RegEp methods\n var O = {};\n O[SYMBOL] = function () { return 7; };\n return ''[KEY](O) != 7;\n });\n\n var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !fails(function () {\n // Symbol-named RegExp methods call .exec\n var execCalled = false;\n var re = /a/;\n re.exec = function () { execCalled = true; return null; };\n if (KEY === 'split') {\n // RegExp[@@split] doesn't call the regex's exec method, but first creates\n // a new one. We need to return the patched regex when creating the new one.\n re.constructor = {};\n re.constructor[SPECIES] = function () { return re; };\n }\n re[SYMBOL]('');\n return !execCalled;\n }) : undefined;\n\n if (\n !DELEGATES_TO_SYMBOL ||\n !DELEGATES_TO_EXEC ||\n (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) ||\n (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)\n ) {\n var nativeRegExpMethod = /./[SYMBOL];\n var fns = exec(\n defined,\n SYMBOL,\n ''[KEY],\n function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) {\n if (regexp.exec === regexpExec) {\n if (DELEGATES_TO_SYMBOL && !forceStringMethod) {\n // The native String method already delegates to @@method (this\n // polyfilled function), leasing to infinite recursion.\n // We avoid it by directly calling the native @@method method.\n return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };\n }\n return { done: true, value: nativeMethod.call(str, regexp, arg2) };\n }\n return { done: false };\n }\n );\n var strfn = fns[0];\n var rxfn = fns[1];\n\n redefine(String.prototype, KEY, strfn);\n hide(RegExp.prototype, SYMBOL, length == 2\n // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)\n // 21.2.5.11 RegExp.prototype[@@split](string, limit)\n ? function (string, arg) { return rxfn.call(string, this, arg); }\n // 21.2.5.6 RegExp.prototype[@@match](string)\n // 21.2.5.9 RegExp.prototype[@@search](string)\n : function (string) { return rxfn.call(string, this); }\n );\n }\n};\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar sameValue = require('./_same-value');\nvar regExpExec = require('./_regexp-exec-abstract');\n\n// @@search logic\nrequire('./_fix-re-wks')('search', 1, function (defined, SEARCH, $search, maybeCallNative) {\n return [\n // `String.prototype.search` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.search\n function search(regexp) {\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[SEARCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));\n },\n // `RegExp.prototype[@@search]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@search\n function (regexp) {\n var res = maybeCallNative($search, regexp, this);\n if (res.done) return res.value;\n var rx = anObject(regexp);\n var S = String(this);\n var previousLastIndex = rx.lastIndex;\n if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;\n var result = regExpExec(rx, S);\n if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;\n return result === null ? -1 : result.index;\n }\n ];\n});\n","// 21.2.5.3 get RegExp.prototype.flags()\nif (require('./_descriptors') && /./g.flags != 'g') require('./_object-dp').f(RegExp.prototype, 'flags', {\n configurable: true,\n get: require('./_flags')\n});\n","'use strict';\nrequire('./es6.regexp.flags');\nvar anObject = require('./_an-object');\nvar $flags = require('./_flags');\nvar DESCRIPTORS = require('./_descriptors');\nvar TO_STRING = 'toString';\nvar $toString = /./[TO_STRING];\n\nvar define = function (fn) {\n require('./_redefine')(RegExp.prototype, TO_STRING, fn, true);\n};\n\n// 21.2.5.14 RegExp.prototype.toString()\nif (require('./_fails')(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) {\n define(function toString() {\n var R = anObject(this);\n return '/'.concat(R.source, '/',\n 'flags' in R ? R.flags : !DESCRIPTORS && R instanceof RegExp ? $flags.call(R) : undefined);\n });\n// FF44- RegExp#toString has a wrong name\n} else if ($toString.name != TO_STRING) {\n define(function toString() {\n return $toString.call(this);\n });\n}\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = $native || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","'use strict';\nvar addToUnscopables = require('./_add-to-unscopables');\nvar step = require('./_iter-step');\nvar Iterators = require('./_iterators');\nvar toIObject = require('./_to-iobject');\n\n// 22.1.3.4 Array.prototype.entries()\n// 22.1.3.13 Array.prototype.keys()\n// 22.1.3.29 Array.prototype.values()\n// 22.1.3.30 Array.prototype[@@iterator]()\nmodule.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) {\n this._t = toIObject(iterated); // target\n this._i = 0; // next index\n this._k = kind; // kind\n// 22.1.5.2.1 %ArrayIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var kind = this._k;\n var index = this._i++;\n if (!O || index >= O.length) {\n this._t = undefined;\n return step(1);\n }\n if (kind == 'keys') return step(0, index);\n if (kind == 'values') return step(0, O[index]);\n return step(0, [index, O[index]]);\n}, 'values');\n\n// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)\nIterators.Arguments = Iterators.Array;\n\naddToUnscopables('keys');\naddToUnscopables('values');\naddToUnscopables('entries');\n","var $iterators = require('./es6.array.iterator');\nvar getKeys = require('./_object-keys');\nvar redefine = require('./_redefine');\nvar global = require('./_global');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar wks = require('./_wks');\nvar ITERATOR = wks('iterator');\nvar TO_STRING_TAG = wks('toStringTag');\nvar ArrayValues = Iterators.Array;\n\nvar DOMIterables = {\n CSSRuleList: true, // TODO: Not spec compliant, should be false.\n CSSStyleDeclaration: false,\n CSSValueList: false,\n ClientRectList: false,\n DOMRectList: false,\n DOMStringList: false,\n DOMTokenList: true,\n DataTransferItemList: false,\n FileList: false,\n HTMLAllCollection: false,\n HTMLCollection: false,\n HTMLFormElement: false,\n HTMLSelectElement: false,\n MediaList: true, // TODO: Not spec compliant, should be false.\n MimeTypeArray: false,\n NamedNodeMap: false,\n NodeList: true,\n PaintRequestList: false,\n Plugin: false,\n PluginArray: false,\n SVGLengthList: false,\n SVGNumberList: false,\n SVGPathSegList: false,\n SVGPointList: false,\n SVGStringList: false,\n SVGTransformList: false,\n SourceBufferList: false,\n StyleSheetList: true, // TODO: Not spec compliant, should be false.\n TextTrackCueList: false,\n TextTrackList: false,\n TouchList: false\n};\n\nfor (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {\n var NAME = collections[i];\n var explicit = DOMIterables[NAME];\n var Collection = global[NAME];\n var proto = Collection && Collection.prototype;\n var key;\n if (proto) {\n if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);\n if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);\n Iterators[NAME] = ArrayValues;\n if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true);\n }\n}\n","var toInteger = require('./_to-integer');\nvar defined = require('./_defined');\n// true -> String#at\n// false -> String#codePointAt\nmodule.exports = function (TO_STRING) {\n return function (that, pos) {\n var s = String(defined(that));\n var i = toInteger(pos);\n var l = s.length;\n var a, b;\n if (i < 0 || i >= l) return TO_STRING ? '' : undefined;\n a = s.charCodeAt(i);\n return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff\n ? TO_STRING ? s.charAt(i) : a\n : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;\n };\n};\n","'use strict';\nvar $at = require('./_string-at')(true);\n\n// 21.1.3.27 String.prototype[@@iterator]()\nrequire('./_iter-define')(String, 'String', function (iterated) {\n this._t = String(iterated); // target\n this._i = 0; // next index\n// 21.1.5.2.1 %StringIteratorPrototype%.next()\n}, function () {\n var O = this._t;\n var index = this._i;\n var point;\n if (index >= O.length) return { value: undefined, done: true };\n point = $at(O, index);\n this._i += point.length;\n return { value: point, done: false };\n});\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","exports.f = Object.getOwnPropertySymbols;\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];\n } return T;\n} : $assign;\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","'use strict';\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar validate = require('./_validate-collection');\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar tmp = {};\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","'use strict';\nvar fails = require('./_fails');\n\nmodule.exports = function (method, arg) {\n return !!method && fails(function () {\n // eslint-disable-next-line no-useless-call\n arg ? method.call(null, function () { /* empty */ }, 1) : method.call(null);\n });\n};\n","'use strict';\nvar $export = require('./_export');\nvar aFunction = require('./_a-function');\nvar toObject = require('./_to-object');\nvar fails = require('./_fails');\nvar $sort = [].sort;\nvar test = [1, 2, 3];\n\n$export($export.P + $export.F * (fails(function () {\n // IE8-\n test.sort(undefined);\n}) || !fails(function () {\n // V8 bug\n test.sort(null);\n // Old WebKit\n}) || !require('./_strict-method')($sort)), 'Array', {\n // 22.1.3.25 Array.prototype.sort(comparefn)\n sort: function sort(comparefn) {\n return comparefn === undefined\n ? $sort.call(toObject(this))\n : $sort.call(toObject(this), aFunction(comparefn));\n }\n});\n","// 19.1.3.1 Object.assign(target, source)\nvar $export = require('./_export');\n\n$export($export.S + $export.F, 'Object', { assign: require('./_object-assign') });\n","// 7.3.20 SpeciesConstructor(O, defaultConstructor)\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar SPECIES = require('./_wks')('species');\nmodule.exports = function (O, D) {\n var C = anObject(O).constructor;\n var S;\n return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);\n};\n","'use strict';\nvar at = require('./_string-at')(true);\n\n // `AdvanceStringIndex` abstract operation\n// https://tc39.github.io/ecma262/#sec-advancestringindex\nmodule.exports = function (S, index, unicode) {\n return index + (unicode ? at(S, index).length : 1);\n};\n","'use strict';\n\nvar isRegExp = require('./_is-regexp');\nvar anObject = require('./_an-object');\nvar speciesConstructor = require('./_species-constructor');\nvar advanceStringIndex = require('./_advance-string-index');\nvar toLength = require('./_to-length');\nvar callRegExpExec = require('./_regexp-exec-abstract');\nvar regexpExec = require('./_regexp-exec');\nvar fails = require('./_fails');\nvar $min = Math.min;\nvar $push = [].push;\nvar $SPLIT = 'split';\nvar LENGTH = 'length';\nvar LAST_INDEX = 'lastIndex';\nvar MAX_UINT32 = 0xffffffff;\n\n// babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError\nvar SUPPORTS_Y = !fails(function () { RegExp(MAX_UINT32, 'y'); });\n\n// @@split logic\nrequire('./_fix-re-wks')('split', 2, function (defined, SPLIT, $split, maybeCallNative) {\n var internalSplit;\n if (\n 'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||\n 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||\n 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||\n '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||\n '.'[$SPLIT](/()()/)[LENGTH] > 1 ||\n ''[$SPLIT](/.?/)[LENGTH]\n ) {\n // based on es5-shim implementation, need to rework it\n internalSplit = function (separator, limit) {\n var string = String(this);\n if (separator === undefined && limit === 0) return [];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) return $split.call(string, separator, limit);\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n var splitLimit = limit === undefined ? MAX_UINT32 : limit >>> 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var match, lastIndex, lastLength;\n while (match = regexpExec.call(separatorCopy, string)) {\n lastIndex = separatorCopy[LAST_INDEX];\n if (lastIndex > lastLastIndex) {\n output.push(string.slice(lastLastIndex, match.index));\n if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));\n lastLength = match[0][LENGTH];\n lastLastIndex = lastIndex;\n if (output[LENGTH] >= splitLimit) break;\n }\n if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop\n }\n if (lastLastIndex === string[LENGTH]) {\n if (lastLength || !separatorCopy.test('')) output.push('');\n } else output.push(string.slice(lastLastIndex));\n return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;\n };\n // Chakra, V8\n } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {\n internalSplit = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit);\n };\n } else {\n internalSplit = $split;\n }\n\n return [\n // `String.prototype.split` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.split\n function split(separator, limit) {\n var O = defined(this);\n var splitter = separator == undefined ? undefined : separator[SPLIT];\n return splitter !== undefined\n ? splitter.call(separator, O, limit)\n : internalSplit.call(String(O), separator, limit);\n },\n // `RegExp.prototype[@@split]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split\n //\n // NOTE: This cannot be properly polyfilled in engines that don't support\n // the 'y' flag.\n function (regexp, limit) {\n var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split);\n if (res.done) return res.value;\n\n var rx = anObject(regexp);\n var S = String(this);\n var C = speciesConstructor(rx, RegExp);\n\n var unicodeMatching = rx.unicode;\n var flags = (rx.ignoreCase ? 'i' : '') +\n (rx.multiline ? 'm' : '') +\n (rx.unicode ? 'u' : '') +\n (SUPPORTS_Y ? 'y' : 'g');\n\n // ^(? + rx + ) is needed, in combination with some S slicing, to\n // simulate the 'y' flag.\n var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];\n var p = 0;\n var q = 0;\n var A = [];\n while (q < S.length) {\n splitter.lastIndex = SUPPORTS_Y ? q : 0;\n var z = callRegExpExec(splitter, SUPPORTS_Y ? S : S.slice(q));\n var e;\n if (\n z === null ||\n (e = $min(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p\n ) {\n q = advanceStringIndex(S, q, unicodeMatching);\n } else {\n A.push(S.slice(p, q));\n if (A.length === lim) return A;\n for (var i = 1; i <= z.length - 1; i++) {\n A.push(z[i]);\n if (A.length === lim) return A;\n }\n q = p = e;\n }\n }\n A.push(S.slice(p));\n return A;\n }\n ];\n});\n","var getKeys = require('./_object-keys');\nvar toIObject = require('./_to-iobject');\nvar isEnum = require('./_object-pie').f;\nmodule.exports = function (isEntries) {\n return function (it) {\n var O = toIObject(it);\n var keys = getKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) if (isEnum.call(O, key = keys[i++])) {\n result.push(isEntries ? [key, O[key]] : O[key]);\n } return result;\n };\n};\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $entries = require('./_object-to-array')(true);\n\n$export($export.S, 'Object', {\n entries: function entries(it) {\n return $entries(it);\n }\n});\n","// https://github.com/tc39/proposal-object-values-entries\nvar $export = require('./_export');\nvar $values = require('./_object-to-array')(false);\n\n$export($export.S, 'Object', {\n values: function values(it) {\n return $values(it);\n }\n});\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar toInteger = require('./_to-integer');\nvar advanceStringIndex = require('./_advance-string-index');\nvar regExpExec = require('./_regexp-exec-abstract');\nvar max = Math.max;\nvar min = Math.min;\nvar floor = Math.floor;\nvar SUBSTITUTION_SYMBOLS = /\\$([$&`']|\\d\\d?|<[^>]*>)/g;\nvar SUBSTITUTION_SYMBOLS_NO_NAMED = /\\$([$&`']|\\d\\d?)/g;\n\nvar maybeToString = function (it) {\n return it === undefined ? it : String(it);\n};\n\n// @@replace logic\nrequire('./_fix-re-wks')('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) {\n return [\n // `String.prototype.replace` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.replace\n function replace(searchValue, replaceValue) {\n var O = defined(this);\n var fn = searchValue == undefined ? undefined : searchValue[REPLACE];\n return fn !== undefined\n ? fn.call(searchValue, O, replaceValue)\n : $replace.call(String(O), searchValue, replaceValue);\n },\n // `RegExp.prototype[@@replace]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace\n function (regexp, replaceValue) {\n var res = maybeCallNative($replace, regexp, this, replaceValue);\n if (res.done) return res.value;\n\n var rx = anObject(regexp);\n var S = String(this);\n var functionalReplace = typeof replaceValue === 'function';\n if (!functionalReplace) replaceValue = String(replaceValue);\n var global = rx.global;\n if (global) {\n var fullUnicode = rx.unicode;\n rx.lastIndex = 0;\n }\n var results = [];\n while (true) {\n var result = regExpExec(rx, S);\n if (result === null) break;\n results.push(result);\n if (!global) break;\n var matchStr = String(result[0]);\n if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);\n }\n var accumulatedResult = '';\n var nextSourcePosition = 0;\n for (var i = 0; i < results.length; i++) {\n result = results[i];\n var matched = String(result[0]);\n var position = max(min(toInteger(result.index), S.length), 0);\n var captures = [];\n // NOTE: This is equivalent to\n // captures = result.slice(1).map(maybeToString)\n // but for some reason `nativeSlice.call(result, 1, result.length)` (called in\n // the slice polyfill when slicing native arrays) \"doesn't work\" in safari 9 and\n // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.\n for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));\n var namedCaptures = result.groups;\n if (functionalReplace) {\n var replacerArgs = [matched].concat(captures, position, S);\n if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);\n var replacement = String(replaceValue.apply(undefined, replacerArgs));\n } else {\n replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);\n }\n if (position >= nextSourcePosition) {\n accumulatedResult += S.slice(nextSourcePosition, position) + replacement;\n nextSourcePosition = position + matched.length;\n }\n }\n return accumulatedResult + S.slice(nextSourcePosition);\n }\n ];\n\n // https://tc39.github.io/ecma262/#sec-getsubstitution\n function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {\n var tailPos = position + matched.length;\n var m = captures.length;\n var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;\n if (namedCaptures !== undefined) {\n namedCaptures = toObject(namedCaptures);\n symbols = SUBSTITUTION_SYMBOLS;\n }\n return $replace.call(replacement, symbols, function (match, ch) {\n var capture;\n switch (ch.charAt(0)) {\n case '$': return '$';\n case '&': return matched;\n case '`': return str.slice(0, position);\n case \"'\": return str.slice(tailPos);\n case '<':\n capture = namedCaptures[ch.slice(1, -1)];\n break;\n default: // \\d\\d?\n var n = +ch;\n if (n === 0) return match;\n if (n > m) {\n var f = floor(n / 10);\n if (f === 0) return match;\n if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);\n return match;\n }\n capture = captures[n - 1];\n }\n return capture === undefined ? '' : capture;\n });\n }\n});\n","// fast apply, http://jsperf.lnkit.com/fast-apply/5\nmodule.exports = function (fn, args, that) {\n var un = that === undefined;\n switch (args.length) {\n case 0: return un ? fn()\n : fn.call(that);\n case 1: return un ? fn(args[0])\n : fn.call(that, args[0]);\n case 2: return un ? fn(args[0], args[1])\n : fn.call(that, args[0], args[1]);\n case 3: return un ? fn(args[0], args[1], args[2])\n : fn.call(that, args[0], args[1], args[2]);\n case 4: return un ? fn(args[0], args[1], args[2], args[3])\n : fn.call(that, args[0], args[1], args[2], args[3]);\n } return fn.apply(that, args);\n};\n","var ctx = require('./_ctx');\nvar invoke = require('./_invoke');\nvar html = require('./_html');\nvar cel = require('./_dom-create');\nvar global = require('./_global');\nvar process = global.process;\nvar setTask = global.setImmediate;\nvar clearTask = global.clearImmediate;\nvar MessageChannel = global.MessageChannel;\nvar Dispatch = global.Dispatch;\nvar counter = 0;\nvar queue = {};\nvar ONREADYSTATECHANGE = 'onreadystatechange';\nvar defer, channel, port;\nvar run = function () {\n var id = +this;\n // eslint-disable-next-line no-prototype-builtins\n if (queue.hasOwnProperty(id)) {\n var fn = queue[id];\n delete queue[id];\n fn();\n }\n};\nvar listener = function (event) {\n run.call(event.data);\n};\n// Node.js 0.9+ & IE10+ has setImmediate, otherwise:\nif (!setTask || !clearTask) {\n setTask = function setImmediate(fn) {\n var args = [];\n var i = 1;\n while (arguments.length > i) args.push(arguments[i++]);\n queue[++counter] = function () {\n // eslint-disable-next-line no-new-func\n invoke(typeof fn == 'function' ? fn : Function(fn), args);\n };\n defer(counter);\n return counter;\n };\n clearTask = function clearImmediate(id) {\n delete queue[id];\n };\n // Node.js 0.8-\n if (require('./_cof')(process) == 'process') {\n defer = function (id) {\n process.nextTick(ctx(run, id, 1));\n };\n // Sphere (JS game engine) Dispatch API\n } else if (Dispatch && Dispatch.now) {\n defer = function (id) {\n Dispatch.now(ctx(run, id, 1));\n };\n // Browsers with MessageChannel, includes WebWorkers\n } else if (MessageChannel) {\n channel = new MessageChannel();\n port = channel.port2;\n channel.port1.onmessage = listener;\n defer = ctx(port.postMessage, port, 1);\n // Browsers with postMessage, skip WebWorkers\n // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'\n } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {\n defer = function (id) {\n global.postMessage(id + '', '*');\n };\n global.addEventListener('message', listener, false);\n // IE8-\n } else if (ONREADYSTATECHANGE in cel('script')) {\n defer = function (id) {\n html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {\n html.removeChild(this);\n run.call(id);\n };\n };\n // Rest old browsers\n } else {\n defer = function (id) {\n setTimeout(ctx(run, id, 1), 0);\n };\n }\n}\nmodule.exports = {\n set: setTask,\n clear: clearTask\n};\n","var global = require('./_global');\nvar macrotask = require('./_task').set;\nvar Observer = global.MutationObserver || global.WebKitMutationObserver;\nvar process = global.process;\nvar Promise = global.Promise;\nvar isNode = require('./_cof')(process) == 'process';\n\nmodule.exports = function () {\n var head, last, notify;\n\n var flush = function () {\n var parent, fn;\n if (isNode && (parent = process.domain)) parent.exit();\n while (head) {\n fn = head.fn;\n head = head.next;\n try {\n fn();\n } catch (e) {\n if (head) notify();\n else last = undefined;\n throw e;\n }\n } last = undefined;\n if (parent) parent.enter();\n };\n\n // Node.js\n if (isNode) {\n notify = function () {\n process.nextTick(flush);\n };\n // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339\n } else if (Observer && !(global.navigator && global.navigator.standalone)) {\n var toggle = true;\n var node = document.createTextNode('');\n new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new\n notify = function () {\n node.data = toggle = !toggle;\n };\n // environments with maybe non-completely correct, but existent Promise\n } else if (Promise && Promise.resolve) {\n // Promise.resolve without an argument throws an error in LG WebOS 2\n var promise = Promise.resolve(undefined);\n notify = function () {\n promise.then(flush);\n };\n // for other environments - macrotask based on:\n // - setImmediate\n // - MessageChannel\n // - window.postMessag\n // - onreadystatechange\n // - setTimeout\n } else {\n notify = function () {\n // strange IE + webpack dev server bug - use .call(global)\n macrotask.call(global, flush);\n };\n }\n\n return function (fn) {\n var task = { fn: fn, next: undefined };\n if (last) last.next = task;\n if (!head) {\n head = task;\n notify();\n } last = task;\n };\n};\n","'use strict';\n// 25.4.1.5 NewPromiseCapability(C)\nvar aFunction = require('./_a-function');\n\nfunction PromiseCapability(C) {\n var resolve, reject;\n this.promise = new C(function ($$resolve, $$reject) {\n if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');\n resolve = $$resolve;\n reject = $$reject;\n });\n this.resolve = aFunction(resolve);\n this.reject = aFunction(reject);\n}\n\nmodule.exports.f = function (C) {\n return new PromiseCapability(C);\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar global = require('./_global');\nvar ctx = require('./_ctx');\nvar classof = require('./_classof');\nvar $export = require('./_export');\nvar isObject = require('./_is-object');\nvar aFunction = require('./_a-function');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar speciesConstructor = require('./_species-constructor');\nvar task = require('./_task').set;\nvar microtask = require('./_microtask')();\nvar newPromiseCapabilityModule = require('./_new-promise-capability');\nvar perform = require('./_perform');\nvar userAgent = require('./_user-agent');\nvar promiseResolve = require('./_promise-resolve');\nvar PROMISE = 'Promise';\nvar TypeError = global.TypeError;\nvar process = global.process;\nvar versions = process && process.versions;\nvar v8 = versions && versions.v8 || '';\nvar $Promise = global[PROMISE];\nvar isNode = classof(process) == 'process';\nvar empty = function () { /* empty */ };\nvar Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;\nvar newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;\n\nvar USE_NATIVE = !!function () {\n try {\n // correct subclassing with @@species support\n var promise = $Promise.resolve(1);\n var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) {\n exec(empty, empty);\n };\n // unhandled rejections tracking support, NodeJS Promise without it fails @@species test\n return (isNode || typeof PromiseRejectionEvent == 'function')\n && promise.then(empty) instanceof FakePromise\n // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables\n // https://bugs.chromium.org/p/chromium/issues/detail?id=830565\n // we can't detect it synchronously, so just check versions\n && v8.indexOf('6.6') !== 0\n && userAgent.indexOf('Chrome/66') === -1;\n } catch (e) { /* empty */ }\n}();\n\n// helpers\nvar isThenable = function (it) {\n var then;\n return isObject(it) && typeof (then = it.then) == 'function' ? then : false;\n};\nvar notify = function (promise, isReject) {\n if (promise._n) return;\n promise._n = true;\n var chain = promise._c;\n microtask(function () {\n var value = promise._v;\n var ok = promise._s == 1;\n var i = 0;\n var run = function (reaction) {\n var handler = ok ? reaction.ok : reaction.fail;\n var resolve = reaction.resolve;\n var reject = reaction.reject;\n var domain = reaction.domain;\n var result, then, exited;\n try {\n if (handler) {\n if (!ok) {\n if (promise._h == 2) onHandleUnhandled(promise);\n promise._h = 1;\n }\n if (handler === true) result = value;\n else {\n if (domain) domain.enter();\n result = handler(value); // may throw\n if (domain) {\n domain.exit();\n exited = true;\n }\n }\n if (result === reaction.promise) {\n reject(TypeError('Promise-chain cycle'));\n } else if (then = isThenable(result)) {\n then.call(result, resolve, reject);\n } else resolve(result);\n } else reject(value);\n } catch (e) {\n if (domain && !exited) domain.exit();\n reject(e);\n }\n };\n while (chain.length > i) run(chain[i++]); // variable length - can't use forEach\n promise._c = [];\n promise._n = false;\n if (isReject && !promise._h) onUnhandled(promise);\n });\n};\nvar onUnhandled = function (promise) {\n task.call(global, function () {\n var value = promise._v;\n var unhandled = isUnhandled(promise);\n var result, handler, console;\n if (unhandled) {\n result = perform(function () {\n if (isNode) {\n process.emit('unhandledRejection', value, promise);\n } else if (handler = global.onunhandledrejection) {\n handler({ promise: promise, reason: value });\n } else if ((console = global.console) && console.error) {\n console.error('Unhandled promise rejection', value);\n }\n });\n // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should\n promise._h = isNode || isUnhandled(promise) ? 2 : 1;\n } promise._a = undefined;\n if (unhandled && result.e) throw result.v;\n });\n};\nvar isUnhandled = function (promise) {\n return promise._h !== 1 && (promise._a || promise._c).length === 0;\n};\nvar onHandleUnhandled = function (promise) {\n task.call(global, function () {\n var handler;\n if (isNode) {\n process.emit('rejectionHandled', promise);\n } else if (handler = global.onrejectionhandled) {\n handler({ promise: promise, reason: promise._v });\n }\n });\n};\nvar $reject = function (value) {\n var promise = this;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n promise._v = value;\n promise._s = 2;\n if (!promise._a) promise._a = promise._c.slice();\n notify(promise, true);\n};\nvar $resolve = function (value) {\n var promise = this;\n var then;\n if (promise._d) return;\n promise._d = true;\n promise = promise._w || promise; // unwrap\n try {\n if (promise === value) throw TypeError(\"Promise can't be resolved itself\");\n if (then = isThenable(value)) {\n microtask(function () {\n var wrapper = { _w: promise, _d: false }; // wrap\n try {\n then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));\n } catch (e) {\n $reject.call(wrapper, e);\n }\n });\n } else {\n promise._v = value;\n promise._s = 1;\n notify(promise, false);\n }\n } catch (e) {\n $reject.call({ _w: promise, _d: false }, e); // wrap\n }\n};\n\n// constructor polyfill\nif (!USE_NATIVE) {\n // 25.4.3.1 Promise(executor)\n $Promise = function Promise(executor) {\n anInstance(this, $Promise, PROMISE, '_h');\n aFunction(executor);\n Internal.call(this);\n try {\n executor(ctx($resolve, this, 1), ctx($reject, this, 1));\n } catch (err) {\n $reject.call(this, err);\n }\n };\n // eslint-disable-next-line no-unused-vars\n Internal = function Promise(executor) {\n this._c = []; // <- awaiting reactions\n this._a = undefined; // <- checked in isUnhandled reactions\n this._s = 0; // <- state\n this._d = false; // <- done\n this._v = undefined; // <- value\n this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled\n this._n = false; // <- notify\n };\n Internal.prototype = require('./_redefine-all')($Promise.prototype, {\n // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)\n then: function then(onFulfilled, onRejected) {\n var reaction = newPromiseCapability(speciesConstructor(this, $Promise));\n reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;\n reaction.fail = typeof onRejected == 'function' && onRejected;\n reaction.domain = isNode ? process.domain : undefined;\n this._c.push(reaction);\n if (this._a) this._a.push(reaction);\n if (this._s) notify(this, false);\n return reaction.promise;\n },\n // 25.4.5.1 Promise.prototype.catch(onRejected)\n 'catch': function (onRejected) {\n return this.then(undefined, onRejected);\n }\n });\n OwnPromiseCapability = function () {\n var promise = new Internal();\n this.promise = promise;\n this.resolve = ctx($resolve, promise, 1);\n this.reject = ctx($reject, promise, 1);\n };\n newPromiseCapabilityModule.f = newPromiseCapability = function (C) {\n return C === $Promise || C === Wrapper\n ? new OwnPromiseCapability(C)\n : newGenericPromiseCapability(C);\n };\n}\n\n$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });\nrequire('./_set-to-string-tag')($Promise, PROMISE);\nrequire('./_set-species')(PROMISE);\nWrapper = require('./_core')[PROMISE];\n\n// statics\n$export($export.S + $export.F * !USE_NATIVE, PROMISE, {\n // 25.4.4.5 Promise.reject(r)\n reject: function reject(r) {\n var capability = newPromiseCapability(this);\n var $$reject = capability.reject;\n $$reject(r);\n return capability.promise;\n }\n});\n$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {\n // 25.4.4.6 Promise.resolve(x)\n resolve: function resolve(x) {\n return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);\n }\n});\n$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) {\n $Promise.all(iter)['catch'](empty);\n})), PROMISE, {\n // 25.4.4.1 Promise.all(iterable)\n all: function all(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var resolve = capability.resolve;\n var reject = capability.reject;\n var result = perform(function () {\n var values = [];\n var index = 0;\n var remaining = 1;\n forOf(iterable, false, function (promise) {\n var $index = index++;\n var alreadyCalled = false;\n values.push(undefined);\n remaining++;\n C.resolve(promise).then(function (value) {\n if (alreadyCalled) return;\n alreadyCalled = true;\n values[$index] = value;\n --remaining || resolve(values);\n }, reject);\n });\n --remaining || resolve(values);\n });\n if (result.e) reject(result.v);\n return capability.promise;\n },\n // 25.4.4.4 Promise.race(iterable)\n race: function race(iterable) {\n var C = this;\n var capability = newPromiseCapability(C);\n var reject = capability.reject;\n var result = perform(function () {\n forOf(iterable, false, function (promise) {\n C.resolve(promise).then(capability.resolve, reject);\n });\n });\n if (result.e) reject(result.v);\n return capability.promise;\n }\n});\n","module.exports = function (exec) {\n try {\n return { e: false, v: exec() };\n } catch (e) {\n return { e: true, v: e };\n }\n};\n","var global = require('./_global');\nvar navigator = global.navigator;\n\nmodule.exports = navigator && navigator.userAgent || '';\n","var anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar newPromiseCapability = require('./_new-promise-capability');\n\nmodule.exports = function (C, x) {\n anObject(C);\n if (isObject(x) && x.constructor === C) return x;\n var promiseCapability = newPromiseCapability.f(C);\n var resolve = promiseCapability.resolve;\n resolve(x);\n return promiseCapability.promise;\n};\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","// 21.1.3.18 String.prototype.startsWith(searchString [, position ])\n'use strict';\nvar $export = require('./_export');\nvar toLength = require('./_to-length');\nvar context = require('./_string-context');\nvar STARTS_WITH = 'startsWith';\nvar $startsWith = ''[STARTS_WITH];\n\n$export($export.P + $export.F * require('./_fails-is-regexp')(STARTS_WITH), 'String', {\n startsWith: function startsWith(searchString /* , position = 0 */) {\n var that = context(this, searchString, STARTS_WITH);\n var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));\n var search = String(searchString);\n return $startsWith\n ? $startsWith.call(that, search, index)\n : that.slice(index, index + search.length) === search;\n }\n});\n","// 20.1.2.4 Number.isNaN(number)\nvar $export = require('./_export');\n\n$export($export.S, 'Number', {\n isNaN: function isNaN(number) {\n // eslint-disable-next-line no-self-compare\n return number != number;\n }\n});\n","// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isWeakMap = input => instanceOf(input, WeakMap);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isTextNode = input => getConstructor(input) === Text;\nconst isEvent = input => instanceOf(input, Event);\nconst isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\nconst isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\n\nconst isEmpty = input =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (e) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: Object.assign({}, detail, {\n plyr: this,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise(resolve =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport { toggleListener } from './events';\nimport is from './is';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) {\n return;\n }\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) {\n return;\n }\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) {\n return;\n }\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) {\n return;\n }\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n return null;\n }\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.object(existing) && is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) {\n return;\n }\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n if (hide) {\n element.setAttribute('hidden', '');\n } else {\n element.removeAttribute('hidden');\n }\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Trap focus inside container\nexport function trapFocus(element = null, toggle = false) {\n if (!is.element(element)) {\n return;\n }\n\n const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n const trap = event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9) {\n return;\n }\n\n // Get the current focused element\n const focused = document.activeElement;\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n if (!is.element(element)) {\n return;\n }\n\n // Set regular focus\n element.focus({ preventScroll: true });\n\n // If we want to mimic keyboard focus via tab\n if (tabFocus) {\n toggleClass(element, this.config.classNames.tabFocus);\n }\n}\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport { toggleHidden } from './elements';\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element) {\n setTimeout(() => {\n try {\n toggleHidden(element, true);\n element.offsetHeight; // eslint-disable-line\n toggleHidden(element, false);\n } catch (e) {\n // Do nothing\n }\n }, 0);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isEdge: window.navigator.userAgent.includes('Edge'),\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider, playsinline) {\n const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (e) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map(source => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n extend() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(source => source.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n // Get sources\n const sources = html5.getSources.call(player);\n\n // Get first match for requested size\n const source = sources.find(source => Number(source.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n player.play();\n }\n });\n\n // Load new source\n player.media.load();\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","var global = require('./_global');\nvar inheritIfRequired = require('./_inherit-if-required');\nvar dP = require('./_object-dp').f;\nvar gOPN = require('./_object-gopn').f;\nvar isRegExp = require('./_is-regexp');\nvar $flags = require('./_flags');\nvar $RegExp = global.RegExp;\nvar Base = $RegExp;\nvar proto = $RegExp.prototype;\nvar re1 = /a/g;\nvar re2 = /a/g;\n// \"new\" creates a new object, old webkit buggy here\nvar CORRECT_NEW = new $RegExp(re1) !== re1;\n\nif (require('./_descriptors') && (!CORRECT_NEW || require('./_fails')(function () {\n re2[require('./_wks')('match')] = false;\n // RegExp constructor can alter flags and IsRegExp works correct with @@match\n return $RegExp(re1) != re1 || $RegExp(re2) == re2 || $RegExp(re1, 'i') != '/a/i';\n}))) {\n $RegExp = function RegExp(p, f) {\n var tiRE = this instanceof $RegExp;\n var piRE = isRegExp(p);\n var fiU = f === undefined;\n return !tiRE && piRE && p.constructor === $RegExp && fiU ? p\n : inheritIfRequired(CORRECT_NEW\n ? new Base(piRE && !fiU ? p.source : p, f)\n : Base((piRE = p instanceof $RegExp) ? p.source : p, piRE && fiU ? $flags.call(p) : f)\n , tiRE ? this : proto, $RegExp);\n };\n var proxy = function (key) {\n key in $RegExp || dP($RegExp, key, {\n configurable: true,\n get: function () { return Base[key]; },\n set: function (it) { Base[key] = it; }\n });\n };\n for (var keys = gOPN(Base), i = 0; keys.length > i;) proxy(keys[i++]);\n proto.constructor = $RegExp;\n $RegExp.prototype = proto;\n require('./_redefine')(global, 'RegExp', $RegExp);\n}\n\nrequire('./_set-species')('RegExp');\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) {\n return input;\n }\n\n return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport function replaceAll(input = '', find = '', replace = '') {\n return input.replace(\n new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'),\n replace.toString(),\n );\n}\n\n// Convert to title case\nexport function toTitleCase(input = '') {\n return input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n}\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([key, value]) => {\n string = replaceAll(string, key, value);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n get(key) {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n }\n\n set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n }\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (e) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (e) {\n reject(e);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then(result => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// 20.2.2.34 Math.trunc(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', {\n trunc: function trunc(it) {\n return (it > 0 ? Math.floor : Math.ceil)(it);\n }\n});\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = value => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = value => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(null, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const cors = url.host !== window.location.host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`,\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n role: 'presentation',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n\n const attributes = Object.assign({}, attr, {\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '),\n });\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = Object.assign({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.includes(this.config.classNames.control)) {\n attributes.class += ` ${this.config.classNames.control}`;\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'presentation',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type]);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-label': i18n.get(type, this.config),\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on(\n menuItem,\n 'keydown keyup',\n event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![32, 38, 39, 40].includes(event.which)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [32, 39].includes(event.which)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.which !== 32) {\n if (event.which === 40 || (isRadioButton && event.which === 39)) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on(menuItem, 'keyup', event => {\n if (event.which !== 13) {\n return;\n }\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behaviour\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(checked) {\n // Ensure exclusivity\n if (checked) {\n Array.from(menuItem.parentNode.children)\n .filter(node => matches(node, '[role=\"menuitemradio\"]'))\n .forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n event => {\n if (is.keyboardEvent(event) && event.which !== 32) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const value = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n // Calculate percentage\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n const visible = `${this.config.classNames.tooltip}--visible`;\n\n const toggle = toggle => {\n toggleClass(this.elements.display.seekTooltip, visible, toggle);\n };\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n // Display the time a click would seek to\n controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n // Set position\n this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Set the speed options\n if (is.array(options)) {\n this.options.speed = options;\n } else if (this.isHTML5 || this.isVimeo) {\n this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\n }\n\n // Set options if passed and filter based on config\n this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, tabFocus = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, tabFocus);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.which === 27) {\n show = false;\n } else if (is.event(input)) {\n const isMenuItem = popup.contains(input.target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', tabFocus = false) {\n const target = document.getElementById(`plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, tabFocus);\n },\n\n // Set the download link\n setDownloadLink() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set download link\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n // TODO: Set order based on order in the config.controls array?\n create(data) {\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n\n // Restart button\n if (this.config.controls.includes('restart')) {\n container.appendChild(controls.createButton.call(this, 'restart'));\n }\n\n // Rewind button\n if (this.config.controls.includes('rewind')) {\n container.appendChild(controls.createButton.call(this, 'rewind'));\n }\n\n // Play/Pause button\n if (this.config.controls.includes('play')) {\n container.appendChild(controls.createButton.call(this, 'play'));\n }\n\n // Fast forward button\n if (this.config.controls.includes('fast-forward')) {\n container.appendChild(controls.createButton.call(this, 'fast-forward'));\n }\n\n // Progress\n if (this.config.controls.includes('progress')) {\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n controls.createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(controls.createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n container.appendChild(this.elements.progress);\n }\n\n // Media current time display\n if (this.config.controls.includes('current-time')) {\n container.appendChild(controls.createTime.call(this, 'currentTime'));\n }\n\n // Media duration display\n if (this.config.controls.includes('duration')) {\n container.appendChild(controls.createTime.call(this, 'duration'));\n }\n\n // Volume controls\n if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {\n const volume = createElement('div', {\n class: 'plyr__volume',\n });\n\n // Toggle mute button\n if (this.config.controls.includes('mute')) {\n volume.appendChild(controls.createButton.call(this, 'mute'));\n }\n\n // Volume range control\n if (this.config.controls.includes('volume')) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n controls.createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n\n this.elements.volume = volume;\n }\n\n container.appendChild(volume);\n }\n\n // Toggle captions button\n if (this.config.controls.includes('captions')) {\n container.appendChild(controls.createButton.call(this, 'captions'));\n }\n\n // Settings button / menu\n if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n const control = createElement('div', {\n class: 'plyr__menu',\n hidden: '',\n });\n\n control.appendChild(\n controls.createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on(menuItem, 'click', () => {\n controls.showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on(\n pane,\n 'keydown',\n event => {\n // We only care about <-\n if (event.which !== 37) {\n return;\n }\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n controls.showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on(backButton, 'click', () => {\n controls.showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n control.appendChild(popup);\n container.appendChild(control);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = control;\n }\n\n // Picture in picture button\n if (this.config.controls.includes('pip') && support.pip) {\n container.appendChild(controls.createButton.call(this, 'pip'));\n }\n\n // Airplay button\n if (this.config.controls.includes('airplay') && support.airplay) {\n container.appendChild(controls.createButton.call(this, 'airplay'));\n }\n\n // Download button\n if (this.config.controls.includes('download')) {\n const attributes = {\n element: 'a',\n href: this.download,\n target: '_blank',\n };\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(controls.createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (this.config.controls.includes('fullscreen')) {\n container.appendChild(controls.createButton.call(this, 'fullscreen'));\n }\n\n // Larger overlaid play button\n if (this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));\n }\n\n this.elements.controls = container;\n\n // Set available quality levels\n if (this.isHTML5) {\n controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n controls.setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n } else if (is.element(container)) {\n container.innerHTML = replace(container.innerHTML);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n Object.defineProperty(button, 'pressed', {\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button)\n .filter(Boolean)\n .forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {string} input - the URL to be parsed\n * @param {boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (e) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n track.mode = 'hidden';\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n\n // Update available languages in list\n if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter(track => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(track => track.language === language);\n return !track; // Break iteration if there is a match\n });\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || [])\n .map(cue => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/v2/video/{0}.json',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api:\n 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n },\n },\n\n // API keys\n keys: {\n google: null,\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n },\n\n // YouTube plugin\n youtube: {\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { hasClass, toggleClass, trapFocus } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\n\nfunction onChange() {\n if (!this.enabled) {\n return;\n }\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Trigger an event\n triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n\n // Trap focus in container\n if (!browser.isIos) {\n trapFocus.call(this.player, this.target, this.active);\n }\n}\n\nfunction toggleFallback(toggle = false) {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX || 0,\n y: window.scrollY || 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n\n if (!hasProperty) {\n viewport.content += `,${property}`;\n }\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter(part => part.trim() !== property)\n .join(',');\n }\n\n // Force a repaint as sometimes Safari doesn't want to fill the screen\n setTimeout(() => repaint(this.target), 100);\n }\n\n // Toggle button and fire events\n onChange.call(this);\n}\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n onChange.call(this);\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.toggle();\n });\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get native() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get usingNative() {\n return Fullscreen.native && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) {\n return '';\n }\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is enabled\n get enabled() {\n return (\n (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n this.player.config.fullscreen.enabled &&\n this.player.supported.ui &&\n this.player.isVideo\n );\n }\n\n // Get active state\n get active() {\n if (!this.enabled) {\n return false;\n }\n\n // Fallback using classname\n if (!Fullscreen.native || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];\n\n return element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.container;\n }\n\n // Update UI\n update() {\n if (this.enabled) {\n let mode;\n\n if (this.forceFallback) {\n mode = 'Fallback (forced)';\n } else if (Fullscreen.native) {\n mode = 'Native';\n } else {\n mode = 'Fallback';\n }\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n }\n\n // Make an element fullscreen\n enter() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitEnterFullscreen();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, true);\n } else if (!this.prefix) {\n this.target.requestFullscreen();\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n }\n\n // Bail from fullscreen\n exit() {\n if (!this.enabled) {\n return;\n }\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n this.target.webkitExitFullscreen();\n this.player.play();\n } else if (!Fullscreen.native || this.forceFallback) {\n toggleFallback.call(this, false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n }\n\n // Toggle state\n toggle() {\n if (!this.active) {\n this.enter();\n } else {\n this.exit();\n }\n }\n}\n\nexport default Fullscreen;\n","// 20.2.2.28 Math.sign(x)\nmodule.exports = Math.sign || function sign(x) {\n // eslint-disable-next-line no-self-compare\n return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;\n};\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// 20.2.2.28 Math.sign(x)\nvar $export = require('./_export');\n\n$export($export.S, 'Math', { sign: require('./_math-sign') });\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/loadImage';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add iOS class\n toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('poster', poster);\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch(err => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw err;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n ui.togglePoster.call(this, true);\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n target.pressed = this.playing;\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls } = this.elements;\n\n if (controls && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now());\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport is from './is';\n\n/* function reduceAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n} */\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n let ratio = input;\n\n if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) {\n ({ ratio } = this.embed);\n }\n\n if (!is.string(ratio)) {\n ({ ratio } = this.config);\n }\n\n const [x, y] = ratio.split(':').map(Number);\n const padding = (100 / x) * y;\n\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && this.supported.ui) {\n const height = 240;\n const offset = (height - padding) / (height / 50);\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n\n return { padding, ratio };\n}\n\nexport default { setAspectRatio };\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { setAspectRatio } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.setTabFocus = this.setTabFocus.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const code = event.keyCode ? event.keyCode : event.which;\n const pressed = event.type === 'keydown';\n const repeat = pressed && code === this.lastKey;\n\n // Bail if a modifier key is set\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keycodes should we prevent default\n const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!repeat) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!repeat) {\n player.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n player.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n player.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n player.forward();\n break;\n\n case 37:\n // Arrow back\n player.rewind();\n break;\n\n case 70:\n // F key\n player.fullscreen.toggle();\n break;\n\n case 67:\n // C key\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n player.loop = !player.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last code for next cycle\n this.lastKey = code;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch() {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n }\n\n setTabFocus(event) {\n const { player } = this;\n const { elements } = player;\n\n clearTimeout(this.focusTimer);\n\n // Ignore any key other than tab\n if (event.type === 'keydown' && event.which !== 9) {\n return;\n }\n\n // Store reference to event timeStamp\n if (event.type === 'keydown') {\n this.lastKeyDown = event.timeStamp;\n }\n\n // Remove current classes\n const removeCurrent = () => {\n const className = player.config.classNames.tabFocus;\n const current = getElements.call(player, `.${className}`);\n toggleClass(current, className, false);\n };\n\n // Determine if a key was pressed to trigger this event\n const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n // Ignore focus events if a key was pressed prior\n if (event.type === 'focus' && !wasKeyDown) {\n return;\n }\n\n // Remove all current\n removeCurrent();\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n this.focusTimer = setTimeout(() => {\n const focused = document.activeElement;\n\n // Ignore if current focus element isn't inside the player\n if (!elements.container.contains(focused)) {\n return;\n }\n\n toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n }, 10);\n }\n\n // Global window & document listeners\n global(toggle = true) {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n\n // Tab focus detection\n toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);\n }\n\n // Container listeners\n container() {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n event => {\n const { controls } = elements;\n\n // Remove button states for fullscreen\n if (controls && event.type === 'enterfullscreen') {\n controls.pressed = false;\n controls.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Force edge to repaint on exit fullscreen\n // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen\n /* if (browser.isEdge) {\n on.call(player, elements.container, 'exitfullscreen', () => {\n setTimeout(() => repaint(elements.container), 100);\n });\n } */\n\n // Set a gutter for Vimeo\n const setGutter = (ratio, padding, toggle) => {\n if (!player.isVimeo) {\n return;\n }\n\n const target = player.elements.wrapper.firstChild;\n const [, height] = ratio.split(':').map(Number);\n const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number);\n\n target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null;\n target.style.margin = toggle ? '0 auto' : null;\n };\n\n // Resize on fullscreen change\n const setPlayerSize = measure => {\n // If we don't need to measure the viewport\n if (!measure) {\n return setAspectRatio.call(player);\n }\n\n const rect = elements.container.getBoundingClientRect();\n const { width, height } = rect;\n\n return setAspectRatio.call(player, `${width}:${height}`);\n };\n\n const resized = () => {\n window.clearTimeout(timers.resized);\n timers.resized = window.setTimeout(setPlayerSize, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const { target, usingNative } = player.fullscreen;\n\n // Ignore for iOS native\n if (!player.isEmbed || target !== elements.container) {\n return;\n }\n\n const isEnter = event.type === 'enterfullscreen';\n\n // Set the player size when entering fullscreen to viewport size\n const { padding, ratio } = setPlayerSize(isEnter);\n\n // Set Vimeo gutter\n setGutter(ratio, padding, isEnter);\n\n // If not using native fullscreen, we need to check for resizes of viewport\n if (!usingNative) {\n if (isEnter) {\n on.call(player, window, 'resize', resized);\n } else {\n off.call(player, window, 'resize', resized);\n }\n }\n });\n }\n\n // Listen for media events\n media() {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event =>\n controls.durationUpdate.call(player, event),\n );\n\n // Check for audio tracks on load\n // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point\n on.call(player, player.media, 'canplay loadeddata', () => {\n toggleHidden(elements.volume, !player.hasAudio);\n toggleHidden(elements.buttons.mute, !player.hasAudio);\n });\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // If autoplay, then load advertisement if required\n // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows\n on.call(player, player.media, 'playing', () => {\n if (!player.ads) {\n return;\n }\n\n // If ads are enabled, wait for them first\n if (player.ads.enabled && !player.ads.initialized) {\n // Wait for manager response\n player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play());\n }\n });\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, player.play, 'play');\n } else {\n this.proxy(event, player.togglePlay, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadLink.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, event => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n }\n\n // Run default and custom handlers\n proxy(event, defaultHandler, customHandlerKey) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n }\n\n // Trigger custom and default handlers\n bind(element, type, defaultHandler, customHandlerKey, passive = true) {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n event => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n }\n\n // Listen for control events\n controls() {\n const { player } = this;\n const { elements } = player;\n\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', player.togglePlay, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward');\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n\n controls.toggleMenu.call(player, event);\n });\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n event => {\n const code = event.which;\n\n // We only care about space and return\n if (![13, 32].includes(code)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (code === 13) {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.which === 27) {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const code = event.keyCode ? event.keyCode : event.which;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n player.play();\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n event => {\n const seek = event.currentTarget;\n\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', event => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebkit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n event => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, elements, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n event => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));\n\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n }\n}\n\nexport default Listeners;\n","var dP = require('./_object-dp').f;\nvar FProto = Function.prototype;\nvar nameRE = /^\\s*function ([^ (]*)/;\nvar NAME = 'name';\n\n// 19.2.4.2 name\nNAME in FProto || require('./_descriptors') && dP(FProto, NAME, {\n configurable: true,\n get: function () {\n try {\n return ('' + this).match(nameRE)[1];\n } catch (e) {\n return '';\n }\n }\n});\n","'use strict';\n\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar advanceStringIndex = require('./_advance-string-index');\nvar regExpExec = require('./_regexp-exec-abstract');\n\n// @@match logic\nrequire('./_fix-re-wks')('match', 1, function (defined, MATCH, $match, maybeCallNative) {\n return [\n // `String.prototype.match` method\n // https://tc39.github.io/ecma262/#sec-string.prototype.match\n function match(regexp) {\n var O = defined(this);\n var fn = regexp == undefined ? undefined : regexp[MATCH];\n return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));\n },\n // `RegExp.prototype[@@match]` method\n // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match\n function (regexp) {\n var res = maybeCallNative($match, regexp, this);\n if (res.done) return res.value;\n var rx = anObject(regexp);\n var S = String(this);\n if (!rx.global) return regExpExec(rx, S);\n var fullUnicode = rx.unicode;\n rx.lastIndex = 0;\n var A = [];\n var n = 0;\n var result;\n while ((result = regExpExec(rx, S)) !== null) {\n var matchStr = String(result[0]);\n A[n] = matchStr;\n if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);\n n++;\n }\n return n === 0 ? null : A;\n }\n ];\n});\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathStripped = path.replace(/^(css|img)!/, ''),\n isCss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(path)) {\n isCss = true;\n\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped; //.replace(/^css!/, ''); // remove \"css!\" prefix\n } else if (/(^img!|\\.(png|gif|jpg|svg)$)/.test(path)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // Note: The following code isolates IE using `hideFocus` and treats empty\n // stylesheets as failures to get around lack of onerror support\n if (isCss && 'hideFocus' in e) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function)} [arg1] - The bundleId or success callback\n * @param {Function} [arg2] - The success or error callback\n * @param {Function} [arg3] - The error callback\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n // load scripts\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, stripHTML } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set intial ratio\n setAspectRatio.call(this);\n\n // Load the API if not already\n if (!is.object(window.Vimeo)) {\n loadScript(this.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(this);\n })\n .catch(error => {\n this.debug.warn('Vimeo API failed to load', error);\n });\n } else {\n vimeo.ready.call(this);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams(\n extend(\n {},\n {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: !this.config.fullscreen.iosNative,\n },\n config,\n ),\n );\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n }\n\n const id = parseId(source);\n\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allowtransparency', '');\n iframe.setAttribute('allow', 'autoplay');\n\n // Get poster, if already set\n const { poster } = player;\n\n // Inject the package\n const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n\n // Get poster image\n fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => {\n if (is.empty(response)) {\n return;\n }\n\n // Get the URL for thumbnail\n const url = new URL(response[0].thumbnail_large);\n\n // Get original image\n url.pathname = `${url.pathname.split('_')[0]}.jpg`;\n\n // Set and show poster\n ui.setPoster.call(player, url.href).catch(() => {});\n });\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(error => {\n // Hide menu item (and menu if empty)\n if (error.name === 'Error') {\n controls.setSpeedMenu.call(player, []);\n }\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then(value => {\n currentSrc = value;\n controls.setDownloadLink.call(player);\n })\n .catch(error => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = `${width}:${height}`;\n setAspectRatio.call(this, player.embed.ratio);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/loadImage';\nimport loadScript from '../utils/loadScript';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Set aspect ratio\n setAspectRatio.call(this);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Load the API\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n\n // Setup callback for the API\n // YouTube has it's own system of course...\n window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];\n\n // Add to queue\n window.onYouTubeReadyCallbacks.push(() => {\n youtube.ready.call(this);\n });\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n window.onYouTubeReadyCallbacks.forEach(callback => {\n callback();\n });\n };\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n // Try via undocumented API method first\n // This method disappears now and then though...\n // https://github.com/sampotts/plyr/issues/709\n if (is.function(this.embed.getVideoData)) {\n const { title } = this.embed.getVideoData();\n\n if (is.empty(title)) {\n this.config.title = title;\n ui.setTitle.call(this);\n return;\n }\n }\n\n // Or via Google API\n const key = this.config.keys.google;\n if (is.string(key) && !is.empty(key)) {\n const url = format(this.config.urls.youtube.api, videoId, key);\n\n fetch(url)\n .then(result => {\n if (is.object(result)) {\n this.config.title = result.items[0].snippet.title;\n ui.setTitle.call(this);\n }\n })\n .catch(() => {});\n }\n },\n\n // API ready\n ready() {\n const player = this;\n\n // Ignore already setup (race condition)\n const currentId = player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n\n // Get poster, if already set\n const { poster } = player;\n\n // Replace media element\n const container = createElement('div', { id, poster });\n player.media = replaceElement(container, player.media);\n\n // Id to poster wrapper\n const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src))\n .then(posterSrc => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!posterSrc.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n\n const config = player.config.youtube;\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(id, {\n videoId,\n host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined,\n playerVars: extend(\n {},\n {\n autoplay: player.config.autoplay ? 1 : 0, // Autoplay\n hl: player.config.hl, // iframe interface language\n controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported\n disablekb: 1, // Disable keyboard as we handle it\n playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occured';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n player.options.speed = instance.getAvailablePlaybackRates();\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n setTimeout(() => ui.build.call(player), 50);\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Faux poster container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.extend.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/loadScript';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load() {\n if (this.enabled) {\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n }\n }\n\n /**\n * Get the ads instance ready\n */\n ready() {\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n }\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: this.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA() {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // We assume the adContainer is the video container of the plyr element\n // that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n }\n\n /**\n * Request advertisements\n */\n requestAds() {\n const { container } = this.player.elements;\n\n try {\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n event => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (e) {\n this.onAdError(e);\n }\n }\n\n /**\n * Update the ad countdown\n * @param {boolean} start\n */\n pollCountdown(start = false) {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n }\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} adsManagerLoadedEvent\n */\n onAdsManagerLoaded(event) {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n }\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent(event) {\n const { container } = this.player.elements;\n\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n const event = `ads${type.replace(/_/g, '').toLowerCase()}`;\n triggerEvent.call(this.player, this.player.media, event);\n };\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Bubble event\n dispatchEvent(event.type);\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // Fire event\n dispatchEvent(event.type);\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n this.loadAds();\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n dispatchEvent(event.type);\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n dispatchEvent(event.type);\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n case google.ima.AdEvent.Type.MIDPOINT:\n case google.ima.AdEvent.Type.COMPLETE:\n case google.ima.AdEvent.Type.IMPRESSION:\n case google.ima.AdEvent.Type.CLICK:\n dispatchEvent(event.type);\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n\n default:\n break;\n }\n }\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError(event) {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n }\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners() {\n const { container } = this.player.elements;\n let time;\n\n // Add listeners to the required events\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n }\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play() {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n }\n\n /**\n * Resume our video\n */\n resumeContent() {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play our video\n if (this.player.currentTime < this.player.duration) {\n this.player.play();\n }\n }\n\n /**\n * Pause our video\n */\n pauseContent() {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing.\n this.playing = true;\n\n // Pause our video.\n this.player.pause();\n }\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel() {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n }\n\n /**\n * Re-create our adsManager\n */\n loadAds() {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n }\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {string} event - Event type\n */\n trigger(event, ...args) {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on(event, callback) {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n }\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {number} time\n * @param {string} from\n */\n startSafetyTimer(time, from) {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n }\n\n /**\n * Clear our safety timer(s)\n * @param {string} from\n */\n clearSafetyTimer(from) {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n }\n}\n\nexport default Ads;\n","'use strict';\n// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)\nvar $export = require('./_export');\nvar $find = require('./_array-methods')(6);\nvar KEY = 'findIndex';\nvar forced = true;\n// Shouldn't skip holes\nif (KEY in []) Array(1)[KEY](function () { forced = false; });\n$export($export.P + $export.F * forced, 'Array', {\n findIndex: function findIndex(callbackfn /* , that = undefined */) {\n return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\nrequire('./_add-to-unscopables')(KEY);\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1]) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6]) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load() {\n // Togglethe regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) {\n return;\n }\n\n this.getThumbnails().then(() => {\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n this.loaded = true;\n });\n }\n\n // Download VTT files and parse them\n getThumbnails() {\n return new Promise(resolve => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n\n Promise.all(promises).then(() => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n });\n });\n }\n\n // Process individual VTT file\n getThumbnail(url) {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n if (!thumbnail.frames[0].text.startsWith('/')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n }\n\n startMove(event) {\n if (!this.loaded) {\n return;\n }\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n return;\n }\n\n // Wait until media has a duration\n if (!this.player.media.duration) {\n return;\n }\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n\n endMove() {\n this.toggleThumbContainer(false, true);\n }\n\n startScrubbing(event) {\n // Only act on left mouse button (0), or touch device (event.button is false)\n if (event.button === false || event.button === 0) {\n this.mouseDown = true;\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n }\n\n finishScrubbing() {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n }\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners() {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n }\n\n /**\n * Create HTML elements for image containers\n */\n render() {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.container.appendChild(timeContainer);\n\n // Inject the whole thumb\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n }\n\n showImageAtCurrentTime() {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.toggleThumbContainer(true);\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n this.toggleThumbContainer(hasThumb);\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumbnum or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n }\n\n // Show the image that's currently specified in this.showingThumb\n loadImage(qualityIndex = 0) {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () =>\n this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n }\n\n showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n }\n\n // Remove all preview images that aren't the designated current image\n removeOldImages(currentImage) {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n image.dataset.deleting = true;\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n }\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby(thumbNum, forward = true) {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename))\n this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n }\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n }\n\n get currentImageContainer() {\n if (this.mouseDown) {\n return this.elements.scrubbing.container;\n }\n\n return this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n if (this.mouseDown) {\n return this.currentScrubbingImageElement;\n }\n\n return this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer(toggle = false, clearShowing = false) {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n toggleScrubbingContainer(toggle = false) {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n }\n\n determineContainerAutoSizing() {\n if (this.elements.thumb.imageContainer.clientHeight > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n }\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos() {\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n }\n\n this.setThumbContainerPos();\n }\n\n setThumbContainerPos() {\n const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n const plyrRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const minVal = plyrRect.left - seekbarRect.left + 10;\n const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n if (previewPos < minVal) {\n previewPos = minVal;\n }\n\n if (previewPos > maxVal) {\n previewPos = maxVal;\n }\n\n container.style.left = `${previewPos}px`;\n }\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize() {\n this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`;\n // Can't use media.clientHeight - html5 video goes big and does black bars above and below\n this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`;\n }\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset(previewImage, frame) {\n if (!this.usingSprites) {\n return;\n }\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;\n previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;\n previewImage.style.left = `-${frame.x * multiplier}px`;\n previewImage.style.top = `-${frame.y * multiplier}px`;\n }\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Reload thumbnails\n if (this.previewThumbnails) {\n this.previewThumbnails.load();\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.4.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/previewThumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/loadSprite';\nimport { cloneDeep, extend } from './utils/objects';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (e) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div', { tabindex: 0 });\n wrap(this.media, this.elements.container);\n }\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.config.autoplay) {\n this.play();\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return Boolean(this.provider === providers.html5);\n }\n\n get isEmbed() {\n return Boolean(this.isYouTube || this.isVimeo);\n }\n\n get isYouTube() {\n return Boolean(this.provider === providers.youtube);\n }\n\n get isVimeo() {\n return Boolean(this.provider === providers.vimeo);\n }\n\n get isVideo() {\n return Boolean(this.type === types.video);\n }\n\n get isAudio() {\n return Boolean(this.type === types.audio);\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play() {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n }\n\n /**\n * Pause the media\n */\n pause() {\n if (!this.playing || !is.function(this.media.pause)) {\n return;\n }\n\n this.media.pause();\n }\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} input\n */\n togglePlay(input) {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n this.play();\n } else {\n this.pause();\n }\n }\n\n /**\n * Stop playback\n */\n stop() {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n }\n\n /**\n * Decrease volume\n * @param {boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume(step) {\n this.increaseVolume(-step);\n }\n\n /**\n * Set muted state\n * @param {boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {number} speed - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.debug.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the poster image for a video\n * @param {input} - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n /**\n * Set the autoplay state\n * @param {boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n const toggle = is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {number} - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay() {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n }\n\n /**\n * Toggle the player controls\n * @param {boolean} [toggle] - Whether to show the controls\n */\n toggleControls(toggle) {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n }\n\n /**\n * Add event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n on(event, callback) {\n on.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Add event listeners once\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n once(event, callback) {\n once.call(this, this.elements.container, event, callback);\n }\n\n /**\n * Remove event listeners\n * @param {string} event - Event type\n * @param {function} callback - Callback for when event occurs\n */\n off(event, callback) {\n off(this.elements.container, event, callback);\n }\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {function} callback - Callback for when destroy is complete\n * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy(callback, soft = false) {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Clear timeout\n clearTimeout(this.timers.loading);\n\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n }\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {string} type - Mime type\n */\n supports(type) {\n return support.mime.call(this, type);\n }\n\n /**\n * Check for support\n * @param {string} type - Player type (audio/video)\n * @param {string} provider - Provider (html5/youtube/vimeo)\n * @param {bool} inline - Where player has `playsinline` sttribute\n */\n static supported(type, provider, inline) {\n return support.check(type, provider, inline);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {string} url - URL for the SVG sprite\n * @param {string} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map(t => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n"]}
\ No newline at end of file diff --git a/dist/plyr.polyfilled.mjs b/dist/plyr.polyfilled.mjs new file mode 100644 index 00000000..e7961376 --- /dev/null +++ b/dist/plyr.polyfilled.mjs @@ -0,0 +1,11723 @@ +typeof navigator === "object" && // Polyfill for creating CustomEvents on IE9/10/11 + +// code pulled from: +// https://github.com/d4tocchini/customevent-polyfill +// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill + +(function() { + if (typeof window === 'undefined') { + return; + } + + try { + var ce = new window.CustomEvent('test', { cancelable: true }); + ce.preventDefault(); + if (ce.defaultPrevented !== true) { + // IE has problems with .preventDefault() on custom events + // http://stackoverflow.com/questions/23349191 + throw new Error('Could not prevent default'); + } + } catch (e) { + var CustomEvent = function(event, params) { + var evt, origPrevent; + params = params || { + bubbles: false, + cancelable: false, + detail: undefined + }; + + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent( + event, + params.bubbles, + params.cancelable, + params.detail + ); + origPrevent = evt.preventDefault; + evt.preventDefault = function() { + origPrevent.call(this); + try { + Object.defineProperty(this, 'defaultPrevented', { + get: function() { + return true; + } + }); + } catch (e) { + this.defaultPrevented = true; + } + }; + return evt; + }; + + CustomEvent.prototype = window.Event.prototype; + window.CustomEvent = CustomEvent; // expose definition to window + } +})(); + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +(function(global) {
+ /**
+ * Polyfill URLSearchParams
+ *
+ * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js
+ */
+
+ var checkIfIteratorIsSupported = function() {
+ try {
+ return !!Symbol.iterator;
+ } catch (error) {
+ return false;
+ }
+ };
+
+
+ var iteratorSupported = checkIfIteratorIsSupported();
+
+ var createIterator = function(items) {
+ var iterator = {
+ next: function() {
+ var value = items.shift();
+ return { done: value === void 0, value: value };
+ }
+ };
+
+ if (iteratorSupported) {
+ iterator[Symbol.iterator] = function() {
+ return iterator;
+ };
+ }
+
+ return iterator;
+ };
+
+ /**
+ * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing
+ * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.
+ */
+ var serializeParam = function(value) {
+ return encodeURIComponent(value).replace(/%20/g, '+');
+ };
+
+ var deserializeParam = function(value) {
+ return decodeURIComponent(value).replace(/\+/g, ' ');
+ };
+
+ var polyfillURLSearchParams = function() {
+
+ var URLSearchParams = function(searchString) {
+ Object.defineProperty(this, '_entries', { writable: true, value: {} });
+ var typeofSearchString = typeof searchString;
+
+ if (typeofSearchString === 'undefined') ; else if (typeofSearchString === 'string') {
+ if (searchString !== '') {
+ this._fromString(searchString);
+ }
+ } else if (searchString instanceof URLSearchParams) {
+ var _this = this;
+ searchString.forEach(function(value, name) {
+ _this.append(name, value);
+ });
+ } else if ((searchString !== null) && (typeofSearchString === 'object')) {
+ if (Object.prototype.toString.call(searchString) === '[object Array]') {
+ for (var i = 0; i < searchString.length; i++) {
+ var entry = searchString[i];
+ if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {
+ this.append(entry[0], entry[1]);
+ } else {
+ throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\'s input');
+ }
+ }
+ } else {
+ for (var key in searchString) {
+ if (searchString.hasOwnProperty(key)) {
+ this.append(key, searchString[key]);
+ }
+ }
+ }
+ } else {
+ throw new TypeError('Unsupported input\'s type for URLSearchParams');
+ }
+ };
+
+ var proto = URLSearchParams.prototype;
+
+ proto.append = function(name, value) {
+ if (name in this._entries) {
+ this._entries[name].push(String(value));
+ } else {
+ this._entries[name] = [String(value)];
+ }
+ };
+
+ proto.delete = function(name) {
+ delete this._entries[name];
+ };
+
+ proto.get = function(name) {
+ return (name in this._entries) ? this._entries[name][0] : null;
+ };
+
+ proto.getAll = function(name) {
+ return (name in this._entries) ? this._entries[name].slice(0) : [];
+ };
+
+ proto.has = function(name) {
+ return (name in this._entries);
+ };
+
+ proto.set = function(name, value) {
+ this._entries[name] = [String(value)];
+ };
+
+ proto.forEach = function(callback, thisArg) {
+ var entries;
+ for (var name in this._entries) {
+ if (this._entries.hasOwnProperty(name)) {
+ entries = this._entries[name];
+ for (var i = 0; i < entries.length; i++) {
+ callback.call(thisArg, entries[i], name, this);
+ }
+ }
+ }
+ };
+
+ proto.keys = function() {
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push(name);
+ });
+ return createIterator(items);
+ };
+
+ proto.values = function() {
+ var items = [];
+ this.forEach(function(value) {
+ items.push(value);
+ });
+ return createIterator(items);
+ };
+
+ proto.entries = function() {
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push([name, value]);
+ });
+ return createIterator(items);
+ };
+
+ if (iteratorSupported) {
+ proto[Symbol.iterator] = proto.entries;
+ }
+
+ proto.toString = function() {
+ var searchArray = [];
+ this.forEach(function(value, name) {
+ searchArray.push(serializeParam(name) + '=' + serializeParam(value));
+ });
+ return searchArray.join('&');
+ };
+
+
+ global.URLSearchParams = URLSearchParams;
+ };
+
+ if (!('URLSearchParams' in global) || (new URLSearchParams('?a=1').toString() !== 'a=1')) {
+ polyfillURLSearchParams();
+ }
+
+ var proto = URLSearchParams.prototype;
+
+ if (typeof proto.sort !== 'function') {
+ proto.sort = function() {
+ var _this = this;
+ var items = [];
+ this.forEach(function(value, name) {
+ items.push([name, value]);
+ if (!_this._entries) {
+ _this.delete(name);
+ }
+ });
+ items.sort(function(a, b) {
+ if (a[0] < b[0]) {
+ return -1;
+ } else if (a[0] > b[0]) {
+ return +1;
+ } else {
+ return 0;
+ }
+ });
+ if (_this._entries) { // force reset because IE keeps keys index
+ _this._entries = {};
+ }
+ for (var i = 0; i < items.length; i++) {
+ this.append(items[i][0], items[i][1]);
+ }
+ };
+ }
+
+ if (typeof proto._fromString !== 'function') {
+ Object.defineProperty(proto, '_fromString', {
+ enumerable: false,
+ configurable: false,
+ writable: false,
+ value: function(searchString) {
+ if (this._entries) {
+ this._entries = {};
+ } else {
+ var keys = [];
+ this.forEach(function(value, name) {
+ keys.push(name);
+ });
+ for (var i = 0; i < keys.length; i++) {
+ this.delete(keys[i]);
+ }
+ }
+
+ searchString = searchString.replace(/^\?/, '');
+ var attributes = searchString.split('&');
+ var attribute;
+ for (var i = 0; i < attributes.length; i++) {
+ attribute = attributes[i].split('=');
+ this.append(
+ deserializeParam(attribute[0]),
+ (attribute.length > 1) ? deserializeParam(attribute[1]) : ''
+ );
+ }
+ }
+ });
+ }
+
+ // HTMLAnchorElement
+
+})(
+ (typeof commonjsGlobal !== 'undefined') ? commonjsGlobal
+ : ((typeof window !== 'undefined') ? window
+ : ((typeof self !== 'undefined') ? self : commonjsGlobal))
+);
+
+(function(global) {
+ /**
+ * Polyfill URL
+ *
+ * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js
+ */
+
+ var checkIfURLIsSupported = function() {
+ try {
+ var u = new URL('b', 'http://a');
+ u.pathname = 'c%20d';
+ return (u.href === 'http://a/c%20d') && u.searchParams;
+ } catch (e) {
+ return false;
+ }
+ };
+
+
+ var polyfillURL = function() {
+ var _URL = global.URL;
+
+ var URL = function(url, base) {
+ if (typeof url !== 'string') url = String(url);
+
+ // Only create another document if the base is different from current location.
+ var doc = document, baseElement;
+ if (base && (global.location === void 0 || base !== global.location.href)) {
+ doc = document.implementation.createHTMLDocument('');
+ baseElement = doc.createElement('base');
+ baseElement.href = base;
+ doc.head.appendChild(baseElement);
+ try {
+ if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);
+ } catch (err) {
+ throw new Error('URL unable to set base ' + base + ' due to ' + err);
+ }
+ }
+
+ var anchorElement = doc.createElement('a');
+ anchorElement.href = url;
+ if (baseElement) {
+ doc.body.appendChild(anchorElement);
+ anchorElement.href = anchorElement.href; // force href to refresh
+ }
+
+ if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
+ throw new TypeError('Invalid URL');
+ }
+
+ Object.defineProperty(this, '_anchorElement', {
+ value: anchorElement
+ });
+
+
+ // create a linked searchParams which reflect its changes on URL
+ var searchParams = new URLSearchParams(this.search);
+ var enableSearchUpdate = true;
+ var enableSearchParamsUpdate = true;
+ var _this = this;
+ ['append', 'delete', 'set'].forEach(function(methodName) {
+ var method = searchParams[methodName];
+ searchParams[methodName] = function() {
+ method.apply(searchParams, arguments);
+ if (enableSearchUpdate) {
+ enableSearchParamsUpdate = false;
+ _this.search = searchParams.toString();
+ enableSearchParamsUpdate = true;
+ }
+ };
+ });
+
+ Object.defineProperty(this, 'searchParams', {
+ value: searchParams,
+ enumerable: true
+ });
+
+ var search = void 0;
+ Object.defineProperty(this, '_updateSearchParams', {
+ enumerable: false,
+ configurable: false,
+ writable: false,
+ value: function() {
+ if (this.search !== search) {
+ search = this.search;
+ if (enableSearchParamsUpdate) {
+ enableSearchUpdate = false;
+ this.searchParams._fromString(this.search);
+ enableSearchUpdate = true;
+ }
+ }
+ }
+ });
+ };
+
+ var proto = URL.prototype;
+
+ var linkURLWithAnchorAttribute = function(attributeName) {
+ Object.defineProperty(proto, attributeName, {
+ get: function() {
+ return this._anchorElement[attributeName];
+ },
+ set: function(value) {
+ this._anchorElement[attributeName] = value;
+ },
+ enumerable: true
+ });
+ };
+
+ ['hash', 'host', 'hostname', 'port', 'protocol']
+ .forEach(function(attributeName) {
+ linkURLWithAnchorAttribute(attributeName);
+ });
+
+ Object.defineProperty(proto, 'search', {
+ get: function() {
+ return this._anchorElement['search'];
+ },
+ set: function(value) {
+ this._anchorElement['search'] = value;
+ this._updateSearchParams();
+ },
+ enumerable: true
+ });
+
+ Object.defineProperties(proto, {
+
+ 'toString': {
+ get: function() {
+ var _this = this;
+ return function() {
+ return _this.href;
+ };
+ }
+ },
+
+ 'href': {
+ get: function() {
+ return this._anchorElement.href.replace(/\?$/, '');
+ },
+ set: function(value) {
+ this._anchorElement.href = value;
+ this._updateSearchParams();
+ },
+ enumerable: true
+ },
+
+ 'pathname': {
+ get: function() {
+ return this._anchorElement.pathname.replace(/(^\/?)/, '/');
+ },
+ set: function(value) {
+ this._anchorElement.pathname = value;
+ },
+ enumerable: true
+ },
+
+ 'origin': {
+ get: function() {
+ // get expected port from protocol
+ var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];
+ // add port to origin if, expected port is different than actual port
+ // and it is not empty f.e http://foo:8080
+ // 8080 != 80 && 8080 != ''
+ var addPortToOrigin = this._anchorElement.port != expectedPort &&
+ this._anchorElement.port !== '';
+
+ return this._anchorElement.protocol +
+ '//' +
+ this._anchorElement.hostname +
+ (addPortToOrigin ? (':' + this._anchorElement.port) : '');
+ },
+ enumerable: true
+ },
+
+ 'password': { // TODO
+ get: function() {
+ return '';
+ },
+ set: function(value) {
+ },
+ enumerable: true
+ },
+
+ 'username': { // TODO
+ get: function() {
+ return '';
+ },
+ set: function(value) {
+ },
+ enumerable: true
+ },
+ });
+
+ URL.createObjectURL = function(blob) {
+ return _URL.createObjectURL.apply(_URL, arguments);
+ };
+
+ URL.revokeObjectURL = function(url) {
+ return _URL.revokeObjectURL.apply(_URL, arguments);
+ };
+
+ global.URL = URL;
+
+ };
+
+ if (!checkIfURLIsSupported()) {
+ polyfillURL();
+ }
+
+ if ((global.location !== void 0) && !('origin' in global.location)) {
+ var getOrigin = function() {
+ return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');
+ };
+
+ try {
+ Object.defineProperty(global.location, 'origin', {
+ get: getOrigin,
+ enumerable: true
+ });
+ } catch (e) {
+ setInterval(function() {
+ global.location.origin = getOrigin();
+ }, 100);
+ }
+ }
+
+})(
+ (typeof commonjsGlobal !== 'undefined') ? commonjsGlobal
+ : ((typeof window !== 'undefined') ? window
+ : ((typeof self !== 'undefined') ? self : commonjsGlobal))
+); + +var _aFunction = function (it) { + if (typeof it != 'function') throw TypeError(it + ' is not a function!'); + return it; +}; + +// optional / simple context binding + +var _ctx = function (fn, that, length) { + _aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; +}; + +var _global = createCommonjsModule(function (module) { +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef +}); + +var _core = createCommonjsModule(function (module) { +var core = module.exports = { version: '2.6.3' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef +}); +var _core_1 = _core.version; + +var _isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + +var _anObject = function (it) { + if (!_isObject(it)) throw TypeError(it + ' is not an object!'); + return it; +}; + +var _fails = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; + } +}; + +// Thank's IE8 for his funny defineProperty +var _descriptors = !_fails(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; +}); + +var document$1 = _global.document; +// typeof document.createElement is 'object' in old IE +var is = _isObject(document$1) && _isObject(document$1.createElement); +var _domCreate = function (it) { + return is ? document$1.createElement(it) : {}; +}; + +var _ie8DomDefine = !_descriptors && !_fails(function () { + return Object.defineProperty(_domCreate('div'), 'a', { get: function () { return 7; } }).a != 7; +}); + +// 7.1.1 ToPrimitive(input [, PreferredType]) + +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +var _toPrimitive = function (it, S) { + if (!_isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); +}; + +var dP = Object.defineProperty; + +var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) { + _anObject(O); + P = _toPrimitive(P, true); + _anObject(Attributes); + if (_ie8DomDefine) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; +}; + +var _objectDp = { + f: f +}; + +var _propertyDesc = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; +}; + +var _hide = _descriptors ? function (object, key, value) { + return _objectDp.f(object, key, _propertyDesc(1, value)); +} : function (object, key, value) { + object[key] = value; + return object; +}; + +var hasOwnProperty = {}.hasOwnProperty; +var _has = function (it, key) { + return hasOwnProperty.call(it, key); +}; + +var id = 0; +var px = Math.random(); +var _uid = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + +var _redefine = createCommonjsModule(function (module) { +var SRC = _uid('src'); +var TO_STRING = 'toString'; +var $toString = Function[TO_STRING]; +var TPL = ('' + $toString).split(TO_STRING); + +_core.inspectSource = function (it) { + return $toString.call(it); +}; + +(module.exports = function (O, key, val, safe) { + var isFunction = typeof val == 'function'; + if (isFunction) _has(val, 'name') || _hide(val, 'name', key); + if (O[key] === val) return; + if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); + if (O === _global) { + O[key] = val; + } else if (!safe) { + delete O[key]; + _hide(O, key, val); + } else if (O[key]) { + O[key] = val; + } else { + _hide(O, key, val); + } +// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative +})(Function.prototype, TO_STRING, function toString() { + return typeof this == 'function' && this[SRC] || $toString.call(this); +}); +}); + +var PROTOTYPE = 'prototype'; + +var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE]; + var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {}); + var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); + var key, own, out, exp; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out; + // extend global + if (target) _redefine(target, key, out, type & $export.U); + // export + if (exports[key] != out) _hide(exports, key, exp); + if (IS_PROTO && expProto[key] != out) expProto[key] = out; + } +}; +_global.core = _core; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +var _export = $export; + +// 7.2.1 RequireObjectCoercible(argument) +var _defined = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; +}; + +// 7.1.13 ToObject(argument) + +var _toObject = function (it) { + return Object(_defined(it)); +}; + +// call something on iterator step with safe closing on error + +var _iterCall = function (iterator, fn, value, entries) { + try { + return entries ? fn(_anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch (e) { + var ret = iterator['return']; + if (ret !== undefined) _anObject(ret.call(iterator)); + throw e; + } +}; + +var _iterators = {}; + +var _library = false; + +var _shared = createCommonjsModule(function (module) { +var SHARED = '__core-js_shared__'; +var store = _global[SHARED] || (_global[SHARED] = {}); + +(module.exports = function (key, value) { + return store[key] || (store[key] = value !== undefined ? value : {}); +})('versions', []).push({ + version: _core.version, + mode: 'global', + copyright: '© 2019 Denis Pushkarev (zloirock.ru)' +}); +}); + +var _wks = createCommonjsModule(function (module) { +var store = _shared('wks'); + +var Symbol = _global.Symbol; +var USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : _uid)('Symbol.' + name)); +}; + +$exports.store = store; +}); + +// check on default Array iterator + +var ITERATOR = _wks('iterator'); +var ArrayProto = Array.prototype; + +var _isArrayIter = function (it) { + return it !== undefined && (_iterators.Array === it || ArrayProto[ITERATOR] === it); +}; + +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +var _toInteger = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + +// 7.1.15 ToLength + +var min = Math.min; +var _toLength = function (it) { + return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + +var _createProperty = function (object, index, value) { + if (index in object) _objectDp.f(object, index, _propertyDesc(0, value)); + else object[index] = value; +}; + +var toString = {}.toString; + +var _cof = function (it) { + return toString.call(it).slice(8, -1); +}; + +// getting tag from 19.1.3.6 Object.prototype.toString() + +var TAG = _wks('toStringTag'); +// ES3 wrong here +var ARG = _cof(function () { return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function (it, key) { + try { + return it[key]; + } catch (e) { /* empty */ } +}; + +var _classof = function (it) { + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? _cof(O) + // ES3 arguments fallback + : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; + +var ITERATOR$1 = _wks('iterator'); + +var core_getIteratorMethod = _core.getIteratorMethod = function (it) { + if (it != undefined) return it[ITERATOR$1] + || it['@@iterator'] + || _iterators[_classof(it)]; +}; + +var ITERATOR$2 = _wks('iterator'); +var SAFE_CLOSING = false; + +try { + var riter = [7][ITERATOR$2](); + riter['return'] = function () { SAFE_CLOSING = true; }; +} catch (e) { /* empty */ } + +var _iterDetect = function (exec, skipClosing) { + if (!skipClosing && !SAFE_CLOSING) return false; + var safe = false; + try { + var arr = [7]; + var iter = arr[ITERATOR$2](); + iter.next = function () { return { done: safe = true }; }; + arr[ITERATOR$2] = function () { return iter; }; + exec(arr); + } catch (e) { /* empty */ } + return safe; +}; + +_export(_export.S + _export.F * !_iterDetect(function (iter) { }), 'Array', { + // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) + from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { + var O = _toObject(arrayLike); + var C = typeof this == 'function' ? this : Array; + var aLen = arguments.length; + var mapfn = aLen > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; + var index = 0; + var iterFn = core_getIteratorMethod(O); + var length, result, step, iterator; + if (mapping) mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); + // if object isn't iterable or it's array with default iterator - use simple case + if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) { + for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) { + _createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value); + } + } else { + length = _toLength(O.length); + for (result = new C(length); length > index; index++) { + _createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); + } + } + result.length = index; + return result; + } +}); + +// fallback for non-array-like ES3 and non-enumerable old V8 strings + +// eslint-disable-next-line no-prototype-builtins +var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return _cof(it) == 'String' ? it.split('') : Object(it); +}; + +// 7.2.2 IsArray(argument) + +var _isArray = Array.isArray || function isArray(arg) { + return _cof(arg) == 'Array'; +}; + +var SPECIES = _wks('species'); + +var _arraySpeciesConstructor = function (original) { + var C; + if (_isArray(original)) { + C = original.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) C = undefined; + if (_isObject(C)) { + C = C[SPECIES]; + if (C === null) C = undefined; + } + } return C === undefined ? Array : C; +}; + +// 9.4.2.3 ArraySpeciesCreate(originalArray, length) + + +var _arraySpeciesCreate = function (original, length) { + return new (_arraySpeciesConstructor(original))(length); +}; + +// 0 -> Array#forEach +// 1 -> Array#map +// 2 -> Array#filter +// 3 -> Array#some +// 4 -> Array#every +// 5 -> Array#find +// 6 -> Array#findIndex + + + + + +var _arrayMethods = function (TYPE, $create) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + var create = $create || _arraySpeciesCreate; + return function ($this, callbackfn, that) { + var O = _toObject($this); + var self = _iobject(O); + var f = _ctx(callbackfn, that, 3); + var length = _toLength(self.length); + var index = 0; + var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined; + var val, res; + for (;length > index; index++) if (NO_HOLES || index in self) { + val = self[index]; + res = f(val, index, O); + if (TYPE) { + if (IS_MAP) result[index] = res; // map + else if (res) switch (TYPE) { + case 3: return true; // some + case 5: return val; // find + case 6: return index; // findIndex + case 2: result.push(val); // filter + } else if (IS_EVERY) return false; // every + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; + }; +}; + +// 22.1.3.31 Array.prototype[@@unscopables] +var UNSCOPABLES = _wks('unscopables'); +var ArrayProto$1 = Array.prototype; +if (ArrayProto$1[UNSCOPABLES] == undefined) _hide(ArrayProto$1, UNSCOPABLES, {}); +var _addToUnscopables = function (key) { + ArrayProto$1[UNSCOPABLES][key] = true; +}; + +// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined) + +var $find = _arrayMethods(5); +var KEY = 'find'; +var forced = true; +// Shouldn't skip holes +if (KEY in []) Array(1)[KEY](function () { forced = false; }); +_export(_export.P + _export.F * forced, 'Array', { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); +_addToUnscopables(KEY); + +var f$1 = {}.propertyIsEnumerable; + +var _objectPie = { + f: f$1 +}; + +// to indexed object, toObject with fallback for non-array-like ES3 strings + + +var _toIobject = function (it) { + return _iobject(_defined(it)); +}; + +var gOPD = Object.getOwnPropertyDescriptor; + +var f$2 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) { + O = _toIobject(O); + P = _toPrimitive(P, true); + if (_ie8DomDefine) try { + return gOPD(O, P); + } catch (e) { /* empty */ } + if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]); +}; + +var _objectGopd = { + f: f$2 +}; + +// Works with __proto__ only. Old v8 can't work with null proto objects. +/* eslint-disable no-proto */ + + +var check = function (O, proto) { + _anObject(O); + if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); +}; +var _setProto = { + set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line + function (test, buggy, set) { + try { + set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2); + set(test, []); + buggy = !(test instanceof Array); + } catch (e) { buggy = true; } + return function setPrototypeOf(O, proto) { + check(O, proto); + if (buggy) O.__proto__ = proto; + else set(O, proto); + return O; + }; + }({}, false) : undefined), + check: check +}; + +var setPrototypeOf = _setProto.set; +var _inheritIfRequired = function (that, target, C) { + var S = target.constructor; + var P; + if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf) { + setPrototypeOf(that, P); + } return that; +}; + +var max = Math.max; +var min$1 = Math.min; +var _toAbsoluteIndex = function (index, length) { + index = _toInteger(index); + return index < 0 ? max(index + length, 0) : min$1(index, length); +}; + +// false -> Array#indexOf +// true -> Array#includes + + + +var _arrayIncludes = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = _toIobject($this); + var length = _toLength(O.length); + var index = _toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; + +var shared = _shared('keys'); + +var _sharedKey = function (key) { + return shared[key] || (shared[key] = _uid(key)); +}; + +var arrayIndexOf = _arrayIncludes(false); +var IE_PROTO = _sharedKey('IE_PROTO'); + +var _objectKeysInternal = function (object, names) { + var O = _toIobject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) _has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (_has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; +}; + +// IE 8- don't enum bug keys +var _enumBugKeys = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + +// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) + +var hiddenKeys = _enumBugKeys.concat('length', 'prototype'); + +var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return _objectKeysInternal(O, hiddenKeys); +}; + +var _objectGopn = { + f: f$3 +}; + +var _stringWs = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; + +var space = '[' + _stringWs + ']'; +var non = '\u200b\u0085'; +var ltrim = RegExp('^' + space + space + '*'); +var rtrim = RegExp(space + space + '*$'); + +var exporter = function (KEY, exec, ALIAS) { + var exp = {}; + var FORCE = _fails(function () { + return !!_stringWs[KEY]() || non[KEY]() != non; + }); + var fn = exp[KEY] = FORCE ? exec(trim) : _stringWs[KEY]; + if (ALIAS) exp[ALIAS] = fn; + _export(_export.P + _export.F * FORCE, 'String', exp); +}; + +// 1 -> String#trimLeft +// 2 -> String#trimRight +// 3 -> String#trim +var trim = exporter.trim = function (string, TYPE) { + string = String(_defined(string)); + if (TYPE & 1) string = string.replace(ltrim, ''); + if (TYPE & 2) string = string.replace(rtrim, ''); + return string; +}; + +var _stringTrim = exporter; + +// 19.1.2.14 / 15.2.3.14 Object.keys(O) + + + +var _objectKeys = Object.keys || function keys(O) { + return _objectKeysInternal(O, _enumBugKeys); +}; + +var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) { + _anObject(O); + var keys = _objectKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) _objectDp.f(O, P = keys[i++], Properties[P]); + return O; +}; + +var document$2 = _global.document; +var _html = document$2 && document$2.documentElement; + +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) + + + +var IE_PROTO$1 = _sharedKey('IE_PROTO'); +var Empty = function () { /* empty */ }; +var PROTOTYPE$1 = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = _domCreate('iframe'); + var i = _enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + _html.appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE$1][_enumBugKeys[i]]; + return createDict(); +}; + +var _objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE$1] = _anObject(O); + result = new Empty(); + Empty[PROTOTYPE$1] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO$1] = O; + } else result = createDict(); + return Properties === undefined ? result : _objectDps(result, Properties); +}; + +var gOPN = _objectGopn.f; +var gOPD$1 = _objectGopd.f; +var dP$1 = _objectDp.f; +var $trim = _stringTrim.trim; +var NUMBER = 'Number'; +var $Number = _global[NUMBER]; +var Base = $Number; +var proto = $Number.prototype; +// Opera ~12 has broken Object#toString +var BROKEN_COF = _cof(_objectCreate(proto)) == NUMBER; +var TRIM = 'trim' in String.prototype; + +// 7.1.3 ToNumber(argument) +var toNumber = function (argument) { + var it = _toPrimitive(argument, false); + if (typeof it == 'string' && it.length > 2) { + it = TRIM ? it.trim() : $trim(it, 3); + var first = it.charCodeAt(0); + var third, radix, maxCode; + if (first === 43 || first === 45) { + third = it.charCodeAt(2); + if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix + } else if (first === 48) { + switch (it.charCodeAt(1)) { + case 66: case 98: radix = 2; maxCode = 49; break; // fast equal /^0b[01]+$/i + case 79: case 111: radix = 8; maxCode = 55; break; // fast equal /^0o[0-7]+$/i + default: return +it; + } + for (var digits = it.slice(2), i = 0, l = digits.length, code; i < l; i++) { + code = digits.charCodeAt(i); + // parseInt parses a string to a first unavailable symbol + // but ToNumber should return NaN if a string contains unavailable symbols + if (code < 48 || code > maxCode) return NaN; + } return parseInt(digits, radix); + } + } return +it; +}; + +if (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) { + $Number = function Number(value) { + var it = arguments.length < 1 ? 0 : value; + var that = this; + return that instanceof $Number + // check on 1..constructor(foo) case + && (BROKEN_COF ? _fails(function () { proto.valueOf.call(that); }) : _cof(that) != NUMBER) + ? _inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it); + }; + for (var keys = _descriptors ? gOPN(Base) : ( + // ES3: + 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + + // ES6 (in case, if modules with ES6 Number statics required before): + 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' + + 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger' + ).split(','), j = 0, key; keys.length > j; j++) { + if (_has(Base, key = keys[j]) && !_has($Number, key)) { + dP$1($Number, key, gOPD$1(Base, key)); + } + } + $Number.prototype = proto; + proto.constructor = $Number; + _redefine(_global, NUMBER, $Number); +} + +// most Object methods by ES6 should accept primitives + + + +var _objectSap = function (KEY, exec) { + var fn = (_core.Object || {})[KEY] || Object[KEY]; + var exp = {}; + exp[KEY] = exec(fn); + _export(_export.S + _export.F * _fails(function () { fn(1); }), 'Object', exp); +}; + +// 19.1.2.14 Object.keys(O) + + + +_objectSap('keys', function () { + return function keys(it) { + return _objectKeys(_toObject(it)); + }; +}); + +// 7.2.8 IsRegExp(argument) + + +var MATCH = _wks('match'); +var _isRegexp = function (it) { + var isRegExp; + return _isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : _cof(it) == 'RegExp'); +}; + +// helper for String#{startsWith, endsWith, includes} + + + +var _stringContext = function (that, searchString, NAME) { + if (_isRegexp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!"); + return String(_defined(that)); +}; + +var MATCH$1 = _wks('match'); +var _failsIsRegexp = function (KEY) { + var re = /./; + try { + '/./'[KEY](re); + } catch (e) { + try { + re[MATCH$1] = false; + return !'/./'[KEY](re); + } catch (f) { /* empty */ } + } return true; +}; + +var INCLUDES = 'includes'; + +_export(_export.P + _export.F * _failsIsRegexp(INCLUDES), 'String', { + includes: function includes(searchString /* , position = 0 */) { + return !!~_stringContext(this, searchString, INCLUDES) + .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined); + } +}); + +// https://github.com/tc39/Array.prototype.includes + +var $includes = _arrayIncludes(true); + +_export(_export.P, 'Array', { + includes: function includes(el /* , fromIndex = 0 */) { + return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); + } +}); + +_addToUnscopables('includes'); + +// 7.2.9 SameValue(x, y) +var _sameValue = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare + return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; +}; + +var builtinExec = RegExp.prototype.exec; + + // `RegExpExec` abstract operation +// https://tc39.github.io/ecma262/#sec-regexpexec +var _regexpExecAbstract = function (R, S) { + var exec = R.exec; + if (typeof exec === 'function') { + var result = exec.call(R, S); + if (typeof result !== 'object') { + throw new TypeError('RegExp exec method returned something other than an Object or null'); + } + return result; + } + if (_classof(R) !== 'RegExp') { + throw new TypeError('RegExp#exec called on incompatible receiver'); + } + return builtinExec.call(R, S); +}; + +// 21.2.5.3 get RegExp.prototype.flags + +var _flags = function () { + var that = _anObject(this); + var result = ''; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.unicode) result += 'u'; + if (that.sticky) result += 'y'; + return result; +}; + +var nativeExec = RegExp.prototype.exec; +// This always refers to the native implementation, because the +// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js, +// which loads this file before patching the method. +var nativeReplace = String.prototype.replace; + +var patchedExec = nativeExec; + +var LAST_INDEX = 'lastIndex'; + +var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/, + re2 = /b*/g; + nativeExec.call(re1, 'a'); + nativeExec.call(re2, 'a'); + return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0; +})(); + +// nonparticipating capturing group, copied from es5-shim's String#split patch. +var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + +var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED; + +if (PATCH) { + patchedExec = function exec(str) { + var re = this; + var lastIndex, reCopy, match, i; + + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + re.source + '$(?!\\s)', _flags.call(re)); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX]; + + match = nativeExec.call(re, str); + + if (UPDATES_LAST_INDEX_WRONG && match) { + re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/ + // eslint-disable-next-line no-loop-func + nativeReplace.call(match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; + } + }); + } + + return match; + }; +} + +var _regexpExec = patchedExec; + +_export({ + target: 'RegExp', + proto: true, + forced: _regexpExec !== /./.exec +}, { + exec: _regexpExec +}); + +var SPECIES$1 = _wks('species'); + +var REPLACE_SUPPORTS_NAMED_GROUPS = !_fails(function () { + // #replace needs built-in support for named groups. + // #match works fine because it just return the exec results, even if it has + // a "grops" property. + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + return ''.replace(re, '$<a>') !== '7'; +}); + +var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = (function () { + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length === 2 && result[0] === 'a' && result[1] === 'b'; +})(); + +var _fixReWks = function (KEY, length, exec) { + var SYMBOL = _wks(KEY); + + var DELEGATES_TO_SYMBOL = !_fails(function () { + // String methods call symbol-named RegEp methods + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) != 7; + }); + + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !_fails(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + re.exec = function () { execCalled = true; return null; }; + if (KEY === 'split') { + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES$1] = function () { return re; }; + } + re[SYMBOL](''); + return !execCalled; + }) : undefined; + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) || + (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) + ) { + var nativeRegExpMethod = /./[SYMBOL]; + var fns = exec( + _defined, + SYMBOL, + ''[KEY], + function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) { + if (regexp.exec === _regexpExec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) }; + } + return { done: true, value: nativeMethod.call(str, regexp, arg2) }; + } + return { done: false }; + } + ); + var strfn = fns[0]; + var rxfn = fns[1]; + + _redefine(String.prototype, KEY, strfn); + _hide(RegExp.prototype, SYMBOL, length == 2 + // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) + // 21.2.5.11 RegExp.prototype[@@split](string, limit) + ? function (string, arg) { return rxfn.call(string, this, arg); } + // 21.2.5.6 RegExp.prototype[@@match](string) + // 21.2.5.9 RegExp.prototype[@@search](string) + : function (string) { return rxfn.call(string, this); } + ); + } +}; + +// @@search logic +_fixReWks('search', 1, function (defined, SEARCH, $search, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.github.io/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[SEARCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@search + function (regexp) { + var res = maybeCallNative($search, regexp, this); + if (res.done) return res.value; + var rx = _anObject(regexp); + var S = String(this); + var previousLastIndex = rx.lastIndex; + if (!_sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = _regexpExecAbstract(rx, S); + if (!_sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; +}); + +// 21.2.5.3 get RegExp.prototype.flags() +if (_descriptors && /./g.flags != 'g') _objectDp.f(RegExp.prototype, 'flags', { + configurable: true, + get: _flags +}); + +var TO_STRING = 'toString'; +var $toString = /./[TO_STRING]; + +var define = function (fn) { + _redefine(RegExp.prototype, TO_STRING, fn, true); +}; + +// 21.2.5.14 RegExp.prototype.toString() +if (_fails(function () { return $toString.call({ source: 'a', flags: 'b' }) != '/a/b'; })) { + define(function toString() { + var R = _anObject(this); + return '/'.concat(R.source, '/', + 'flags' in R ? R.flags : !_descriptors && R instanceof RegExp ? _flags.call(R) : undefined); + }); +// FF44- RegExp#toString has a wrong name +} else if ($toString.name != TO_STRING) { + define(function toString() { + return $toString.call(this); + }); +} + +var _iterStep = function (done, value) { + return { value: value, done: !!done }; +}; + +var def = _objectDp.f; + +var TAG$1 = _wks('toStringTag'); + +var _setToStringTag = function (it, tag, stat) { + if (it && !_has(it = stat ? it : it.prototype, TAG$1)) def(it, TAG$1, { configurable: true, value: tag }); +}; + +var IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +_hide(IteratorPrototype, _wks('iterator'), function () { return this; }); + +var _iterCreate = function (Constructor, NAME, next) { + Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) }); + _setToStringTag(Constructor, NAME + ' Iterator'); +}; + +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) + + +var IE_PROTO$2 = _sharedKey('IE_PROTO'); +var ObjectProto = Object.prototype; + +var _objectGpo = Object.getPrototypeOf || function (O) { + O = _toObject(O); + if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + +var ITERATOR$3 = _wks('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; + +var returnThis = function () { return this; }; + +var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + _iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR$3] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = _objectGpo($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + _setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!_library && typeof IteratorPrototype[ITERATOR$3] != 'function') _hide(IteratorPrototype, ITERATOR$3, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR$3])) { + _hide(proto, ITERATOR$3, $default); + } + // Plug for library + _iterators[NAME] = $default; + _iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) _redefine(proto, key, methods[key]); + } else _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) { + this._t = _toIobject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return _iterStep(1); + } + if (kind == 'keys') return _iterStep(0, index); + if (kind == 'values') return _iterStep(0, O[index]); + return _iterStep(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +_iterators.Arguments = _iterators.Array; + +_addToUnscopables('keys'); +_addToUnscopables('values'); +_addToUnscopables('entries'); + +var ITERATOR$4 = _wks('iterator'); +var TO_STRING_TAG = _wks('toStringTag'); +var ArrayValues = _iterators.Array; + +var DOMIterables = { + CSSRuleList: true, // TODO: Not spec compliant, should be false. + CSSStyleDeclaration: false, + CSSValueList: false, + ClientRectList: false, + DOMRectList: false, + DOMStringList: false, + DOMTokenList: true, + DataTransferItemList: false, + FileList: false, + HTMLAllCollection: false, + HTMLCollection: false, + HTMLFormElement: false, + HTMLSelectElement: false, + MediaList: true, // TODO: Not spec compliant, should be false. + MimeTypeArray: false, + NamedNodeMap: false, + NodeList: true, + PaintRequestList: false, + Plugin: false, + PluginArray: false, + SVGLengthList: false, + SVGNumberList: false, + SVGPathSegList: false, + SVGPointList: false, + SVGStringList: false, + SVGTransformList: false, + SourceBufferList: false, + StyleSheetList: true, // TODO: Not spec compliant, should be false. + TextTrackCueList: false, + TextTrackList: false, + TouchList: false +}; + +for (var collections = _objectKeys(DOMIterables), i = 0; i < collections.length; i++) { + var NAME = collections[i]; + var explicit = DOMIterables[NAME]; + var Collection = _global[NAME]; + var proto$1 = Collection && Collection.prototype; + var key$1; + if (proto$1) { + if (!proto$1[ITERATOR$4]) _hide(proto$1, ITERATOR$4, ArrayValues); + if (!proto$1[TO_STRING_TAG]) _hide(proto$1, TO_STRING_TAG, NAME); + _iterators[NAME] = ArrayValues; + if (explicit) for (key$1 in es6_array_iterator) if (!proto$1[key$1]) _redefine(proto$1, key$1, es6_array_iterator[key$1], true); + } +} + +// true -> String#at +// false -> String#codePointAt +var _stringAt = function (TO_STRING) { + return function (that, pos) { + var s = String(_defined(that)); + var i = _toInteger(pos); + var l = s.length; + var a, b; + if (i < 0 || i >= l) return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; +}; + +var $at = _stringAt(true); + +// 21.1.3.27 String.prototype[@@iterator]() +_iterDefine(String, 'String', function (iterated) { + this._t = String(iterated); // target + this._i = 0; // next index +// 21.1.5.2.1 %StringIteratorPrototype%.next() +}, function () { + var O = this._t; + var index = this._i; + var point; + if (index >= O.length) return { value: undefined, done: true }; + point = $at(O, index); + this._i += point.length; + return { value: point, done: false }; +}); + +var _meta = createCommonjsModule(function (module) { +var META = _uid('meta'); + + +var setDesc = _objectDp.f; +var id = 0; +var isExtensible = Object.isExtensible || function () { + return true; +}; +var FREEZE = !_fails(function () { + return isExtensible(Object.preventExtensions({})); +}); +var setMeta = function (it) { + setDesc(it, META, { value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + } }); +}; +var fastKey = function (it, create) { + // return primitive with prefix + if (!_isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if (!_has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return 'F'; + // not necessary to add metadata + if (!create) return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; +}; +var getWeak = function (it, create) { + if (!_has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return true; + // not necessary to add metadata + if (!create) return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; +}; +// add metadata on freeze-family methods calling +var onFreeze = function (it) { + if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it); + return it; +}; +var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze +}; +}); +var _meta_1 = _meta.KEY; +var _meta_2 = _meta.NEED; +var _meta_3 = _meta.fastKey; +var _meta_4 = _meta.getWeak; +var _meta_5 = _meta.onFreeze; + +var f$4 = Object.getOwnPropertySymbols; + +var _objectGops = { + f: f$4 +}; + +// 19.1.2.1 Object.assign(target, source, ...) + + + + + +var $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +var _objectAssign = !$assign || _fails(function () { + var A = {}; + var B = {}; + // eslint-disable-next-line no-undef + var S = Symbol(); + var K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function (k) { B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source) { // eslint-disable-line no-unused-vars + var T = _toObject(target); + var aLen = arguments.length; + var index = 1; + var getSymbols = _objectGops.f; + var isEnum = _objectPie.f; + while (aLen > index) { + var S = _iobject(arguments[index++]); + var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; + } return T; +} : $assign; + +var _redefineAll = function (target, src, safe) { + for (var key in src) _redefine(target, key, src[key], safe); + return target; +}; + +var _anInstance = function (it, Constructor, name, forbiddenField) { + if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + +var _forOf = createCommonjsModule(function (module) { +var BREAK = {}; +var RETURN = {}; +var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { + var iterFn = ITERATOR ? function () { return iterable; } : core_getIteratorMethod(iterable); + var f = _ctx(fn, that, entries ? 2 : 1); + var index = 0; + var length, step, iterator, result; + if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if (_isArrayIter(iterFn)) for (length = _toLength(iterable.length); length > index; index++) { + result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if (result === BREAK || result === RETURN) return result; + } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { + result = _iterCall(iterator, f, step.value, entries); + if (result === BREAK || result === RETURN) return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; +}); + +var _validateCollection = function (it, TYPE) { + if (!_isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); + return it; +}; + +var getWeak = _meta.getWeak; + + + + + + + +var arrayFind = _arrayMethods(5); +var arrayFindIndex = _arrayMethods(6); +var id$1 = 0; + +// fallback for uncaught frozen keys +var uncaughtFrozenStore = function (that) { + return that._l || (that._l = new UncaughtFrozenStore()); +}; +var UncaughtFrozenStore = function () { + this.a = []; +}; +var findUncaughtFrozen = function (store, key) { + return arrayFind(store.a, function (it) { + return it[0] === key; + }); +}; +UncaughtFrozenStore.prototype = { + get: function (key) { + var entry = findUncaughtFrozen(this, key); + if (entry) return entry[1]; + }, + has: function (key) { + return !!findUncaughtFrozen(this, key); + }, + set: function (key, value) { + var entry = findUncaughtFrozen(this, key); + if (entry) entry[1] = value; + else this.a.push([key, value]); + }, + 'delete': function (key) { + var index = arrayFindIndex(this.a, function (it) { + return it[0] === key; + }); + if (~index) this.a.splice(index, 1); + return !!~index; + } +}; + +var _collectionWeak = { + getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { + var C = wrapper(function (that, iterable) { + _anInstance(that, C, NAME, '_i'); + that._t = NAME; // collection type + that._i = id$1++; // collection id + that._l = undefined; // leak store for uncaught frozen objects + if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); + }); + _redefineAll(C.prototype, { + // 23.3.3.2 WeakMap.prototype.delete(key) + // 23.4.3.3 WeakSet.prototype.delete(value) + 'delete': function (key) { + if (!_isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key); + return data && _has(data, this._i) && delete data[this._i]; + }, + // 23.3.3.4 WeakMap.prototype.has(key) + // 23.4.3.4 WeakSet.prototype.has(value) + has: function has(key) { + if (!_isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key); + return data && _has(data, this._i); + } + }); + return C; + }, + def: function (that, key, value) { + var data = getWeak(_anObject(key), true); + if (data === true) uncaughtFrozenStore(that).set(key, value); + else data[that._i] = value; + return that; + }, + ufstore: uncaughtFrozenStore +}; + +var _collection = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { + var Base = _global[NAME]; + var C = Base; + var ADDER = IS_MAP ? 'set' : 'add'; + var proto = C && C.prototype; + var O = {}; + var fixMethod = function (KEY) { + var fn = proto[KEY]; + _redefine(proto, KEY, + KEY == 'delete' ? function (a) { + return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'has' ? function has(a) { + return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'get' ? function get(a) { + return IS_WEAK && !_isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; } + : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; } + ); + }; + if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () { + new C().entries().next(); + }))) { + // create collection constructor + C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); + _redefineAll(C.prototype, methods); + _meta.NEED = true; + } else { + var instance = new C(); + // early implementations not supports chaining + var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; + // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false + var THROWS_ON_PRIMITIVES = _fails(function () { instance.has(1); }); + // most early implementations doesn't supports iterables, most modern - not close it correctly + var ACCEPT_ITERABLES = _iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new + // for early implementations -0 and +0 not the same + var BUGGY_ZERO = !IS_WEAK && _fails(function () { + // V8 ~ Chromium 42- fails only with 5+ elements + var $instance = new C(); + var index = 5; + while (index--) $instance[ADDER](index, index); + return !$instance.has(-0); + }); + if (!ACCEPT_ITERABLES) { + C = wrapper(function (target, iterable) { + _anInstance(target, C, NAME); + var that = _inheritIfRequired(new Base(), target, C); + if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); + return that; + }); + C.prototype = proto; + proto.constructor = C; + } + if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { + fixMethod('delete'); + fixMethod('has'); + IS_MAP && fixMethod('get'); + } + if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); + // weak collections should not contains .clear method + if (IS_WEAK && proto.clear) delete proto.clear; + } + + _setToStringTag(C, NAME); + + O[NAME] = C; + _export(_export.G + _export.W + _export.F * (C != Base), O); + + if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP); + + return C; +}; + +var es6_weakMap = createCommonjsModule(function (module) { +var each = _arrayMethods(0); + + + + + + + +var WEAK_MAP = 'WeakMap'; +var getWeak = _meta.getWeak; +var isExtensible = Object.isExtensible; +var uncaughtFrozenStore = _collectionWeak.ufstore; +var tmp = {}; +var InternalMap; + +var wrapper = function (get) { + return function WeakMap() { + return get(this, arguments.length > 0 ? arguments[0] : undefined); + }; +}; + +var methods = { + // 23.3.3.3 WeakMap.prototype.get(key) + get: function get(key) { + if (_isObject(key)) { + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key); + return data ? data[this._i] : undefined; + } + }, + // 23.3.3.5 WeakMap.prototype.set(key, value) + set: function set(key, value) { + return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value); + } +}; + +// 23.3 WeakMap Objects +var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true); + +// IE11 WeakMap frozen keys fix +if (_fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { + InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP); + _objectAssign(InternalMap.prototype, methods); + _meta.NEED = true; + each(['delete', 'has', 'get', 'set'], function (key) { + var proto = $WeakMap.prototype; + var method = proto[key]; + _redefine(proto, key, function (a, b) { + // store frozen objects on internal weakmap shim + if (_isObject(a) && !isExtensible(a)) { + if (!this._f) this._f = new InternalMap(); + var result = this._f[key](a, b); + return key == 'set' ? this : result; + // store all the rest on native weakmap + } return method.call(this, a, b); + }); + }); +} +}); + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); +} + +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); +} + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); +} + +function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); +} + +var _strictMethod = function (method, arg) { + return !!method && _fails(function () { + // eslint-disable-next-line no-useless-call + arg ? method.call(null, function () { /* empty */ }, 1) : method.call(null); + }); +}; + +var $sort = [].sort; +var test = [1, 2, 3]; + +_export(_export.P + _export.F * (_fails(function () { + // IE8- + test.sort(undefined); +}) || !_fails(function () { + // V8 bug + test.sort(null); + // Old WebKit +}) || !_strictMethod($sort)), 'Array', { + // 22.1.3.25 Array.prototype.sort(comparefn) + sort: function sort(comparefn) { + return comparefn === undefined + ? $sort.call(_toObject(this)) + : $sort.call(_toObject(this), _aFunction(comparefn)); + } +}); + +// 19.1.3.1 Object.assign(target, source) + + +_export(_export.S + _export.F, 'Object', { assign: _objectAssign }); + +// 7.3.20 SpeciesConstructor(O, defaultConstructor) + + +var SPECIES$2 = _wks('species'); +var _speciesConstructor = function (O, D) { + var C = _anObject(O).constructor; + var S; + return C === undefined || (S = _anObject(C)[SPECIES$2]) == undefined ? D : _aFunction(S); +}; + +var at = _stringAt(true); + + // `AdvanceStringIndex` abstract operation +// https://tc39.github.io/ecma262/#sec-advancestringindex +var _advanceStringIndex = function (S, index, unicode) { + return index + (unicode ? at(S, index).length : 1); +}; + +var $min = Math.min; +var $push = [].push; +var $SPLIT = 'split'; +var LENGTH = 'length'; +var LAST_INDEX$1 = 'lastIndex'; +var MAX_UINT32 = 0xffffffff; + +// babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError +var SUPPORTS_Y = !_fails(function () { }); + +// @@split logic +_fixReWks('split', 2, function (defined, SPLIT, $split, maybeCallNative) { + var internalSplit; + if ( + 'abbc'[$SPLIT](/(b)*/)[1] == 'c' || + 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || + 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 || + '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 || + '.'[$SPLIT](/()()/)[LENGTH] > 1 || + ''[$SPLIT](/.?/)[LENGTH] + ) { + // based on es5-shim implementation, need to rework it + internalSplit = function (separator, limit) { + var string = String(this); + if (separator === undefined && limit === 0) return []; + // If `separator` is not a regex, use native split + if (!_isRegexp(separator)) return $split.call(string, separator, limit); + var output = []; + var flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.unicode ? 'u' : '') + + (separator.sticky ? 'y' : ''); + var lastLastIndex = 0; + var splitLimit = limit === undefined ? MAX_UINT32 : limit >>> 0; + // Make `global` and avoid `lastIndex` issues by working with a copy + var separatorCopy = new RegExp(separator.source, flags + 'g'); + var match, lastIndex, lastLength; + while (match = _regexpExec.call(separatorCopy, string)) { + lastIndex = separatorCopy[LAST_INDEX$1]; + if (lastIndex > lastLastIndex) { + output.push(string.slice(lastLastIndex, match.index)); + if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1)); + lastLength = match[0][LENGTH]; + lastLastIndex = lastIndex; + if (output[LENGTH] >= splitLimit) break; + } + if (separatorCopy[LAST_INDEX$1] === match.index) separatorCopy[LAST_INDEX$1]++; // Avoid an infinite loop + } + if (lastLastIndex === string[LENGTH]) { + if (lastLength || !separatorCopy.test('')) output.push(''); + } else output.push(string.slice(lastLastIndex)); + return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output; + }; + // Chakra, V8 + } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) { + internalSplit = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit); + }; + } else { + internalSplit = $split; + } + + return [ + // `String.prototype.split` method + // https://tc39.github.io/ecma262/#sec-string.prototype.split + function split(separator, limit) { + var O = defined(this); + var splitter = separator == undefined ? undefined : separator[SPLIT]; + return splitter !== undefined + ? splitter.call(separator, O, limit) + : internalSplit.call(String(O), separator, limit); + }, + // `RegExp.prototype[@@split]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split + // + // NOTE: This cannot be properly polyfilled in engines that don't support + // the 'y' flag. + function (regexp, limit) { + var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split); + if (res.done) return res.value; + + var rx = _anObject(regexp); + var S = String(this); + var C = _speciesConstructor(rx, RegExp); + + var unicodeMatching = rx.unicode; + var flags = (rx.ignoreCase ? 'i' : '') + + (rx.multiline ? 'm' : '') + + (rx.unicode ? 'u' : '') + + (SUPPORTS_Y ? 'y' : 'g'); + + // ^(? + rx + ) is needed, in combination with some S slicing, to + // simulate the 'y' flag. + var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (S.length === 0) return _regexpExecAbstract(splitter, S) === null ? [S] : []; + var p = 0; + var q = 0; + var A = []; + while (q < S.length) { + splitter.lastIndex = SUPPORTS_Y ? q : 0; + var z = _regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q)); + var e; + if ( + z === null || + (e = $min(_toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p + ) { + q = _advanceStringIndex(S, q, unicodeMatching); + } else { + A.push(S.slice(p, q)); + if (A.length === lim) return A; + for (var i = 1; i <= z.length - 1; i++) { + A.push(z[i]); + if (A.length === lim) return A; + } + q = p = e; + } + } + A.push(S.slice(p)); + return A; + } + ]; +}); + +var isEnum = _objectPie.f; +var _objectToArray = function (isEntries) { + return function (it) { + var O = _toIobject(it); + var keys = _objectKeys(O); + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) if (isEnum.call(O, key = keys[i++])) { + result.push(isEntries ? [key, O[key]] : O[key]); + } return result; + }; +}; + +// https://github.com/tc39/proposal-object-values-entries + +var $entries = _objectToArray(true); + +_export(_export.S, 'Object', { + entries: function entries(it) { + return $entries(it); + } +}); + +// https://github.com/tc39/proposal-object-values-entries + +var $values = _objectToArray(false); + +_export(_export.S, 'Object', { + values: function values(it) { + return $values(it); + } +}); + +var max$1 = Math.max; +var min$2 = Math.min; +var floor$1 = Math.floor; +var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g; +var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g; + +var maybeToString = function (it) { + return it === undefined ? it : String(it); +}; + +// @@replace logic +_fixReWks('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) { + return [ + // `String.prototype.replace` method + // https://tc39.github.io/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = defined(this); + var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; + return fn !== undefined + ? fn.call(searchValue, O, replaceValue) + : $replace.call(String(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace + function (regexp, replaceValue) { + var res = maybeCallNative($replace, regexp, this, replaceValue); + if (res.done) return res.value; + + var rx = _anObject(regexp); + var S = String(this); + var functionalReplace = typeof replaceValue === 'function'; + if (!functionalReplace) replaceValue = String(replaceValue); + var global = rx.global; + if (global) { + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + var results = []; + while (true) { + var result = _regexpExecAbstract(rx, S); + if (result === null) break; + results.push(result); + if (!global) break; + var matchStr = String(result[0]); + if (matchStr === '') rx.lastIndex = _advanceStringIndex(S, _toLength(rx.lastIndex), fullUnicode); + } + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + var matched = String(result[0]); + var position = max$1(min$2(_toInteger(result.index), S.length), 0); + var captures = []; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = [matched].concat(captures, position, S); + if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); + var replacement = String(replaceValue.apply(undefined, replacerArgs)); + } else { + replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += S.slice(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + return accumulatedResult + S.slice(nextSourcePosition); + } + ]; + + // https://tc39.github.io/ecma262/#sec-getsubstitution + function getSubstitution(matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = _toObject(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return $replace.call(replacement, symbols, function (match, ch) { + var capture; + switch (ch.charAt(0)) { + case '$': return '$'; + case '&': return matched; + case '`': return str.slice(0, position); + case "'": return str.slice(tailPos); + case '<': + capture = namedCaptures[ch.slice(1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return match; + if (n > m) { + var f = floor$1(n / 10); + if (f === 0) return match; + if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); + return match; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + } +}); + +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +var _invoke = function (fn, args, that) { + var un = that === undefined; + switch (args.length) { + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; + +var process = _global.process; +var setTask = _global.setImmediate; +var clearTask = _global.clearImmediate; +var MessageChannel = _global.MessageChannel; +var Dispatch = _global.Dispatch; +var counter = 0; +var queue = {}; +var ONREADYSTATECHANGE = 'onreadystatechange'; +var defer, channel, port; +var run = function () { + var id = +this; + // eslint-disable-next-line no-prototype-builtins + if (queue.hasOwnProperty(id)) { + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function (event) { + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if (!setTask || !clearTask) { + setTask = function setImmediate(fn) { + var args = []; + var i = 1; + while (arguments.length > i) args.push(arguments[i++]); + queue[++counter] = function () { + // eslint-disable-next-line no-new-func + _invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id) { + delete queue[id]; + }; + // Node.js 0.8- + if (_cof(process) == 'process') { + defer = function (id) { + process.nextTick(_ctx(run, id, 1)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(_ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if (MessageChannel) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = listener; + defer = _ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if (_global.addEventListener && typeof postMessage == 'function' && !_global.importScripts) { + defer = function (id) { + _global.postMessage(id + '', '*'); + }; + _global.addEventListener('message', listener, false); + // IE8- + } else if (ONREADYSTATECHANGE in _domCreate('script')) { + defer = function (id) { + _html.appendChild(_domCreate('script'))[ONREADYSTATECHANGE] = function () { + _html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(_ctx(run, id, 1), 0); + }; + } +} +var _task = { + set: setTask, + clear: clearTask +}; + +var macrotask = _task.set; +var Observer = _global.MutationObserver || _global.WebKitMutationObserver; +var process$1 = _global.process; +var Promise$1 = _global.Promise; +var isNode = _cof(process$1) == 'process'; + +var _microtask = function () { + var head, last, notify; + + var flush = function () { + var parent, fn; + if (isNode && (parent = process$1.domain)) parent.exit(); + while (head) { + fn = head.fn; + head = head.next; + try { + fn(); + } catch (e) { + if (head) notify(); + else last = undefined; + throw e; + } + } last = undefined; + if (parent) parent.enter(); + }; + + // Node.js + if (isNode) { + notify = function () { + process$1.nextTick(flush); + }; + // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 + } else if (Observer && !(_global.navigator && _global.navigator.standalone)) { + var toggle = true; + var node = document.createTextNode(''); + new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new + notify = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (Promise$1 && Promise$1.resolve) { + // Promise.resolve without an argument throws an error in LG WebOS 2 + var promise = Promise$1.resolve(undefined); + notify = function () { + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function () { + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(_global, flush); + }; + } + + return function (fn) { + var task = { fn: fn, next: undefined }; + if (last) last.next = task; + if (!head) { + head = task; + notify(); + } last = task; + }; +}; + +// 25.4.1.5 NewPromiseCapability(C) + + +function PromiseCapability(C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = _aFunction(resolve); + this.reject = _aFunction(reject); +} + +var f$5 = function (C) { + return new PromiseCapability(C); +}; + +var _newPromiseCapability = { + f: f$5 +}; + +var _perform = function (exec) { + try { + return { e: false, v: exec() }; + } catch (e) { + return { e: true, v: e }; + } +}; + +var navigator$1 = _global.navigator; + +var _userAgent = navigator$1 && navigator$1.userAgent || ''; + +var _promiseResolve = function (C, x) { + _anObject(C); + if (_isObject(x) && x.constructor === C) return x; + var promiseCapability = _newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; +}; + +var SPECIES$3 = _wks('species'); + +var _setSpecies = function (KEY) { + var C = _global[KEY]; + if (_descriptors && C && !C[SPECIES$3]) _objectDp.f(C, SPECIES$3, { + configurable: true, + get: function () { return this; } + }); +}; + +var task = _task.set; +var microtask = _microtask(); + + + + +var PROMISE = 'Promise'; +var TypeError$1 = _global.TypeError; +var process$2 = _global.process; +var versions = process$2 && process$2.versions; +var v8 = versions && versions.v8 || ''; +var $Promise = _global[PROMISE]; +var isNode$1 = _classof(process$2) == 'process'; +var empty = function () { /* empty */ }; +var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; +var newPromiseCapability = newGenericPromiseCapability = _newPromiseCapability.f; + +var USE_NATIVE = !!function () { + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1); + var FakePromise = (promise.constructor = {})[_wks('species')] = function (exec) { + exec(empty, empty); + }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode$1 || typeof PromiseRejectionEvent == 'function') + && promise.then(empty) instanceof FakePromise + // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables + // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 + // we can't detect it synchronously, so just check versions + && v8.indexOf('6.6') !== 0 + && _userAgent.indexOf('Chrome/66') === -1; + } catch (e) { /* empty */ } +}(); + +// helpers +var isThenable = function (it) { + var then; + return _isObject(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var notify = function (promise, isReject) { + if (promise._n) return; + promise._n = true; + var chain = promise._c; + microtask(function () { + var value = promise._v; + var ok = promise._s == 1; + var i = 0; + var run = function (reaction) { + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then, exited; + try { + if (handler) { + if (!ok) { + if (promise._h == 2) onHandleUnhandled(promise); + promise._h = 1; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); // may throw + if (domain) { + domain.exit(); + exited = true; + } + } + if (result === reaction.promise) { + reject(TypeError$1('Promise-chain cycle')); + } else if (then = isThenable(result)) { + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (e) { + if (domain && !exited) domain.exit(); + reject(e); + } + }; + while (chain.length > i) run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if (isReject && !promise._h) onUnhandled(promise); + }); +}; +var onUnhandled = function (promise) { + task.call(_global, function () { + var value = promise._v; + var unhandled = isUnhandled(promise); + var result, handler, console; + if (unhandled) { + result = _perform(function () { + if (isNode$1) { + process$2.emit('unhandledRejection', value, promise); + } else if (handler = _global.onunhandledrejection) { + handler({ promise: promise, reason: value }); + } else if ((console = _global.console) && console.error) { + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode$1 || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if (unhandled && result.e) throw result.v; + }); +}; +var isUnhandled = function (promise) { + return promise._h !== 1 && (promise._a || promise._c).length === 0; +}; +var onHandleUnhandled = function (promise) { + task.call(_global, function () { + var handler; + if (isNode$1) { + process$2.emit('rejectionHandled', promise); + } else if (handler = _global.onrejectionhandled) { + handler({ promise: promise, reason: promise._v }); + } + }); +}; +var $reject = function (value) { + var promise = this; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if (!promise._a) promise._a = promise._c.slice(); + notify(promise, true); +}; +var $resolve = function (value) { + var promise = this; + var then; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if (promise === value) throw TypeError$1("Promise can't be resolved itself"); + if (then = isThenable(value)) { + microtask(function () { + var wrapper = { _w: promise, _d: false }; // wrap + try { + then.call(value, _ctx($resolve, wrapper, 1), _ctx($reject, wrapper, 1)); + } catch (e) { + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch (e) { + $reject.call({ _w: promise, _d: false }, e); // wrap + } +}; + +// constructor polyfill +if (!USE_NATIVE) { + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor) { + _anInstance(this, $Promise, PROMISE, '_h'); + _aFunction(executor); + Internal.call(this); + try { + executor(_ctx($resolve, this, 1), _ctx($reject, this, 1)); + } catch (err) { + $reject.call(this, err); + } + }; + // eslint-disable-next-line no-unused-vars + Internal = function Promise(executor) { + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = _redefineAll($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected) { + var reaction = newPromiseCapability(_speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode$1 ? process$2.domain : undefined; + this._c.push(reaction); + if (this._a) this._a.push(reaction); + if (this._s) notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + OwnPromiseCapability = function () { + var promise = new Internal(); + this.promise = promise; + this.resolve = _ctx($resolve, promise, 1); + this.reject = _ctx($reject, promise, 1); + }; + _newPromiseCapability.f = newPromiseCapability = function (C) { + return C === $Promise || C === Wrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; +} + +_export(_export.G + _export.W + _export.F * !USE_NATIVE, { Promise: $Promise }); +_setToStringTag($Promise, PROMISE); +_setSpecies(PROMISE); +Wrapper = _core[PROMISE]; + +// statics +_export(_export.S + _export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r) { + var capability = newPromiseCapability(this); + var $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +_export(_export.S + _export.F * (_library || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x) { + return _promiseResolve(_library && this === Wrapper ? $Promise : this, x); + } +}); +_export(_export.S + _export.F * !(USE_NATIVE && _iterDetect(function (iter) { + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = _perform(function () { + var values = []; + var index = 0; + var remaining = 1; + _forOf(iterable, false, function (promise) { + var $index = index++; + var alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.e) reject(result.v); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var reject = capability.reject; + var result = _perform(function () { + _forOf(iterable, false, function (promise) { + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if (result.e) reject(result.v); + return capability.promise; + } +}); + +var STARTS_WITH = 'startsWith'; +var $startsWith = ''[STARTS_WITH]; + +_export(_export.P + _export.F * _failsIsRegexp(STARTS_WITH), 'String', { + startsWith: function startsWith(searchString /* , position = 0 */) { + var that = _stringContext(this, searchString, STARTS_WITH); + var index = _toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length)); + var search = String(searchString); + return $startsWith + ? $startsWith.call(that, search, index) + : that.slice(index, index + search.length) === search; + } +}); + +// 20.1.2.4 Number.isNaN(number) + + +_export(_export.S, 'Number', { + isNaN: function isNaN(number) { + // eslint-disable-next-line no-self-compare + return number != number; + } +}); + +// ========================================================================== +// Type checking utils +// ========================================================================== +var getConstructor = function getConstructor(input) { + return input !== null && typeof input !== 'undefined' ? input.constructor : null; +}; + +var instanceOf = function instanceOf(input, constructor) { + return Boolean(input && constructor && input instanceof constructor); +}; + +var isNullOrUndefined = function isNullOrUndefined(input) { + return input === null || typeof input === 'undefined'; +}; + +var isObject = function isObject(input) { + return getConstructor(input) === Object; +}; + +var isNumber = function isNumber(input) { + return getConstructor(input) === Number && !Number.isNaN(input); +}; + +var isString = function isString(input) { + return getConstructor(input) === String; +}; + +var isBoolean = function isBoolean(input) { + return getConstructor(input) === Boolean; +}; + +var isFunction = function isFunction(input) { + return getConstructor(input) === Function; +}; + +var isArray = function isArray(input) { + return Array.isArray(input); +}; + +var isWeakMap = function isWeakMap(input) { + return instanceOf(input, WeakMap); +}; + +var isNodeList = function isNodeList(input) { + return instanceOf(input, NodeList); +}; + +var isElement = function isElement(input) { + return instanceOf(input, Element); +}; + +var isTextNode = function isTextNode(input) { + return getConstructor(input) === Text; +}; + +var isEvent = function isEvent(input) { + return instanceOf(input, Event); +}; + +var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); +}; + +var isCue = function isCue(input) { + return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); +}; + +var isTrack = function isTrack(input) { + return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind); +}; + +var isEmpty = function isEmpty(input) { + return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length; +}; + +var isUrl = function isUrl(input) { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } // Must be string from here + + + if (!isString(input)) { + return false; + } // Add the protocol if required + + + var string = input; + + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = "http://".concat(input); + } + + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } +}; + +var is$1 = { + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty +}; + +// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md +// https://www.youtube.com/watch?v=NPM6172J22g + +var supportsPassiveListeners = function () { + // Test via a getter in the options object to see if the passive property is accessed + var supported = false; + + try { + var options = Object.defineProperty({}, 'passive', { + get: function get() { + supported = true; + return null; + } + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) {// Do nothing + } + + return supported; +}(); // Toggle event listener + + +function toggleListener(element, event, callback) { + var _this = this; + + var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is$1.empty(event) || !is$1.function(callback)) { + return; + } // Allow multiple events + + + var events = event.split(' '); // Build options + // Default to just the capture boolean for browsers with no passive listener support + + var options = capture; // If passive events listeners are supported + + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive: passive, + // Whether the listener is a capturing listener or not + capture: capture + }; + } // If a single node is passed, bind the event listener + + + events.forEach(function (type) { + if (_this && _this.eventListeners && toggle) { + // Cache event listener + _this.eventListeners.push({ + element: element, + type: type, + callback: callback, + options: options + }); + } + + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); +} // Bind event handler + +function on(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, true, passive, capture); +} // Unbind event handler + +function off(element) { + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + toggleListener.call(this, element, events, callback, false, passive, capture); +} // Bind once-only event handler + +function once(element) { + var _this2 = this; + + var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var callback = arguments.length > 2 ? arguments[2] : undefined; + var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + var onceCallback = function onceCallback() { + off(element, events, onceCallback, passive, capture); + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + callback.apply(_this2, args); + }; + + toggleListener.call(this, element, events, onceCallback, true, passive, capture); +} // Trigger event + +function triggerEvent(element) { + var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + // Bail if no element + if (!is$1.element(element) || is$1.empty(type)) { + return; + } // Create and dispatch the event + + + var event = new CustomEvent(type, { + bubbles: bubbles, + detail: Object.assign({}, detail, { + plyr: this + }) + }); // Dispatch the event + + element.dispatchEvent(event); +} // Unbind all cached event listeners + +function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(function (item) { + var element = item.element, + type = item.type, + callback = item.callback, + options = item.options; + element.removeEventListener(type, callback, options); + }); + this.eventListeners = []; + } +} // Run method when / if player is ready + +function ready() { + var _this3 = this; + + return new Promise(function (resolve) { + return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve); + }).then(function () {}); +} + +function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + + Array.from(targets).reverse().forEach(function (element, index) { + var child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling. + + var parent = element.parentNode; + var sibling = element.nextSibling; // Wrap the element (is automatically removed from its current + // parent). + + child.appendChild(element); // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); +} // Set attributes + +function setAttributes(element, attributes) { + if (!is$1.element(element) || is$1.empty(attributes)) { + return; + } // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" + + + Object.entries(attributes).filter(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + value = _ref2[1]; + + return !is$1.nullOrUndefined(value); + }).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + + return element.setAttribute(key, value); + }); +} // Create a DocumentFragment + +function createElement(type, attributes, text) { + // Create a new <element> + var element = document.createElement(type); // Set all passed attributes + + if (is$1.object(attributes)) { + setAttributes(element, attributes); + } // Add text node + + + if (is$1.string(text)) { + element.innerText = text; + } // Return built element + + + return element; +} // Inaert an element after another + +function insertAfter(element, target) { + if (!is$1.element(element) || !is$1.element(target)) { + return; + } + + target.parentNode.insertBefore(element, target.nextSibling); +} // Insert a DocumentFragment + +function insertElement(type, parent, attributes, text) { + if (!is$1.element(parent)) { + return; + } + + parent.appendChild(createElement(type, attributes, text)); +} // Remove element(s) + +function removeElement(element) { + if (is$1.nodeList(element) || is$1.array(element)) { + Array.from(element).forEach(removeElement); + return; + } + + if (!is$1.element(element) || !is$1.element(element.parentNode)) { + return; + } + + element.parentNode.removeChild(element); +} // Remove all child elements + +function emptyElement(element) { + if (!is$1.element(element)) { + return; + } + + var length = element.childNodes.length; + + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } +} // Replace element + +function replaceElement(newChild, oldChild) { + if (!is$1.element(oldChild) || !is$1.element(oldChild.parentNode) || !is$1.element(newChild)) { + return null; + } + + oldChild.parentNode.replaceChild(newChild, oldChild); + return newChild; +} // Get an attribute object from a string selector + +function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + if (!is$1.string(sel) || is$1.empty(sel)) { + return {}; + } + + var attributes = {}; + var existing = existingAttributes; + sel.split(',').forEach(function (s) { + // Remove whitespace + var selector = s.trim(); + var className = selector.replace('.', ''); + var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value + + var parts = stripped.split('='); + var key = parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character + + var start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is$1.object(existing) && is$1.string(existing.class)) { + existing.class += " ".concat(className); + } + + attributes.class = className; + break; + + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + + case '[': + // Attribute selector + attributes[key] = value; + break; + + default: + break; + } + }); + return attributes; +} // Toggle hidden + +function toggleHidden(element, hidden) { + if (!is$1.element(element)) { + return; + } + + var hide = hidden; + + if (!is$1.boolean(hide)) { + hide = !element.hidden; + } + + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } +} // Mirror Element.classList.toggle, with IE compatibility for "force" argument + +function toggleClass(element, className, force) { + if (is$1.nodeList(element)) { + return Array.from(element).map(function (e) { + return toggleClass(e, className, force); + }); + } + + if (is$1.element(element)) { + var method = 'toggle'; + + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } + + element.classList[method](className); + return element.classList.contains(className); + } + + return false; +} // Has class name + +function hasClass(element, className) { + return is$1.element(element) && element.classList.contains(className); +} // Element matches selector + +function matches(element, selector) { + + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } + + var matches = match; + return matches.call(element, selector); +} // Find all elements + +function getElements(selector) { + return this.elements.container.querySelectorAll(selector); +} // Find a single element + +function getElement(selector) { + return this.elements.container.querySelector(selector); +} // Trap focus inside container + +function trapFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is$1.element(element)) { + return; + } + + var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + var first = focusable[0]; + var last = focusable[focusable.length - 1]; + + var trap = function trap(event) { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } // Get the current focused element + + + var focused = document.activeElement; + + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); +} // Set focus and tab focus class + +function setFocus() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!is$1.element(element)) { + return; + } // Set regular focus + + + element.focus({ + preventScroll: true + }); // If we want to mimic keyboard focus via tab + + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } +} + +var transitionEndEvent = function () { + var element = document.createElement('span'); + var events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + }; + var type = Object.keys(events).find(function (event) { + return element.style[event] !== undefined; + }); + return is$1.string(type) ? events[type] : false; +}(); // Force repaint of element + +function repaint(element) { + setTimeout(function () { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line + + toggleHidden(element, false); + } catch (e) {// Do nothing + } + }, 0); +} + +// ========================================================================== +// Browser sniffing +// Unfortunately, due to mixed support, UA sniffing is required +// ========================================================================== +var browser = { + isIE: + /* @cc_on!@ */ + !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform) +}; + +var defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora' +}; // Check for feature support + +var support = { + // Basic support + audio: 'canPlayType' in document.createElement('audio'), + video: 'canPlayType' in document.createElement('video'), + // Check for support + // Basic functionality vs full UI + check: function check(type, provider, playsinline) { + var canPlayInline = browser.isIPhone && playsinline && support.playsinline; + var api = support[type] || provider !== 'html5'; + var ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); + return { + api: api, + ui: ui + }; + }, + // Picture-in-picture support + // Safari & Chrome only currently + pip: function () { + if (browser.isIPhone) { + return false; + } // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls + + + if (is$1.function(createElement('video').webkitSetPresentationMode)) { + return true; + } // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture + + + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } + + return false; + }(), + // Airplay support + // Safari only currently + airplay: is$1.function(window.WebKitPlaybackTargetAvailabilityEvent), + // Inline playback support + // https://webkit.org/blog/6784/new-video-policies-for-ios/ + playsinline: 'playsInline' in document.createElement('video'), + // Check for mime type support against a player instance + // Credits: http://diveintohtml5.info/everything.html + // Related: http://www.leanbackplayer.com/test/h5mt.html + mime: function mime(input) { + if (is$1.empty(input)) { + return false; + } + + var _input$split = input.split('/'), + _input$split2 = _slicedToArray(_input$split, 1), + mediaType = _input$split2[0]; + + var type = input; // Verify we're using HTML5 and there's no media type mismatch + + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } // Add codec if required + + + if (Object.keys(defaultCodecs).includes(type)) { + type += "; codecs=\"".concat(defaultCodecs[input], "\""); + } + + try { + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); + } catch (e) { + return false; + } + }, + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), + // <input type="range"> Sliders + rangeInput: function () { + var range = document.createElement('input'); + range.type = 'range'; + return range.type === 'range'; + }(), + // Touch + // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event + touch: 'ontouchstart' in document.documentElement, + // Detect transitions support + transitions: transitionEndEvent !== false, + // Reduced motion iOS & MacOS setting + // https://webkit.org/blog/7551/responsive-design-for-motion/ + reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches +}; + +var html5 = { + getSources: function getSources() { + var _this = this; + + if (!this.isHTML5) { + return []; + } + + var sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified) + + return sources.filter(function (source) { + var type = source.getAttribute('type'); + + if (is$1.empty(type)) { + return true; + } + + return support.mime.call(_this, type); + }); + }, + // Get quality levels + getQualityOptions: function getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources.call(this).map(function (source) { + return Number(source.getAttribute('size')); + }).filter(Boolean); + }, + extend: function extend() { + if (!this.isHTML5) { + return; + } + + var player = this; // Quality + + Object.defineProperty(player.media, 'quality', { + get: function get() { + // Get sources + var sources = html5.getSources.call(player); + var source = sources.find(function (source) { + return source.getAttribute('src') === player.source; + }); // Return size, if match is found + + return source && Number(source.getAttribute('size')); + }, + set: function set(input) { + // Get sources + var sources = html5.getSources.call(player); // Get first match for requested size + + var source = sources.find(function (source) { + return Number(source.getAttribute('size')) === input; + }); // No matching source found + + if (!source) { + return; + } // Get current state + + + var _player$media = player.media, + currentTime = _player$media.currentTime, + paused = _player$media.paused, + preload = _player$media.preload, + readyState = _player$media.readyState; // Set new source + + player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044) + + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', function () { + player.currentTime = currentTime; // Resume playing + + if (!paused) { + player.play(); + } + }); // Load new source + + player.media.load(); + } // Trigger change event + + + triggerEvent.call(player, player.media, 'qualitychange', false, { + quality: input + }); + } + }); + }, + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests: function cancelRequests() { + if (!this.isHTML5) { + return; + } // Remove child sources + + + removeElement(html5.getSources.call(this)); // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + + this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + + this.media.load(); // Debugging + + this.debug.log('Cancelled network requests'); + } +}; + +// ========================================================================== + +function dedupe(array) { + if (!is$1.array(array)) { + return array; + } + + return array.filter(function (item, index) { + return array.indexOf(item) === index; + }); +} // Get the closest value in an array + +function closest(array, value) { + if (!is$1.array(array) || !array.length) { + return null; + } + + return array.reduce(function (prev, curr) { + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); +} + +function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); +} // Get a nested value in an object + +function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); +} // Deep extend destination object with N more objects + +function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + if (!sources.length) { + return target; + } + + var source = sources.shift(); + + if (!is$1.object(source)) { + return target; + } + + Object.keys(source).forEach(function (key) { + if (is$1.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); + } + + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); + } + }); + return extend.apply(void 0, [target].concat(sources)); +} + +var dP$2 = _objectDp.f; +var gOPN$1 = _objectGopn.f; + + +var $RegExp = _global.RegExp; +var Base$1 = $RegExp; +var proto$2 = $RegExp.prototype; +var re1 = /a/g; +var re2 = /a/g; +// "new" creates a new object, old webkit buggy here +var CORRECT_NEW = new $RegExp(re1) !== re1; + +if (_descriptors && (!CORRECT_NEW || _fails(function () { + re2[_wks('match')] = false; + // RegExp constructor can alter flags and IsRegExp works correct with @@match + return $RegExp(re1) != re1 || $RegExp(re2) == re2 || $RegExp(re1, 'i') != '/a/i'; +}))) { + $RegExp = function RegExp(p, f) { + var tiRE = this instanceof $RegExp; + var piRE = _isRegexp(p); + var fiU = f === undefined; + return !tiRE && piRE && p.constructor === $RegExp && fiU ? p + : _inheritIfRequired(CORRECT_NEW + ? new Base$1(piRE && !fiU ? p.source : p, f) + : Base$1((piRE = p instanceof $RegExp) ? p.source : p, piRE && fiU ? _flags.call(p) : f) + , tiRE ? this : proto$2, $RegExp); + }; + var proxy = function (key) { + key in $RegExp || dP$2($RegExp, key, { + configurable: true, + get: function () { return Base$1[key]; }, + set: function (it) { Base$1[key] = it; } + }); + }; + for (var keys$1 = gOPN$1(Base$1), i$1 = 0; keys$1.length > i$1;) proxy(keys$1[i$1++]); + proto$2.constructor = $RegExp; + $RegExp.prototype = proto$2; + _redefine(_global, 'RegExp', $RegExp); +} + +_setSpecies('RegExp'); + +function generateId(prefix) { + return "".concat(prefix, "-").concat(Math.floor(Math.random() * 10000)); +} // Format string + +function format(input) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (is$1.empty(input)) { + return input; + } + + return input.toString().replace(/{(\d+)}/g, function (match, i) { + return args[i].toString(); + }); +} // Get percentage + +function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } + + return (current / max * 100).toFixed(2); +} // Replace all occurances of a string in a string + +function replaceAll() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); +} // Convert to title case + +function toTitleCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + return input.toString().replace(/\w\S*/g, function (text) { + return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); + }); +} // Convert string to pascalCase + +function toPascalCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert kebab case + + string = replaceAll(string, '-', ' '); // Convert snake case + + string = replaceAll(string, '_', ' '); // Convert to title case + + string = toTitleCase(string); // Convert to pascal case + + return replaceAll(string, ' ', ''); +} // Convert string to pascalCase + +function toCamelCase() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var string = input.toString(); // Convert to pascal case + + string = toPascalCase(string); // Convert first character to lowercase + + return string.charAt(0).toLowerCase() + string.slice(1); +} // Remove HTML from a string + +function stripHTML(source) { + var fragment = document.createDocumentFragment(); + var element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; +} // Like outerHTML, but also works for DocumentFragment + +function getHTML(element) { + var wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; +} + +var resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube' +}; +var i18n = { + get: function get() { + var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (is$1.empty(key) || is$1.empty(config)) { + return ''; + } + + var string = getDeep(config.i18n, key); + + if (is$1.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; + } + + return ''; + } + + var replace = { + '{seektime}': config.seekTime, + '{title}': config.title + }; + Object.entries(replace).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + string = replaceAll(string, key, value); + }); + return string; + } +}; + +var Storage = +/*#__PURE__*/ +function () { + function Storage(player) { + _classCallCheck(this, Storage); + + this.enabled = player.config.storage.enabled; + this.key = player.config.storage.key; + } // Check for actual support (see if we can use it) + + + _createClass(Storage, [{ + key: "get", + value: function get(key) { + if (!Storage.supported || !this.enabled) { + return null; + } + + var store = window.localStorage.getItem(this.key); + + if (is$1.empty(store)) { + return null; + } + + var json = JSON.parse(store); + return is$1.string(key) && key.length ? json[key] : json; + } + }, { + key: "set", + value: function set(object) { + // Bail if we don't have localStorage support or it's disabled + if (!Storage.supported || !this.enabled) { + return; + } // Can only store objectst + + + if (!is$1.object(object)) { + return; + } // Get current storage + + + var storage = this.get(); // Default to empty object + + if (is$1.empty(storage)) { + storage = {}; + } // Update the working copy of the values + + + extend(storage, object); // Update storage + + window.localStorage.setItem(this.key, JSON.stringify(storage)); + } + }], [{ + key: "supported", + get: function get() { + try { + if (!('localStorage' in window)) { + return false; + } + + var test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode) + // see: https://github.com/sampotts/plyr/issues/131 + + window.localStorage.setItem(test, test); + window.localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + } + }]); + + return Storage; +}(); + +// ========================================================================== +// Fetch wrapper +// Using XHR to avoid issues with older browsers +// ========================================================================== +function fetch(url) { + var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text'; + return new Promise(function (resolve, reject) { + try { + var request = new XMLHttpRequest(); // Check for CORS support + + if (!('withCredentials' in request)) { + return; + } + + request.addEventListener('load', function () { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); + request.addEventListener('error', function () { + throw new Error(request.status); + }); + request.open('GET', url, true); // Set the required response type + + request.responseType = responseType; + request.send(); + } catch (e) { + reject(e); + } + }); +} + +// ========================================================================== + +function loadSprite(url, id) { + if (!is$1.string(url)) { + return; + } + + var prefix = 'cache'; + var hasId = is$1.string(id); + var isCached = false; + + var exists = function exists() { + return document.getElementById(id) !== null; + }; + + var update = function update(container, data) { + container.innerHTML = data; // Check again incase of race condition + + if (hasId && exists()) { + return; + } // Inject the SVG to the body + + + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set + + + if (!hasId || !exists()) { + var useStorage = Storage.supported; // Create container + + var container = document.createElement('div'); + container.setAttribute('hidden', ''); + + if (hasId) { + container.setAttribute('id', id); + } // Check in cache + + + if (useStorage) { + var cached = window.localStorage.getItem("".concat(prefix, "-").concat(id)); + isCached = cached !== null; + + if (isCached) { + var data = JSON.parse(cached); + update(container, data.content); + } + } // Get the sprite + + + fetch(url).then(function (result) { + if (is$1.empty(result)) { + return; + } + + if (useStorage) { + window.localStorage.setItem("".concat(prefix, "-").concat(id), JSON.stringify({ + content: result + })); + } + + update(container, result); + }).catch(function () {}); + } +} + +// 20.2.2.34 Math.trunc(x) + + +_export(_export.S, 'Math', { + trunc: function trunc(it) { + return (it > 0 ? Math.floor : Math.ceil)(it); + } +}); + +var getHours = function getHours(value) { + return Math.trunc(value / 60 / 60 % 60, 10); +}; +var getMinutes = function getMinutes(value) { + return Math.trunc(value / 60 % 60, 10); +}; +var getSeconds = function getSeconds(value) { + return Math.trunc(value % 60, 10); +}; // Format time to UI friendly string + +function formatTime() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var displayHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if the value isn't a number + if (!is$1.number(time)) { + return formatTime(null, displayHours, inverted); + } // Format time component to add leading zero + + + var format = function format(value) { + return "0".concat(value).slice(-2); + }; // Breakdown to hours, mins, secs + + + var hours = getHours(time); + var mins = getMinutes(time); + var secs = getSeconds(time); // Do we need to display hours? + + if (displayHours || hours > 0) { + hours = "".concat(hours, ":"); + } else { + hours = ''; + } // Render + + + return "".concat(inverted && time > 0 ? '-' : '').concat(hours).concat(format(mins), ":").concat(format(secs)); +} + +var controls = { + // Get icon URL + getIconUrl: function getIconUrl() { + var url = new URL(this.config.iconUrl, window.location); + var cors = url.host !== window.location.host || browser.isIE && !window.svg4everybody; + return { + url: this.config.iconUrl, + cors: cors + }; + }, + // Find the UI controls + findElements: function findElements() { + try { + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons + + this.elements.buttons = { + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen) + }; // Progress + + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs + + this.elements.inputs = { + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume) + }; // Display + + this.elements.display = { + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration) + }; // Seek tooltip + + if (is$1.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector(".".concat(this.config.classNames.tooltip)); + } + + return true; + } catch (error) { + // Log it + this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls + + this.toggleNativeControls(true); + return false; + } + }, + // Create <svg> icon + createIcon: function createIcon(type, attributes) { + var namespace = 'http://www.w3.org/2000/svg'; + var iconUrl = controls.getIconUrl.call(this); + var iconPath = "".concat(!iconUrl.cors ? iconUrl.url : '', "#").concat(this.config.iconPrefix); // Create <svg> + + var icon = document.createElementNS(namespace, 'svg'); + setAttributes(icon, extend(attributes, { + role: 'presentation', + focusable: 'false' + })); // Create the <use> to reference sprite + + var use = document.createElementNS(namespace, 'use'); + var path = "".concat(iconPath, "-").concat(type); // Set `href` attributes + // https://github.com/sampotts/plyr/issues/460 + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href + + if ('href' in use) { + use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); + } // Always set the older attribute even though it's "deprecated" (it'll be around for ages) + + + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg> + + icon.appendChild(use); + return icon; + }, + // Create hidden text label + createLabel: function createLabel(key) { + var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var text = i18n.get(key, this.config); + var attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') + }); + return createElement('span', attributes, text); + }, + // Create a badge + createBadge: function createBadge(text) { + if (is$1.empty(text)) { + return null; + } + + var badge = createElement('span', { + class: this.config.classNames.menu.value + }); + badge.appendChild(createElement('span', { + class: this.config.classNames.menu.badge + }, text)); + return badge; + }, + // Create a <button> + createButton: function createButton(buttonType, attr) { + var attributes = Object.assign({}, attr); + var type = toCamelCase(buttonType); + var props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null + }; + ['element', 'icon', 'label'].forEach(function (key) { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); // Default to 'button' type to prevent form submission + + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { + attributes.type = 'button'; + } // Set class name + + + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { + attributes.class += " ".concat(this.config.classNames.control); + } + } else { + attributes.class = this.config.classNames.control; + } // Large play button + + + switch (buttonType) { + case 'play': + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; + break; + + case 'mute': + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; + break; + + case 'captions': + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; + break; + + case 'fullscreen': + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; + break; + + case 'play-large': + attributes.class += " ".concat(this.config.classNames.control, "--overlaid"); + type = 'play'; + props.label = 'play'; + props.icon = 'play'; + break; + + default: + if (is$1.empty(props.label)) { + props.label = type; + } + + if (is$1.empty(props.icon)) { + props.icon = buttonType; + } + + } + + var button = createElement(props.element); // Setup toggle icon and labels + + if (props.toggle) { + // Icon + button.appendChild(controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed' + })); + button.appendChild(controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed' + })); // Label/Tooltip + + button.appendChild(controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed' + })); + button.appendChild(controls.createLabel.call(this, props.label, { + class: 'label--not-pressed' + })); + } else { + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); + } // Merge and set attributes + + + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons + + if (type === 'play') { + if (!is$1.array(this.elements.buttons[type])) { + this.elements.buttons[type] = []; + } + + this.elements.buttons[type].push(button); + } else { + this.elements.buttons[type] = button; + } + + return button; + }, + // Create an <input type='range'> + createRange: function createRange(type, attributes) { + // Seek input + var input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), { + type: 'range', + min: 0, + max: 100, + step: 0.01, + value: 0, + autocomplete: 'off', + // A11y fixes for https://github.com/sampotts/plyr/issues/905 + role: 'slider', + 'aria-label': i18n.get(type, this.config), + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'aria-valuenow': 0 + }, attributes)); + this.elements.inputs[type] = input; // Set the fill for webkit now + + controls.updateRangeFill.call(this, input); + return input; + }, + // Create a <progress> + createProgress: function createProgress(type, attributes) { + var progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), { + min: 0, + max: 100, + value: 0, + role: 'presentation', + 'aria-hidden': true + }, attributes)); // Create the label inside + + if (type !== 'volume') { + progress.appendChild(createElement('span', null, '0')); + var suffixKey = { + played: 'played', + buffer: 'buffered' + }[type]; + var suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; + progress.innerText = "% ".concat(suffix.toLowerCase()); + } + + this.elements.display[type] = progress; + return progress; + }, + // Create time display + createTime: function createTime(type) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + var container = createElement('div', extend(attributes, { + class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-label': i18n.get(type, this.config) + }), '00:00'); // Reference for updates + + this.elements.display[type] = container; + return container; + }, + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { + var _this = this; + + // Navigate through menus via arrow keys and space + on(menuItem, 'keydown keyup', function (event) { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } // Prevent play / seek + + + event.preventDefault(); + event.stopPropagation(); // We're just here to prevent the keydown bubbling + + if (event.type === 'keydown') { + return; + } + + var isRadioButton = matches(menuItem, '[role="menuitemradio"]'); // Show the respective menu + + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(_this, type, true); + } else { + var target; + + if (event.which !== 32) { + if (event.which === 40 || isRadioButton && event.which === 39) { + target = menuItem.nextElementSibling; + + if (!is$1.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; + + if (!is$1.element(target)) { + target = menuItem.parentNode.lastElementChild; + } + } + + setFocus.call(_this, target, true); + } + } + }, false); // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here + + on(menuItem, 'keyup', function (event) { + if (event.which !== 13) { + return; + } + + controls.focusFirstMenuItem.call(_this, null, true); + }); + }, + // Create a settings menu item + createMenuItem: function createMenuItem(_ref) { + var _this2 = this; + + var value = _ref.value, + list = _ref.list, + type = _ref.type, + title = _ref.title, + _ref$badge = _ref.badge, + badge = _ref$badge === void 0 ? null : _ref$badge, + _ref$checked = _ref.checked, + checked = _ref$checked === void 0 ? false : _ref$checked; + var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + var menuItem = createElement('button', extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: "".concat(this.config.classNames.control, " ").concat(attributes.class ? attributes.class : '').trim(), + 'aria-checked': checked, + value: value + })); + var flex = createElement('span'); // We have to set as HTML incase of special characters + + flex.innerHTML = title; + + if (is$1.element(badge)) { + flex.appendChild(badge); + } + + menuItem.appendChild(flex); // Replicate radio button behaviour + + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get: function get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set: function set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children).filter(function (node) { + return matches(node, '[role="menuitemradio"]'); + }).forEach(function (node) { + return node.setAttribute('aria-checked', 'false'); + }); + } + + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + } + }); + this.listeners.bind(menuItem, 'click keyup', function (event) { + if (is$1.keyboardEvent(event) && event.which !== 32) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + menuItem.checked = true; + + switch (type) { + case 'language': + _this2.currentTrack = Number(value); + break; + + case 'quality': + _this2.quality = value; + break; + + case 'speed': + _this2.speed = parseFloat(value); + break; + + default: + break; + } + + controls.showMenuPanel.call(_this2, 'home', is$1.keyboardEvent(event)); + }, type, false); + controls.bindMenuItemShortcuts.call(this, menuItem, type); + list.appendChild(menuItem); + }, + // Format a time for display + formatTime: function formatTime$$1() { + var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + // Bail if the value isn't a number + if (!is$1.number(time)) { + return time; + } // Always display hours if duration is over an hour + + + var forceHours = getHours(this.duration) > 0; + return formatTime(time, forceHours, inverted); + }, + // Update the displayed time + updateTimeDisplay: function updateTimeDisplay() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var inverted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Bail if there's no element to display or the value isn't a number + if (!is$1.element(target) || !is$1.number(time)) { + return; + } // eslint-disable-next-line no-param-reassign + + + target.innerText = controls.formatTime(time, inverted); + }, + // Update volume UI and storage + updateVolume: function updateVolume() { + if (!this.supported.ui) { + return; + } // Update range + + + if (is$1.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } // Update mute state + + + if (is$1.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } + }, + // Update seek value and lower fill + setRange: function setRange(target) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (!is$1.element(target)) { + return; + } // eslint-disable-next-line + + + target.value = value; // Webkit range fill + + controls.updateRangeFill.call(this, target); + }, + // Update <progress> elements + updateProgress: function updateProgress(event) { + var _this3 = this; + + if (!this.supported.ui || !is$1.event(event)) { + return; + } + + var value = 0; + + var setProgress = function setProgress(target, input) { + var value = is$1.number(input) ? input : 0; + var progress = is$1.element(target) ? target : _this3.elements.display.buffer; // Update value and label + + if (is$1.element(progress)) { + progress.value = value; // Update text label inside + + var label = progress.getElementsByTagName('span')[0]; + + if (is$1.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event + + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + // Check buffer status + + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + break; + + default: + break; + } + } + }, + // Webkit polyfill for lower fill range + updateRangeFill: function updateRangeFill(target) { + // Get range from event if event passed + var range = is$1.event(target) ? target.target : target; // Needs to be a valid <input type='range'> + + if (!is$1.element(range) || range.getAttribute('type') !== 'range') { + return; + } // Set aria values for https://github.com/sampotts/plyr/issues/905 + + + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + var currentTime = controls.formatTime(this.currentTime); + var duration = controls.formatTime(this.duration); + var format$$1 = i18n.get('seekLabel', this.config); + range.setAttribute('aria-valuetext', format$$1.replace('{currentTime}', currentTime).replace('{duration}', duration)); + } else if (matches(range, this.config.selectors.inputs.volume)) { + var percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', "".concat(percent.toFixed(1), "%")); + } else { + range.setAttribute('aria-valuenow', range.value); + } // WebKit only + + + if (!browser.isWebkit) { + return; + } // Set CSS custom property + + + range.style.setProperty('--value', "".concat(range.value / range.max * 100, "%")); + }, + // Update hover tooltip for seeking + updateSeekTooltip: function updateSeekTooltip(event) { + var _this4 = this; + + // Bail if setting not true + if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) { + return; + } // Calculate percentage + + + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + var visible = "".concat(this.config.classNames.tooltip, "--visible"); + + var toggle = function toggle(_toggle) { + toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + }; // Hide on touch + + + if (this.touch) { + toggle(false); + return; + } // Determine percentage, if already visible + + + if (is$1.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { + percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else { + return; + } // Set bounds + + + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } // Display the time a click would seek to + + + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position + + this.elements.display.seekTooltip.style.left = "".concat(percent, "%"); // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds + + if (is$1.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + toggle(event.type === 'mouseenter'); + } + }, + // Handle time change event + timeUpdate: function timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + var invert = !is$1.element(this.elements.display.duration) && this.config.invertTime; // Duration + + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking + + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } // Playing progress + + + controls.updateProgress.call(this, event); + }, + // Show the duration on metadataloaded or durationchange events + durationUpdate: function durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || !this.config.invertTime && this.currentTime) { + return; + } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 + + + if (this.duration >= Math.pow(2, 32)) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } // Update ARIA values + + + if (is$1.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); + } // If there's a spot to display duration + + + var hasDuration = is$1.element(this.elements.display.duration); // If there's only one time display, display duration there + + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } // If there's a duration element, update content + + + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } // Update the tooltip (if visible) + + + controls.updateSeekTooltip.call(this); + }, + // Hide/show a tab + toggleMenuButton: function toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); + }, + // Update the selected setting + updateSetting: function updateSetting(setting, container, input) { + var pane = this.elements.settings.panels[setting]; + var value = null; + var list = container; + + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is$1.empty(input) ? input : this[setting]; // Get default + + if (is$1.empty(value)) { + value = this.config[setting].default; + } // Unsupported value + + + if (!is$1.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn("Unsupported value of '".concat(value, "' for ").concat(setting)); + return; + } // Disabled value + + + if (!this.config[setting].options.includes(value)) { + this.debug.warn("Disabled value of '".concat(value, "' for ").concat(setting)); + return; + } + } // Get the list if we need to + + + if (!is$1.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } // If there's no list it means it's not been rendered... + + + if (!is$1.element(list)) { + return; + } // Update the label + + + var label = this.elements.settings.buttons[setting].querySelector(".".concat(this.config.classNames.menu.value)); + label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it + + var target = list && list.querySelector("[value=\"".concat(value, "\"]")); + + if (is$1.element(target)) { + target.checked = true; + } + }, + // Translate a value into a nice label + getLabel: function getLabel(setting, value) { + switch (setting) { + case 'speed': + return value === 1 ? i18n.get('normal', this.config) : "".concat(value, "×"); + + case 'quality': + if (is$1.number(value)) { + var label = i18n.get("qualityLabel.".concat(value), this.config); + + if (!label.length) { + return "".concat(value, "p"); + } + + return label; + } + + return toTitleCase(value); + + case 'captions': + return captions.getLabel.call(this); + + default: + return null; + } + }, + // Set the quality menu + setQualityMenu: function setQualityMenu(options) { + var _this5 = this; + + // Menu required + if (!is$1.element(this.elements.settings.panels.quality)) { + return; + } + + var type = 'quality'; + var list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); // Set options if passed and filter based on uniqueness and config + + if (is$1.array(options)) { + this.options.quality = dedupe(options).filter(function (quality) { + return _this5.config.quality.options.includes(quality); + }); + } // Toggle the pane and tab + + + var toggle = !is$1.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Get the badge HTML for HD, 4K etc + + + var getBadge = function getBadge(quality) { + var label = i18n.get("qualityBadge.".concat(quality), _this5.config); + + if (!label.length) { + return null; + } + + return controls.createBadge.call(_this5, label); + }; // Sort options by the config and then render options + + + this.options.quality.sort(function (a, b) { + var sorting = _this5.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }).forEach(function (quality) { + controls.createMenuItem.call(_this5, { + value: quality, + list: list, + type: type, + title: controls.getLabel.call(_this5, 'quality', quality), + badge: getBadge(quality) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Set the looping options + + /* setLoopMenu() { + // Menu required + if (!is.element(this.elements.settings.panels.loop)) { + return; + } + const options = ['start', 'end', 'all', 'reset']; + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); + // Show the pane and tab + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); + // Toggle the pane and tab + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); + // Empty the menu + emptyElement(list); + options.forEach(option => { + const item = createElement('li'); + const button = createElement( + 'button', + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { + type: 'button', + class: this.config.classNames.control, + 'data-plyr-loop-action': option, + }), + i18n.get(option, this.config) + ); + if (['start', 'end'].includes(option)) { + const badge = controls.createBadge.call(this, '00:00'); + button.appendChild(badge); + } + item.appendChild(button); + list.appendChild(item); + }); + }, */ + // Get current selected caption language + // TODO: rework this to user the getter in the API? + // Set a list of available captions languages + setCaptionsMenu: function setCaptionsMenu() { + var _this6 = this; + + // Menu required + if (!is$1.element(this.elements.settings.panels.captions)) { + return; + } // TODO: Captions or language? Currently it's mixed + + + var type = 'captions'; + var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + var tracks = captions.getTracks.call(this); + var toggle = Boolean(tracks.length); // Toggle the pane and tab + + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If there's no captions, bail + + if (!toggle) { + return; + } // Generate options data + + + var options = tracks.map(function (track, value) { + return { + value: value, + checked: _this6.captions.toggled && _this6.currentTrack === value, + title: captions.getLabel.call(_this6, track), + badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + list: list, + type: 'language' + }; + }); // Add the "Disabled" option to turn off captions + + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list: list, + type: 'language' + }); // Generate options + + options.forEach(controls.createMenuItem.bind(this)); + controls.updateSetting.call(this, type, list); + }, + // Set a list of available captions languages + setSpeedMenu: function setSpeedMenu(options) { + var _this7 = this; + + // Menu required + if (!is$1.element(this.elements.settings.panels.speed)) { + return; + } + + var type = 'speed'; + var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options + + if (is$1.array(options)) { + this.options.speed = options; + } else if (this.isHTML5 || this.isVimeo) { + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; + } // Set options if passed and filter based on config + + + this.options.speed = this.options.speed.filter(function (speed) { + return _this7.config.speed.options.includes(speed); + }); // Toggle the pane and tab + + var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu + + emptyElement(list); // Check if we need to toggle the parent + + controls.checkMenu.call(this); // If we're hiding, nothing more to do + + if (!toggle) { + return; + } // Create items + + + this.options.speed.forEach(function (speed) { + controls.createMenuItem.call(_this7, { + value: speed, + list: list, + type: type, + title: controls.getLabel.call(_this7, 'speed', speed) + }); + }); + controls.updateSetting.call(this, type, list); + }, + // Check if we need to hide/show the settings menu + checkMenu: function checkMenu() { + var buttons = this.elements.settings.buttons; + var visible = !is$1.empty(buttons) && Object.values(buttons).some(function (button) { + return !button.hidden; + }); + toggleHidden(this.elements.settings.menu, !visible); + }, + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem: function focusFirstMenuItem(pane) { + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (this.elements.settings.popup.hidden) { + return; + } + + var target = pane; + + if (!is$1.element(target)) { + target = Object.values(this.elements.settings.panels).find(function (pane) { + return !pane.hidden; + }); + } + + var firstItem = target.querySelector('[role^="menuitem"]'); + setFocus.call(this, firstItem, tabFocus); + }, + // Show/hide menu + toggleMenu: function toggleMenu(input) { + var popup = this.elements.settings.popup; + var button = this.elements.buttons.settings; // Menu and button are required + + if (!is$1.element(popup) || !is$1.element(button)) { + return; + } // True toggle by default + + + var hidden = popup.hidden; + var show = hidden; + + if (is$1.boolean(input)) { + show = input; + } else if (is$1.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is$1.event(input)) { + var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // wasn't the button or menu item and we're trying to + // show the menu (a doc click shouldn't show the menu) + + if (isMenuItem || !isMenuItem && input.target !== button && show) { + return; + } + } // Set button attributes + + + button.setAttribute('aria-expanded', show); // Show the actual popup + + toggleHidden(popup, !show); // Add class hook + + toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction + + if (show && is$1.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is$1.keyboardEvent(input)); + } + }, + // Get the natural size of a menu panel + getMenuSize: function getMenuSize(tab) { + var clone = tab.cloneNode(true); + clone.style.position = 'absolute'; + clone.style.opacity = 0; + clone.removeAttribute('hidden'); // Append to parent so we get the "real" size + + tab.parentNode.appendChild(clone); // Get the sizes before we remove + + var width = clone.scrollWidth; + var height = clone.scrollHeight; // Remove from the DOM + + removeElement(clone); + return { + width: width, + height: height + }; + }, + // Show a panel in the menu + showMenuPanel: function showMenuPanel() { + var _this8 = this; + + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail + + if (!is$1.element(target)) { + return; + } // Hide all other panels + + + var container = target.parentNode; + var current = Array.from(container.children).find(function (node) { + return !node.hidden; + }); // If we can do fancy animations, we'll animate the height/width + + if (support.transitions && !support.reducedMotion) { + // Set the current width as a base + container.style.width = "".concat(current.scrollWidth, "px"); + container.style.height = "".concat(current.scrollHeight, "px"); // Get potential sizes + + var size = controls.getMenuSize.call(this, target); // Restore auto height/width + + var restore = function restore(event) { + // We're only bothered about height and width on the container + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { + return; + } // Revert back to auto + + + container.style.width = ''; + container.style.height = ''; // Only listen once + + off.call(_this8, container, transitionEndEvent, restore); + }; // Listen for the transition finishing and restore auto height/width + + + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target + + container.style.width = "".concat(size.width, "px"); + container.style.height = "".concat(size.height, "px"); + } // Set attributes on current tab + + + toggleHidden(current, true); // Set attributes on target + + toggleHidden(target, false); // Focus the first item + + controls.focusFirstMenuItem.call(this, target, tabFocus); + }, + // Set the download link + setDownloadLink: function setDownloadLink() { + var button = this.elements.buttons.download; // Bail if no button + + if (!is$1.element(button)) { + return; + } // Set download link + + + button.setAttribute('href', this.download); + }, + // Build the default HTML + // TODO: Set order based on order in the config.controls array? + create: function create(data) { + var _this9 = this; + + // Create the container + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button + + if (this.config.controls.includes('restart')) { + container.appendChild(controls.createButton.call(this, 'restart')); + } // Rewind button + + + if (this.config.controls.includes('rewind')) { + container.appendChild(controls.createButton.call(this, 'rewind')); + } // Play/Pause button + + + if (this.config.controls.includes('play')) { + container.appendChild(controls.createButton.call(this, 'play')); + } // Fast forward button + + + if (this.config.controls.includes('fast-forward')) { + container.appendChild(controls.createButton.call(this, 'fast-forward')); + } // Progress + + + if (this.config.controls.includes('progress')) { + var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider + + progress.appendChild(controls.createRange.call(this, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress + + progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip + + if (this.config.tooltips.seek) { + var tooltip = createElement('span', { + class: this.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + this.elements.display.seekTooltip = tooltip; + } + + this.elements.progress = progress; + container.appendChild(this.elements.progress); + } // Media current time display + + + if (this.config.controls.includes('current-time')) { + container.appendChild(controls.createTime.call(this, 'currentTime')); + } // Media duration display + + + if (this.config.controls.includes('duration')) { + container.appendChild(controls.createTime.call(this, 'duration')); + } // Volume controls + + + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + var volume = createElement('div', { + class: 'plyr__volume' + }); // Toggle mute button + + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } // Volume range control + + + if (this.config.controls.includes('volume')) { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: this.config.volume + }; // Create the volume range slider + + volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + this.elements.volume = volume; + } + + container.appendChild(volume); + } // Toggle captions button + + + if (this.config.controls.includes('captions')) { + container.appendChild(controls.createButton.call(this, 'captions')); + } // Settings button / menu + + + if (this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { + var control = createElement('div', { + class: 'plyr__menu', + hidden: '' + }); + control.appendChild(controls.createButton.call(this, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu + + var menu = createElement('div', { + role: 'menu' + }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; // Build the menu items + + this.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + controls.showMenuPanel.call(_this9, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this9.config)); + var value = createElement('span', { + class: _this9.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this9.config))); // Screen reader label + + backButton.appendChild(createElement('span', { + class: _this9.config.classNames.hidden + }, i18n.get('menuBack', _this9.config))); // Go back via keyboard + + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek + + + event.preventDefault(); + event.stopPropagation(); // Show the respective menu + + controls.showMenuPanel.call(_this9, 'home', true); + }, false); // Go back via button click + + on(backButton, 'click', function () { + controls.showMenuPanel.call(_this9, 'home', false); + }); // Add to pane + + pane.appendChild(backButton); // Menu + + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this9.elements.settings.buttons[type] = menuItem; + _this9.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); + this.elements.settings.popup = popup; + this.elements.settings.menu = control; + } // Picture in picture button + + + if (this.config.controls.includes('pip') && support.pip) { + container.appendChild(controls.createButton.call(this, 'pip')); + } // Airplay button + + + if (this.config.controls.includes('airplay') && support.airplay) { + container.appendChild(controls.createButton.call(this, 'airplay')); + } // Download button + + + if (this.config.controls.includes('download')) { + var _attributes = { + element: 'a', + href: this.download, + target: '_blank' + }; + var download = this.config.urls.download; + + if (!is$1.url(download) && this.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(this.provider), + label: this.provider + }); + } + + container.appendChild(controls.createButton.call(this, 'download', _attributes)); + } // Toggle fullscreen button + + + if (this.config.controls.includes('fullscreen')) { + container.appendChild(controls.createButton.call(this, 'fullscreen')); + } // Larger overlaid play button + + + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); + } + + this.elements.controls = container; // Set available quality levels + + if (this.isHTML5) { + controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + } + + controls.setSpeedMenu.call(this); + return container; + }, + // Insert controls + inject: function inject() { + var _this10 = this; + + // Sprite + if (this.config.loadSprite) { + var icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX + + if (icon.cors) { + loadSprite(icon.url, 'sprite-plyr'); + } + } // Create a unique ID + + + this.id = Math.floor(Math.random() * 10000); // Null by default + + var container = null; + this.elements.controls = null; // Set template properties + + var props = { + id: this.id, + seektime: this.config.seekTime, + title: this.config.title + }; + var update = true; // If function, run it and use output + + if (is$1.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } // Convert falsy controls to empty array (primarily for empty strings) + + + if (!this.config.controls) { + this.config.controls = []; + } + + if (is$1.element(this.config.controls) || is$1.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option + container = this.config.controls; + } else { + // Create controls + container = controls.create.call(this, { + id: this.id, + seektime: this.config.seekTime, + speed: this.speed, + quality: this.quality, + captions: captions.getLabel.call(this) // TODO: Looping + // loop: 'None', + + }); + update = false; + } // Replace props with their value + + + var replace = function replace(input) { + var result = input; + Object.entries(props).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + value = _ref3[1]; + + result = replaceAll(result, "{".concat(key, "}"), value); + }); + return result; + }; // Update markup + + + if (update) { + if (is$1.string(this.config.controls)) { + container = replace(container); + } else if (is$1.element(container)) { + container.innerHTML = replace(container.innerHTML); + } + } // Controls container + + + var target; // Inject to custom location + + if (is$1.string(this.config.selectors.controls.container)) { + target = document.querySelector(this.config.selectors.controls.container); + } // Inject into the container by default + + + if (!is$1.element(target)) { + target = this.elements.container; + } // Inject controls HTML (needs to be before captions, hence "afterbegin") + + + var insertMethod = is$1.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be + + if (!is$1.element(this.elements.controls)) { + controls.findElements.call(this); + } // Add pressed property to buttons + + + if (!is$1.empty(this.elements.buttons)) { + var addProperty = function addProperty(button) { + var className = _this10.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get: function get() { + return hasClass(button, className); + }, + set: function set() { + var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + toggleClass(button, className, pressed); + } + }); + }; // Toggle classname when pressed property is set + + + Object.values(this.elements.buttons).filter(Boolean).forEach(function (button) { + if (is$1.array(button) || is$1.nodeList(button)) { + Array.from(button).filter(Boolean).forEach(addProperty); + } else { + addProperty(button); + } + }); + } // Edge sometimes doesn't finish the paint so force a repaint + + + if (browser.isEdge) { + repaint(target); + } // Setup tooltips + + + if (this.config.tooltips.controls) { + var _this$config = this.config, + classNames = _this$config.classNames, + selectors = _this$config.selectors; + var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); + var labels = getElements.call(this, selector); + Array.from(labels).forEach(function (label) { + toggleClass(label, _this10.config.classNames.hidden, false); + toggleClass(label, _this10.config.classNames.tooltip, true); + }); + } + } +}; + +/** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ + +function parseUrl(input) { + var safe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var url = input; + + if (safe) { + var parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } + + try { + return new URL(url); + } catch (e) { + return null; + } +} // Convert object to URLSearchParams + +function buildUrlParams(input) { + var params = new URLSearchParams(); + + if (is$1.object(input)) { + Object.entries(input).forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + params.set(key, value); + }); + } + + return params; +} + +var captions = { + // Setup captions + setup: function setup() { + // Requires UI support + if (!this.supported.ui) { + return; + } // Only Vimeo and HTML5 video supported at this point + + + if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { + // Clear menu and hide + if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + + return; + } // Inject the container + + + if (!is$1.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); + insertAfter(this.elements.captions, this.elements.wrapper); + } // Fix IE captions if CORS is used + // Fetch captions and inject as blobs instead (data URIs not supported!) + + + if (browser.isIE && window.URL) { + var elements = this.media.querySelectorAll('track'); + Array.from(elements).forEach(function (track) { + var src = track.getAttribute('src'); + var url = parseUrl(src); + + if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + fetch(src, 'blob').then(function (blob) { + track.setAttribute('src', window.URL.createObjectURL(blob)); + }).catch(function () { + removeElement(track); + }); + } + }); + } // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state + + + var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + var languages = dedupe(browserLanguages.map(function (language) { + return language.split('-')[0]; + })); + var language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto' + + if (language === 'auto') { + var _languages = _slicedToArray(languages, 1); + + language = _languages[0]; + } + + var active = this.storage.get('captions'); + + if (!is$1.boolean(active)) { + active = this.config.captions.active; + } + + Object.assign(this.captions, { + toggled: false, + active: active, + language: language, + languages: languages + }); // Watch changes to textTracks and update captions menu + + if (this.isHTML5) { + var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); + } // Update available languages in list next tick (the event must not be triggered before the listeners) + + + setTimeout(captions.update.bind(this), 0); + }, + // Update available language options in settings based on tracks + update: function update() { + var _this = this; + + var tracks = captions.getTracks.call(this, true); // Get the wanted language + + var _this$captions = this.captions, + active = _this$captions.active, + language = _this$captions.language, + meta = _this$captions.meta, + currentTrackNode = _this$captions.currentTrackNode; + var languageExists = Boolean(tracks.find(function (track) { + return track.language === language; + })); // Handle tracks (add event listener and "pseudo"-default) + + if (this.isHTML5 && this.isVideo) { + tracks.filter(function (track) { + return !meta.get(track); + }).forEach(function (track) { + _this.debug.log('Track added', track); // Attempt to store if the original dom element was "default" + + + meta.set(track, { + default: track.mode === 'showing' + }); // Turn off native caption rendering to avoid double captions + + track.mode = 'hidden'; // Add event listener for cue changes + + on.call(_this, track, 'cuechange', function () { + return captions.updateCues.call(_this); + }); + }); + } // Update language first time it matches, or if the previous matching track was removed + + + if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } // Enable or disable captions based on track length + + + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list + + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); + } + }, + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle: function toggle(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // If there's no full support + if (!this.supported.ui) { + return; + } + + var toggled = this.captions.toggled; // Current state + + var activeClass = this.config.classNames.captions.active; // Get the next state + // If the method is called without parameter, toggle based on current value + + var active = is$1.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event + + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ + captions: active + }); + } // Force language if the call isn't passive and there is no matching language to toggle to + + + if (!this.language && active && !passive) { + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [this.captions.language].concat(_toConsumableArray(this.captions.languages)), true); // Override user preferences to avoid switching languages if a matching track is added + + this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference + + captions.set.call(this, tracks.indexOf(track)); + return; + } // Toggle button if it's enabled + + + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } // Add class hook + + + toggleClass(this.elements.container, activeClass, active); + this.captions.toggled = active; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) + + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } + }, + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set: function set(index) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var tracks = captions.getTracks.call(this); // Disable captions if setting to -1 + + if (index === -1) { + captions.toggle.call(this, false, passive); + return; + } + + if (!is$1.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } + + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; + } + + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + var track = tracks[index]; + + var _ref = track || {}, + language = _ref.language; // Store reference to node for invalidation on remove + + + this.captions.currentTrackNode = track; // Update settings menu + + controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences + + if (!passive) { + this.captions.language = language; + this.storage.set({ + language: language + }); + } // Handle Vimeo captions + + + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } // Trigger event + + + triggerEvent.call(this, this.media, 'languagechange'); + } // Show captions + + + captions.toggle.call(this, true, passive); + + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } + }, + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage: function setLanguage(input) { + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (!is$1.string(input)) { + this.debug.warn('Invalid language argument', input); + return; + } // Normalize + + + var language = input.toLowerCase(); + this.captions.language = language; // Set currentTrack + + var tracks = captions.getTracks.call(this); + var track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks: function getTracks() { + var _this2 = this; + + var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + // Handle media or textTracks missing or null + var tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + + return tracks.filter(function (track) { + return !_this2.isHTML5 || update || _this2.captions.meta.has(track); + }).filter(function (track) { + return ['captions', 'subtitles'].includes(track.kind); + }); + }, + // Match tracks based on languages and get the first + findTrack: function findTrack(languages) { + var _this3 = this; + + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var tracks = captions.getTracks.call(this); + + var sortIsDefault = function sortIsDefault(track) { + return Number((_this3.captions.meta.get(track) || {}).default); + }; + + var sorted = Array.from(tracks).sort(function (a, b) { + return sortIsDefault(b) - sortIsDefault(a); + }); + var track; + languages.every(function (language) { + track = sorted.find(function (track) { + return track.language === language; + }); + return !track; // Break iteration if there is a match + }); // If no match is found but is required, get first + + return track || (force ? sorted[0] : undefined); + }, + // Get the current track + getCurrentTrack: function getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; + }, + // Get UI label for track + getLabel: function getLabel(track) { + var currentTrack = track; + + if (!is$1.track(currentTrack) && support.textTracks && this.captions.toggled) { + currentTrack = captions.getCurrentTrack.call(this); + } + + if (is$1.track(currentTrack)) { + if (!is$1.empty(currentTrack.label)) { + return currentTrack.label; + } + + if (!is$1.empty(currentTrack.language)) { + return track.language.toUpperCase(); + } + + return i18n.get('enabled', this.config); + } + + return i18n.get('disabled', this.config); + }, + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues: function updateCues(input) { + // Requires UI + if (!this.supported.ui) { + return; + } + + if (!is$1.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; + } // Only accept array or empty input + + + if (!is$1.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); + return; + } + + var cues = input; // Get cues from track + + if (!cues) { + var track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []).map(function (cue) { + return cue.getCueAsHTML(); + }).map(getHTML); + } // Set new caption text + + + var content = cues.map(function (cueText) { + return cueText.trim(); + }).join('\n'); + var changed = content !== this.elements.captions.innerHTML; + + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + var caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); // Trigger event + + triggerEvent.call(this, this.media, 'cuechange'); + } + } +}; + +// ========================================================================== +// Plyr default config +// ========================================================================== +var defaults = { + // Disable + enabled: true, + // Custom media title + title: '', + // Logging to console + debug: false, + // Auto play (if supported) + autoplay: false, + // Only allow one media playing at once (vimeo only) + autopause: true, + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, + // Default time to skip when rewind/fast forward + seekTime: 10, + // Default volume + volume: 1, + muted: false, + // Pass a custom duration + duration: null, + // Display the media duration on load in the current time position + // If you have opted to display both duration and currentTime, this is ignored + displayDuration: true, + // Invert the current time to be a countdown + invertTime: true, + // Clicking the currentTime inverts it's value to show time left rather than elapsed + toggleInvert: true, + // Aspect ratio (for embeds) + ratio: '16:9', + // Click video container to play/pause + clickToPlay: true, + // Auto hide the controls + hideControls: true, + // Reset to start when playback ended + resetOnEnd: false, + // Disable the standard context menu + disableContextMenu: true, + // Sprite (for icons) + loadSprite: true, + iconPrefix: 'plyr', + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', + // Blank video (used to prevent errors on source change) + blankVideo: 'https://cdn.plyr.io/static/blank.mp4', + // Quality default + quality: { + default: 576, + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240] + }, + // Set loops + loop: { + active: false // start: null, + // end: null, + + }, + // Speed default and options to display + speed: { + selected: 1, + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] + }, + // Keyboard shortcut settings + keyboard: { + focused: true, + global: false + }, + // Display tooltips + tooltips: { + controls: false, + seek: true + }, + // Captions settings + captions: { + active: false, + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false + }, + // Fullscreen settings + fullscreen: { + enabled: true, + // Allow fullscreen? + fallback: true, + // Fallback using full viewport/window + iosNative: false // Use the native fullscreen in iOS (disables custom controls) + + }, + // Local storage + storage: { + enabled: true, + key: 'plyr' + }, + // Default controls + controls: ['play-large', // 'restart', + // 'rewind', + 'play', // 'fast-forward', + 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download', + 'fullscreen'], + settings: ['captions', 'quality', 'speed'], + // Localisation + i18n: { + restart: 'Restart', + rewind: 'Rewind {seektime}s', + play: 'Play', + pause: 'Pause', + fastForward: 'Forward {seektime}s', + seek: 'Seek', + seekLabel: '{currentTime} of {duration}', + played: 'Played', + buffered: 'Buffered', + currentTime: 'Current time', + duration: 'Duration', + volume: 'Volume', + mute: 'Mute', + unmute: 'Unmute', + enableCaptions: 'Enable captions', + disableCaptions: 'Disable captions', + download: 'Download', + enterFullscreen: 'Enter fullscreen', + exitFullscreen: 'Exit fullscreen', + frameTitle: 'Player for {title}', + captions: 'Captions', + settings: 'Settings', + menuBack: 'Go back to previous menu', + speed: 'Speed', + normal: 'Normal', + quality: 'Quality', + loop: 'Loop', + start: 'Start', + end: 'End', + all: 'All', + reset: 'Reset', + disabled: 'Disabled', + enabled: 'Enabled', + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } + }, + // URLs + urls: { + download: null, + vimeo: { + sdk: 'https://player.vimeo.com/api/player.js', + iframe: 'https://player.vimeo.com/video/{0}?{1}', + api: 'https://vimeo.com/api/v2/video/{0}.json' + }, + youtube: { + sdk: 'https://www.youtube.com/iframe_api', + api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + }, + googleIMA: { + sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' + } + }, + // Custom control listeners + listeners: { + seek: null, + play: null, + pause: null, + restart: null, + rewind: null, + fastForward: null, + mute: null, + volume: null, + captions: null, + download: null, + fullscreen: null, + pip: null, + airplay: null, + speed: null, + quality: null, + loop: null, + language: null + }, + // Events to watch and bubble + events: [// Events to watch on HTML5 media elements and bubble + // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events + 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube + 'statechange', // Quality + 'qualitychange', // Ads + 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'], + // Selectors + // Change these to match your template if using custom HTML + selectors: { + editable: 'input, textarea, select, [contenteditable]', + container: '.plyr', + controls: { + container: null, + wrapper: '.plyr__controls' + }, + labels: '[data-plyr]', + buttons: { + play: '[data-plyr="play"]', + pause: '[data-plyr="pause"]', + restart: '[data-plyr="restart"]', + rewind: '[data-plyr="rewind"]', + fastForward: '[data-plyr="fast-forward"]', + mute: '[data-plyr="mute"]', + captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', + fullscreen: '[data-plyr="fullscreen"]', + pip: '[data-plyr="pip"]', + airplay: '[data-plyr="airplay"]', + settings: '[data-plyr="settings"]', + loop: '[data-plyr="loop"]' + }, + inputs: { + seek: '[data-plyr="seek"]', + volume: '[data-plyr="volume"]', + speed: '[data-plyr="speed"]', + language: '[data-plyr="language"]', + quality: '[data-plyr="quality"]' + }, + display: { + currentTime: '.plyr__time--current', + duration: '.plyr__time--duration', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', + // Used later + volume: '.plyr__volume--display' + }, + progress: '.plyr__progress', + captions: '.plyr__captions', + caption: '.plyr__caption', + menu: { + quality: '.js-plyr__menu__list--quality' + } + }, + // Class hooks added to the player in different states + classNames: { + type: 'plyr--{0}', + provider: 'plyr--{0}', + video: 'plyr__video-wrapper', + embed: 'plyr__video-embed', + embedContainer: 'plyr__video-embed__container', + poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', + ads: 'plyr__ads', + control: 'plyr__control', + controlPressed: 'plyr__control--pressed', + playing: 'plyr--playing', + paused: 'plyr--paused', + stopped: 'plyr--stopped', + loading: 'plyr--loading', + hover: 'plyr--hover', + tooltip: 'plyr__tooltip', + cues: 'plyr__cues', + hidden: 'plyr__sr-only', + hideControls: 'plyr--hide-controls', + isIos: 'plyr--is-ios', + isTouch: 'plyr--is-touch', + uiSupported: 'plyr--full-ui', + noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time' + }, + menu: { + value: 'plyr__menu__value', + badge: 'plyr__badge', + open: 'plyr--menu-open' + }, + captions: { + enabled: 'plyr--captions-enabled', + active: 'plyr--captions-active' + }, + fullscreen: { + enabled: 'plyr--fullscreen-enabled', + fallback: 'plyr--fullscreen-fallback' + }, + pip: { + supported: 'plyr--pip-supported', + active: 'plyr--pip-active' + }, + airplay: { + supported: 'plyr--airplay-supported', + active: 'plyr--airplay-active' + }, + tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' + } + }, + // Embed attributes + attributes: { + embed: { + provider: 'data-plyr-provider', + id: 'data-plyr-embed-id' + } + }, + // API keys + keys: { + google: null + }, + // Advertisements plugin + // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio + ads: { + enabled: false, + publisherId: '', + tagUrl: '' + }, + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '' + }, + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false + }, + // YouTube plugin + youtube: { + noCookie: false, + // Whether to use an alternative version of YouTube without cookies + rel: 0, + // No related vids + showinfo: 0, + // Hide info + iv_load_policy: 3, + // Hide annotations + modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) + + } +}; + +// ========================================================================== +// Plyr states +// ========================================================================== +var pip = { + active: 'picture-in-picture', + inactive: 'inline' +}; + +// ========================================================================== +// Plyr supported types and providers +// ========================================================================== +var providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo' +}; +var types = { + audio: 'audio', + video: 'video' +}; +/** + * Get provider by URL + * @param {String} url + */ + +function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } // Vimeo + + + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; + } + + return null; +} + +// ========================================================================== +// Console wrapper +// ========================================================================== +var noop = function noop() {}; + +var Console = +/*#__PURE__*/ +function () { + function Console() { + var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + _classCallCheck(this, Console); + + this.enabled = window.console && enabled; + + if (this.enabled) { + this.log('Debugging enabled'); + } + } + + _createClass(Console, [{ + key: "log", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; + } + }, { + key: "warn", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; + } + }, { + key: "error", + get: function get() { + // eslint-disable-next-line no-console + return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; + } + }]); + + return Console; +}(); + +function onChange() { + if (!this.enabled) { + return; + } // Update toggle button + + + var button = this.player.elements.buttons.fullscreen; + + if (is$1.element(button)) { + button.pressed = this.active; + } // Trigger an event + + + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container + + if (!browser.isIos) { + trapFocus.call(this.player, this.target, this.active); + } +} + +function toggleFallback() { + var _this = this; + + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + // Store or restore scroll position + if (toggle) { + this.scrollPosition = { + x: window.scrollX || 0, + y: window.scrollY || 0 + }; + } else { + window.scrollTo(this.scrollPosition.x, this.scrollPosition.y); + } // Toggle scroll + + + document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook + + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+ + + if (browser.isIos) { + var viewport = document.head.querySelector('meta[name="viewport"]'); + var property = 'viewport-fit=cover'; // Inject the viewport meta if required + + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } // Check if the property already exists + + + var hasProperty = is$1.string(viewport.content) && viewport.content.includes(property); + + if (toggle) { + this.cleanupViewport = !hasProperty; + + if (!hasProperty) { + viewport.content += ",".concat(property); + } + } else if (this.cleanupViewport) { + viewport.content = viewport.content.split(',').filter(function (part) { + return part.trim() !== property; + }).join(','); + } // Force a repaint as sometimes Safari doesn't want to fill the screen + + + setTimeout(function () { + return repaint(_this.target); + }, 100); + } // Toggle button and fire events + + + onChange.call(this); +} + +var Fullscreen = +/*#__PURE__*/ +function () { + function Fullscreen(player) { + var _this2 = this; + + _classCallCheck(this, Fullscreen); + + // Keep reference to parent + this.player = player; // Get prefix + + this.prefix = Fullscreen.prefix; + this.property = Fullscreen.property; // Scroll position + + this.scrollPosition = { + x: 0, + y: 0 + }; // Force the use of 'full window/browser' rather than fullscreen + + this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners + // Handle event (incase user presses escape etc) + + on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { + // TODO: Filter for target?? + onChange.call(_this2); + }); // Fullscreen toggle on double click + + on.call(this.player, this.player.elements.container, 'dblclick', function (event) { + // Ignore double click in controls + if (is$1.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) { + return; + } + + _this2.toggle(); + }); // Update the UI + + this.update(); + } // Determine if native supported + + + _createClass(Fullscreen, [{ + key: "update", + // Update UI + value: function update() { + if (this.enabled) { + var mode; + + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } + + this.player.debug.log("".concat(mode, " fullscreen enabled")); + } else { + this.player.debug.log('Fullscreen not supported and fallback disabled'); + } // Add styling hook to show button + + + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + } // Make an element fullscreen + + }, { + key: "enter", + value: function enter() { + if (!this.enabled) { + return; + } // iOS native fullscreen doesn't need the request step + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, true); + } else if (!this.prefix) { + this.target.requestFullscreen(); + } else if (!is$1.empty(this.prefix)) { + this.target["".concat(this.prefix, "Request").concat(this.property)](); + } + } // Bail from fullscreen + + }, { + key: "exit", + value: function exit() { + if (!this.enabled) { + return; + } // iOS native fullscreen + + + if (browser.isIos && this.player.config.fullscreen.iosNative) { + this.target.webkitExitFullscreen(); + this.player.play(); + } else if (!Fullscreen.native || this.forceFallback) { + toggleFallback.call(this, false); + } else if (!this.prefix) { + (document.cancelFullScreen || document.exitFullscreen).call(document); + } else if (!is$1.empty(this.prefix)) { + var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; + document["".concat(this.prefix).concat(action).concat(this.property)](); + } + } // Toggle state + + }, { + key: "toggle", + value: function toggle() { + if (!this.active) { + this.enter(); + } else { + this.exit(); + } + } + }, { + key: "usingNative", + // If we're actually using native + get: function get() { + return Fullscreen.native && !this.forceFallback; + } // Get the prefix for handlers + + }, { + key: "enabled", + // Determine if fullscreen is enabled + get: function get() { + return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo; + } // Get active state + + }, { + key: "active", + get: function get() { + if (!this.enabled) { + return false; + } // Fallback using classname + + + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + } + + var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; + return element === this.target; + } // Get target element + + }, { + key: "target", + get: function get() { + return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + } + }], [{ + key: "native", + get: function get() { + return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + } + }, { + key: "prefix", + get: function get() { + // No prefix + if (is$1.function(document.exitFullscreen)) { + return ''; + } // Check for fullscreen support by vendor prefix + + + var value = ''; + var prefixes = ['webkit', 'moz', 'ms']; + prefixes.some(function (pre) { + if (is$1.function(document["".concat(pre, "ExitFullscreen")]) || is$1.function(document["".concat(pre, "CancelFullScreen")])) { + value = pre; + return true; + } + + return false; + }); + return value; + } + }, { + key: "property", + get: function get() { + return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; + } + }]); + + return Fullscreen; +}(); + +// 20.2.2.28 Math.sign(x) +var _mathSign = Math.sign || function sign(x) { + // eslint-disable-next-line no-self-compare + return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1; +}; + +// 20.2.2.28 Math.sign(x) + + +_export(_export.S, 'Math', { sign: _mathSign }); + +// ========================================================================== +// Load image avoiding xhr/fetch CORS issues +// Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded +// By default it checks if it is at least 1px, but you can add a second argument to change this +// ========================================================================== +function loadImage(src) { + var minWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return new Promise(function (resolve, reject) { + var image = new Image(); + + var handler = function handler() { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { + onload: handler, + onerror: handler, + src: src + }); + }); +} + +var ui = { + addStyleHook: function addStyleHook() { + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + }, + // Toggle native HTML5 media controls + toggleNativeControls: function toggleNativeControls() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (toggle && this.isHTML5) { + this.media.setAttribute('controls', ''); + } else { + this.media.removeAttribute('controls'); + } + }, + // Setup the UI + build: function build() { + var _this = this; + + // Re-attach media element listeners + // TODO: Use event bubbling? + this.listeners.media(); // Don't setup interface if no support + + if (!this.supported.ui) { + this.debug.warn("Basic support only for ".concat(this.provider, " ").concat(this.type)); // Restore native controls + + ui.toggleNativeControls.call(this, true); // Bail + + return; + } // Inject custom controls if not present + + + if (!is$1.element(this.elements.controls)) { + // Inject custom controls + controls.inject.call(this); // Re-attach control listeners + + this.listeners.controls(); + } // Remove native controls + + + ui.toggleNativeControls.call(this); // Setup captions for HTML5 + + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume + + + this.volume = null; // Reset mute state + + this.muted = null; // Reset speed + + this.speed = null; // Reset loop state + + this.loop = null; // Reset quality setting + + this.quality = null; // Reset volume display + + controls.updateVolume.call(this); // Reset time display + + controls.timeUpdate.call(this); // Update the UI + + ui.checkPlaying.call(this); // Check for picture-in-picture support + + toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support + + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class + + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class + + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls + + this.ready = true; // Ready event at end of execution stack + + setTimeout(function () { + triggerEvent.call(_this, _this.media, 'ready'); + }, 0); // Set the title + + ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created + + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(function () {}); + } // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + + + if (this.config.duration) { + controls.durationUpdate.call(this); + } + }, + // Setup aria attribute for play and iframe title + setTitle: function setTitle() { + // Find the current text + var label = i18n.get('play', this.config); // If there's a media title set, use that for the label + + if (is$1.string(this.config.title) && !is$1.empty(this.config.title)) { + label += ", ".concat(this.config.title); + } // If there's a play button, set label + + + Array.from(this.elements.buttons.play || []).forEach(function (button) { + button.setAttribute('aria-label', label); + }); // Set iframe title + // https://github.com/sampotts/plyr/issues/124 + + if (this.isEmbed) { + var iframe = getElement.call(this, 'iframe'); + + if (!is$1.element(iframe)) { + return; + } // Default to media type + + + var title = !is$1.empty(this.config.title) ? this.config.title : 'video'; + var format = i18n.get('frameTitle', this.config); + iframe.setAttribute('title', format.replace('{title}', title)); + } + }, + // Toggle poster + togglePoster: function togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster: function setPoster(poster) { + var _this2 = this; + + var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); + } // Set property synchronously to respect the call order + + + this.media.setAttribute('poster', poster); // Wait until ui is ready + + return ready.call(this) // Load image + .then(function () { + return loadImage(poster); + }).catch(function (err) { + // Hide poster on error unless it's been set by another call + if (poster === _this2.poster) { + ui.togglePoster.call(_this2, false); + } // Rethrow + + + throw err; + }).then(function () { + // Prevent race conditions + if (poster !== _this2.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }).then(function () { + Object.assign(_this2.elements.poster.style, { + backgroundImage: "url('".concat(poster, "')"), + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '' + }); + ui.togglePoster.call(_this2, true); + return poster; + }); + }, + // Check playing state + checkPlaying: function checkPlaying(event) { + var _this3 = this; + + // Class hooks + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state + + Array.from(this.elements.buttons.play || []).forEach(function (target) { + target.pressed = _this3.playing; + }); // Only update controls on non timeupdate events + + if (is$1.event(event) && event.type === 'timeupdate') { + return; + } // Toggle controls + + + ui.toggleControls.call(this); + }, + // Check if media is loading + checkLoading: function checkLoading(event) { + var _this4 = this; + + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer + + clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking + + this.timers.loading = setTimeout(function () { + // Update progress bar loading class state + toggleClass(_this4.elements.container, _this4.config.classNames.loading, _this4.loading); // Update controls visibility + + ui.toggleControls.call(_this4); + }, this.loading ? 250 : 0); + }, + // Toggle controls based on state and `force` argument + toggleControls: function toggleControls(force) { + var controls$$1 = this.elements.controls; + + if (controls$$1 && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide + + this.toggleControls(Boolean(force || this.loading || this.paused || controls$$1.pressed || controls$$1.hover || recentTouchSeek)); + } + } +}; + +/* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; +} */ +// Set aspect ratio for responsive container + +function setAspectRatio(input) { + var ratio = input; + + if (!is$1.string(ratio) && !is$1.nullOrUndefined(this.embed)) { + ratio = this.embed.ratio; + } + + if (!is$1.string(ratio)) { + ratio = this.config.ratio; + } + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + x = _ratio$split$map2[0], + y = _ratio$split$map2[1]; + + var padding = 100 / x * y; + this.elements.wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI + + if (this.isVimeo && this.supported.ui) { + var height = 240; + var offset = (height - padding) / (height / 50); + this.media.style.transform = "translateY(-".concat(offset, "%)"); + } + + return { + padding: padding, + ratio: ratio + }; +} + +var Listeners = +/*#__PURE__*/ +function () { + function Listeners(player) { + _classCallCheck(this, Listeners); + + this.player = player; + this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; + this.handleKey = this.handleKey.bind(this); + this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); + this.firstTouch = this.firstTouch.bind(this); + } // Handle key presses + + + _createClass(Listeners, [{ + key: "handleKey", + value: function handleKey(event) { + var player = this.player; + var elements = player.elements; + var code = event.keyCode ? event.keyCode : event.which; + var pressed = event.type === 'keydown'; + var repeat = pressed && code === this.lastKey; // Bail if a modifier key is set + + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } // If the event is bubbled from the media element + // Firefox doesn't get the keycode for whatever reason + + + if (!is$1.number(code)) { + return; + } // Seek by the number keys + + + var seekByKey = function seekByKey() { + // Divide the max duration into 10th's and times by the number value + player.currentTime = player.duration / 10 * (code - 48); + }; // Handle the key on keydown + // Reset on keyup + + + if (pressed) { + // Check focused element + // and if the focused element is not editable (e.g. text input) + // and any that accept key input http://webaim.org/techniques/keyboard/ + var focused = document.activeElement; + + if (is$1.element(focused)) { + var editable = player.config.selectors.editable; + var seek = elements.inputs.seek; + + if (focused !== seek && matches(focused, editable)) { + return; + } + + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } + } // Which keycodes should we prevent default + + + var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows) + + if (preventDefault.includes(code)) { + event.preventDefault(); + event.stopPropagation(); + } + + switch (code) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + // 0-9 + if (!repeat) { + seekByKey(); + } + + break; + + case 32: + case 75: + // Space and K key + if (!repeat) { + player.togglePlay(); + } + + break; + + case 38: + // Arrow up + player.increaseVolume(0.1); + break; + + case 40: + // Arrow down + player.decreaseVolume(0.1); + break; + + case 77: + // M key + if (!repeat) { + player.muted = !player.muted; + } + + break; + + case 39: + // Arrow forward + player.forward(); + break; + + case 37: + // Arrow back + player.rewind(); + break; + + case 70: + // F key + player.fullscreen.toggle(); + break; + + case 67: + // C key + if (!repeat) { + player.toggleCaptions(); + } + + break; + + case 76: + // L key + player.loop = !player.loop; + break; + + /* case 73: + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ + + default: + break; + } // Escape is handle natively when in full screen + // So we only need to worry about non native + + + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); + } // Store last code for next cycle + + + this.lastKey = code; + } else { + this.lastKey = null; + } + } // Toggle menu + + }, { + key: "toggleMenu", + value: function toggleMenu(event) { + controls.toggleMenu.call(this.player, event); + } // Device is touch enabled + + }, { + key: "firstTouch", + value: function firstTouch() { + var player = this.player; + var elements = player.elements; + player.touch = true; // Add touch class + + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + }, { + key: "setTabFocus", + value: function setTabFocus(event) { + var player = this.player; + var elements = player.elements; + clearTimeout(this.focusTimer); // Ignore any key other than tab + + if (event.type === 'keydown' && event.which !== 9) { + return; + } // Store reference to event timeStamp + + + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } // Remove current classes + + + var removeCurrent = function removeCurrent() { + var className = player.config.classNames.tabFocus; + var current = getElements.call(player, ".".concat(className)); + toggleClass(current, className, false); + }; // Determine if a key was pressed to trigger this event + + + var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior + + if (event.type === 'focus' && !wasKeyDown) { + return; + } // Remove all current + + + removeCurrent(); // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + + this.focusTimer = setTimeout(function () { + var focused = document.activeElement; // Ignore if current focus element isn't inside the player + + if (!elements.container.contains(focused)) { + return; + } + + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); + } // Global window & document listeners + + }, { + key: "global", + value: function global() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var player = this.player; // Keyboard shortcuts + + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); + } // Click anywhere closes menu + + + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events + + once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection + + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); + } // Container listeners + + }, { + key: "container", + value: function container() { + var player = this.player; + var config = player.config, + elements = player.elements, + timers = player.timers; // Keyboard shortcuts + + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); + } // Toggle controls on mouse events and entering fullscreen + + + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen + + if (controls$$1 && event.type === 'enterfullscreen') { + controls$$1.pressed = false; + controls$$1.hover = false; + } // Show, then hide after a timeout unless another control event occurs + + + var show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + var delay = 0; + + if (show) { + ui.toggleControls.call(player, true); // Use longer timeout for touch devices + + delay = player.touch ? 3000 : 2000; + } // Clear timer + + + clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen + + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); + }); + } */ + // Set a gutter for Vimeo + + var setGutter = function setGutter(ratio, padding, toggle) { + if (!player.isVimeo) { + return; + } + + var target = player.elements.wrapper.firstChild; + + var _ratio$split$map = ratio.split(':').map(Number), + _ratio$split$map2 = _slicedToArray(_ratio$split$map, 2), + height = _ratio$split$map2[1]; + + var _player$embed$ratio$s = player.embed.ratio.split(':').map(Number), + _player$embed$ratio$s2 = _slicedToArray(_player$embed$ratio$s, 2), + videoWidth = _player$embed$ratio$s2[0], + videoHeight = _player$embed$ratio$s2[1]; + + target.style.maxWidth = toggle ? "".concat(height / videoHeight * videoWidth, "px") : null; + target.style.margin = toggle ? '0 auto' : null; + }; // Resize on fullscreen change + + + var setPlayerSize = function setPlayerSize(measure) { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } + + var rect = elements.container.getBoundingClientRect(); + var width = rect.width, + height = rect.height; + return setAspectRatio.call(player, "".concat(width, ":").concat(height)); + }; + + var resized = function resized() { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; + + on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) { + var _player$fullscreen = player.fullscreen, + target = _player$fullscreen.target, + usingNative = _player$fullscreen.usingNative; // Ignore for iOS native + + if (!player.isEmbed || target !== elements.container) { + return; + } + + var isEnter = event.type === 'enterfullscreen'; // Set the player size when entering fullscreen to viewport size + + var _setPlayerSize = setPlayerSize(isEnter), + padding = _setPlayerSize.padding, + ratio = _setPlayerSize.ratio; // Set Vimeo gutter + + + setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport + + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); + } + } + }); + } // Listen for media events + + }, { + key: "media", + value: function media() { + var _this = this; + + var player = this.player; + var elements = player.elements; // Time change on media + + on.call(player, player.media, 'timeupdate seeking seeked', function (event) { + return controls.timeUpdate.call(player, event); + }); // Display duration + + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) { + return controls.durationUpdate.call(player, event); + }); // Check for audio tracks on load + // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point + + on.call(player, player.media, 'canplay loadeddata', function () { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); + }); // Handle the media finishing + + on.call(player, player.media, 'ended', function () { + // Show poster on end + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { + // Restart + player.restart(); + } + }); // Check for buffer progress + + on.call(player, player.media, 'progress playing seeking seeked', function (event) { + return controls.updateProgress.call(player, event); + }); // Handle volume changes + + on.call(player, player.media, 'volumechange', function (event) { + return controls.updateVolume.call(player, event); + }); // Handle play/pause + + on.call(player, player.media, 'playing play pause ended emptied timeupdate', function (event) { + return ui.checkPlaying.call(player, event); + }); // Loading state + + on.call(player, player.media, 'waiting canplay seeked playing', function (event) { + return ui.checkLoading.call(player, event); + }); // If autoplay, then load advertisement if required + // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows + + on.call(player, player.media, 'playing', function () { + if (!player.ads) { + return; + } // If ads are enabled, wait for them first + + + if (player.ads.enabled && !player.ads.initialized) { + // Wait for manager response + player.ads.managerPromise.then(function () { + return player.ads.play(); + }).catch(function () { + return player.play(); + }); + } + }); // Click video + + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { + // Re-fetch the wrapper + var wrapper = getElement.call(player, ".".concat(player.config.classNames.video)); // Bail if there's no wrapper (this should never happen) + + if (!is$1.element(wrapper)) { + return; + } // On click play, pause or restart + + + on.call(player, elements.container, 'click', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper + + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } // Touch devices will just show controls (if hidden) + + + if (player.touch && player.config.hideControls) { + return; + } + + if (player.ended) { + _this.proxy(event, player.restart, 'restart'); + + _this.proxy(event, player.play, 'play'); + } else { + _this.proxy(event, player.togglePlay, 'play'); + } + }); + } // Disable right click + + + if (player.supported.ui && player.config.disableContextMenu) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { + event.preventDefault(); + }, false); + } // Volume change + + + on.call(player, player.media, 'volumechange', function () { + // Save to storage + player.storage.set({ + volume: player.volume, + muted: player.muted + }); + }); // Speed change + + on.call(player, player.media, 'ratechange', function () { + // Update UI + controls.updateSetting.call(player, 'speed'); // Save to storage + + + player.storage.set({ + speed: player.speed + }); + }); // Quality change + + on.call(player, player.media, 'qualitychange', function (event) { + // Update UI + controls.updateSetting.call(player, 'quality', null, event.detail.quality); + }); // Update download link when ready and if quality changes + + on.call(player, player.media, 'ready qualitychange', function () { + controls.setDownloadLink.call(player); + }); // Proxy events to container + // Bubble up key events for Edge + + var proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + on.call(player, player.media, proxyEvents, function (event) { + var _event$detail = event.detail, + detail = _event$detail === void 0 ? {} : _event$detail; // Get error details from media + + if (event.type === 'error') { + detail = player.media.error; + } + + triggerEvent.call(player, elements.container, event.type, true, detail); + }); + } // Run default and custom handlers + + }, { + key: "proxy", + value: function proxy(event, defaultHandler, customHandlerKey) { + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is$1.function(customHandler); + var returned = true; // Execute custom handler + + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } // Only call default handler if not prevented in custom handler + + + if (returned && is$1.function(defaultHandler)) { + defaultHandler.call(player, event); + } + } // Trigger custom and default handlers + + }, { + key: "bind", + value: function bind(element, type, defaultHandler, customHandlerKey) { + var _this2 = this; + + var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var player = this.player; + var customHandler = player.config.listeners[customHandlerKey]; + var hasCustomHandler = is$1.function(customHandler); + on.call(player, element, type, function (event) { + return _this2.proxy(event, defaultHandler, customHandlerKey); + }, passive && !hasCustomHandler); + } // Listen for control events + + }, { + key: "controls", + value: function controls$$1() { + var _this3 = this; + + var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change + + var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle + + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { + _this3.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause + + + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind + + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind + + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle + + this.bind(elements.buttons.mute, 'click', function () { + player.muted = !player.muted; + }, 'mute'); // Captions toggle + + this.bind(elements.buttons.captions, 'click', function () { + return player.toggleCaptions(); + }); // Download + + this.bind(elements.buttons.download, 'click', function () { + triggerEvent.call(player, player.media, 'download'); + }, 'download'); // Fullscreen toggle + + this.bind(elements.buttons.fullscreen, 'click', function () { + player.fullscreen.toggle(); + }, 'fullscreen'); // Picture-in-Picture + + this.bind(elements.buttons.pip, 'click', function () { + player.pip = 'toggle'; + }, 'pip'); // Airplay + + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle + + this.bind(elements.buttons.settings, 'click', function (event) { + // Prevent the document click listener closing the menu + event.stopPropagation(); + + controls.toggleMenu.call(player, event); + }); // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + + this.bind(elements.buttons.settings, 'keyup', function (event) { + var code = event.which; // We only care about space and return + + if (![13, 32].includes(code)) { + return; + } // Because return triggers a click anyway, all we need to do is set focus + + + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); + + return; + } // Prevent scroll + + + event.preventDefault(); // Prevent playing video (Firefox) + + event.stopPropagation(); // Toggle menu + + controls.toggleMenu.call(player, event); + }, null, false // Can't be passive as we're preventing default + ); // Escape closes menu + + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); // Set range input alternative "value", which matches the tooltip time (#954) + + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); + var percent = 100 / rect.width * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); // Pause while seeking + + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var attribute = 'play-on-seeked'; + + if (is$1.keyboardEvent(event) && code !== 39 && code !== 37) { + return; + } // Record seek time so we can prevent hiding controls for a few seconds after seek + + + player.lastSeekTime = Date.now(); // Was playing before? + + var play = seek.hasAttribute(attribute); // Done seeking + + var done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback + + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); + } + }); // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + + if (browser.isIos) { + var inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(function (input) { + return _this3.bind(input, inputEvent, function (event) { + return repaint(event.target); + }); + }); + } // Seek + + + this.bind(elements.inputs.seek, inputEvent, function (event) { + var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) + + var seekTo = seek.getAttribute('seek-value'); + + if (is$1.empty(seekTo)) { + seekTo = seek.value; + } + + seek.removeAttribute('seek-value'); + player.currentTime = seekTo / seek.max * player.duration; + }, 'seek'); // Seek tooltip + + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this + + this.bind(elements.progress, 'mousemove touchmove', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + + this.bind(elements.progress, 'mouseleave click', function () { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); // Show scrubbing preview + + this.bind(elements.progress, 'mousedown touchstart', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } + }); + this.bind(elements.progress, 'mouseup touchend', function (event) { + var previewThumbnails = player.previewThumbnails; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); // Polyfill for lower fill in <input type="range"> for webkit + + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this3.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); + }); + }); + } // Current time invert + // Only if one time element is used for both currentTime and duration + + + if (player.config.toggleInvert && !is$1.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { + // Do nothing if we're at the start + if (player.currentTime === 0) { + return; + } + + player.config.invertTime = !player.config.invertTime; + + controls.timeUpdate.call(player); + }); + } // Volume + + + this.bind(elements.inputs.volume, inputEvent, function (event) { + player.volume = event.target.value; + }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) + + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); // Show controls when they receive focus (e.g., when using keyboard tab key) + + this.bind(elements.controls, 'focusin', function () { + var config = player.config, + elements = player.elements, + timers = player.timers; // Skip transition to prevent focus from scrolling the parent element + + toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle + + ui.toggleControls.call(player, true); // Restore transition + + setTimeout(function () { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); // Delay a little more for mouse users + + var delay = _this3.touch ? 3000 : 4000; // Clear timer + + clearTimeout(timers.controls); // Hide again after delay + + timers.controls = setTimeout(function () { + return ui.toggleControls.call(player, false); + }, delay); + }); // Mouse wheel for volume + + this.bind(elements.inputs.volume, 'wheel', function (event) { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + var inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true + + var _map = [event.deltaX, -event.deltaY].map(function (value) { + return inverted ? -value : value; + }), + _map2 = _slicedToArray(_map, 2), + x = _map2[0], + y = _map2[1]; // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) + + + var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2% + + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min + + var volume = player.media.volume; + + if (direction === 1 && volume < 1 || direction === -1 && volume > 0) { + event.preventDefault(); + } + }, 'volume', false); + } + }]); + + return Listeners; +}(); + +var dP$3 = _objectDp.f; +var FProto = Function.prototype; +var nameRE = /^\s*function ([^ (]*)/; +var NAME$1 = 'name'; + +// 19.2.4.2 name +NAME$1 in FProto || _descriptors && dP$3(FProto, NAME$1, { + configurable: true, + get: function () { + try { + return ('' + this).match(nameRE)[1]; + } catch (e) { + return ''; + } + } +}); + +// @@match logic +_fixReWks('match', 1, function (defined, MATCH, $match, maybeCallNative) { + return [ + // `String.prototype.match` method + // https://tc39.github.io/ecma262/#sec-string.prototype.match + function match(regexp) { + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[MATCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); + }, + // `RegExp.prototype[@@match]` method + // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match + function (regexp) { + var res = maybeCallNative($match, regexp, this); + if (res.done) return res.value; + var rx = _anObject(regexp); + var S = String(this); + if (!rx.global) return _regexpExecAbstract(rx, S); + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + var A = []; + var n = 0; + var result; + while ((result = _regexpExecAbstract(rx, S)) !== null) { + var matchStr = String(result[0]); + A[n] = matchStr; + if (matchStr === '') rx.lastIndex = _advanceStringIndex(S, _toLength(rx.lastIndex), fullUnicode); + n++; + } + return n === 0 ? null : A; + } + ]; +}); + +var loadjs_umd = createCommonjsModule(function (module, exports) { +(function(root, factory) { + { + module.exports = factory(); + } +}(commonjsGlobal, function() { +/** + * Global dependencies. + * @global {Object} document - DOM + */ + +var devnull = function() {}, + bundleIdCache = {}, + bundleResultCache = {}, + bundleCallbackQueue = {}; + + +/** + * Subscribe to bundle load event. + * @param {string[]} bundleIds - Bundle ids + * @param {Function} callbackFn - The callback function + */ +function subscribe(bundleIds, callbackFn) { + // listify + bundleIds = bundleIds.push ? bundleIds : [bundleIds]; + + var depsNotFound = [], + i = bundleIds.length, + numWaiting = i, + fn, + bundleId, + r, + q; + + // define callback function + fn = function (bundleId, pathsNotFound) { + if (pathsNotFound.length) depsNotFound.push(bundleId); + + numWaiting--; + if (!numWaiting) callbackFn(depsNotFound); + }; + + // register callback + while (i--) { + bundleId = bundleIds[i]; + + // execute callback if in result cache + r = bundleResultCache[bundleId]; + if (r) { + fn(bundleId, r); + continue; + } + + // add to callback queue + q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || []; + q.push(fn); + } +} + + +/** + * Publish bundle load event. + * @param {string} bundleId - Bundle id + * @param {string[]} pathsNotFound - List of files not found + */ +function publish(bundleId, pathsNotFound) { + // exit if id isn't defined + if (!bundleId) return; + + var q = bundleCallbackQueue[bundleId]; + + // cache result + bundleResultCache[bundleId] = pathsNotFound; + + // exit if queue is empty + if (!q) return; + + // empty callback queue + while (q.length) { + q[0](bundleId, pathsNotFound); + q.splice(0, 1); + } +} + + +/** + * Execute callbacks. + * @param {Object or Function} args - The callback args + * @param {string[]} depsNotFound - List of dependencies not found + */ +function executeCallbacks(args, depsNotFound) { + // accept function as argument + if (args.call) args = {success: args}; + + // success and error callbacks + if (depsNotFound.length) (args.error || devnull)(depsNotFound); + else (args.success || devnull)(args); +} + + +/** + * Load individual file. + * @param {string} path - The file path + * @param {Function} callbackFn - The callback function + */ +function loadFile(path, callbackFn, args, numTries) { + var doc = document, + async = args.async, + maxTries = (args.numRetries || 0) + 1, + beforeCallbackFn = args.before || devnull, + pathStripped = path.replace(/^(css|img)!/, ''), + isCss, + e; + + numTries = numTries || 0; + + if (/(^css!|\.css$)/.test(path)) { + isCss = true; + + // css + e = doc.createElement('link'); + e.rel = 'stylesheet'; + e.href = pathStripped; //.replace(/^css!/, ''); // remove "css!" prefix + } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) { + // image + e = doc.createElement('img'); + e.src = pathStripped; + } else { + // javascript + e = doc.createElement('script'); + e.src = path; + e.async = async === undefined ? true : async; + } + + e.onload = e.onerror = e.onbeforeload = function (ev) { + var result = ev.type[0]; + + // Note: The following code isolates IE using `hideFocus` and treats empty + // stylesheets as failures to get around lack of onerror support + if (isCss && 'hideFocus' in e) { + try { + if (!e.sheet.cssText.length) result = 'e'; + } catch (x) { + // sheets objects created from load errors don't allow access to + // `cssText` (unless error is Code:18 SecurityError) + if (x.code != 18) result = 'e'; + } + } + + // handle retries in case of load failure + if (result == 'e') { + // increment counter + numTries += 1; + + // exit function and try again + if (numTries < maxTries) { + return loadFile(path, callbackFn, args, numTries); + } + } + + // execute callback + callbackFn(path, result, ev.defaultPrevented); + }; + + // add to document (unless callback returns `false`) + if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e); +} + + +/** + * Load multiple files. + * @param {string[]} paths - The file paths + * @param {Function} callbackFn - The callback function + */ +function loadFiles(paths, callbackFn, args) { + // listify paths + paths = paths.push ? paths : [paths]; + + var numWaiting = paths.length, + x = numWaiting, + pathsNotFound = [], + fn, + i; + + // define callback function + fn = function(path, result, defaultPrevented) { + // handle error + if (result == 'e') pathsNotFound.push(path); + + // handle beforeload event. If defaultPrevented then that means the load + // will be blocked (ex. Ghostery/ABP on Safari) + if (result == 'b') { + if (defaultPrevented) pathsNotFound.push(path); + else return; + } + + numWaiting--; + if (!numWaiting) callbackFn(pathsNotFound); + }; + + // load scripts + for (i=0; i < x; i++) loadFile(paths[i], fn, args); +} + + +/** + * Initiate script load and register bundle. + * @param {(string|string[])} paths - The file paths + * @param {(string|Function)} [arg1] - The bundleId or success callback + * @param {Function} [arg2] - The success or error callback + * @param {Function} [arg3] - The error callback + */ +function loadjs(paths, arg1, arg2) { + var bundleId, + args; + + // bundleId (if string) + if (arg1 && arg1.trim) bundleId = arg1; + + // args (default is {}) + args = (bundleId ? arg2 : arg1) || {}; + + // throw error if bundle is already defined + if (bundleId) { + if (bundleId in bundleIdCache) { + throw "LoadJS"; + } else { + bundleIdCache[bundleId] = true; + } + } + + // load scripts + loadFiles(paths, function (pathsNotFound) { + // execute callbacks + executeCallbacks(args, pathsNotFound); + + // publish bundle load event + publish(bundleId, pathsNotFound); + }, args); +} + + +/** + * Execute callbacks when dependencies have been satisfied. + * @param {(string|string[])} deps - List of bundle ids + * @param {Object} args - success/error arguments + */ +loadjs.ready = function ready(deps, args) { + // subscribe to bundle load event + subscribe(deps, function (depsNotFound) { + // execute callbacks + executeCallbacks(args, depsNotFound); + }); + + return loadjs; +}; + + +/** + * Manually satisfy bundle dependencies. + * @param {string} bundleId - The bundle id + */ +loadjs.done = function done(bundleId) { + publish(bundleId, []); +}; + + +/** + * Reset loadjs dependencies statuses + */ +loadjs.reset = function reset() { + bundleIdCache = {}; + bundleResultCache = {}; + bundleCallbackQueue = {}; +}; + + +/** + * Determine if bundle has already been defined + * @param String} bundleId - The bundle id + */ +loadjs.isDefined = function isDefined(bundleId) { + return bundleId in bundleIdCache; +}; + + +// export +return loadjs; + +})); +}); + +function loadScript(url) { + return new Promise(function (resolve, reject) { + loadjs_umd(url, { + success: resolve, + error: reject + }); + }); +} + +function parseId(url) { + if (is$1.empty(url)) { + return null; + } + + if (is$1.number(Number(url))) { + return url; + } + + var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; +} // Set playback state and trigger change (only on actual change) + + +function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } +} + +var vimeo = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio + + setAspectRatio.call(this); // Load the API if not already + + if (!is$1.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk).then(function () { + vimeo.ready.call(_this); + }).catch(function (error) { + _this.debug.warn('Vimeo API failed to load', error); + }); + } else { + vimeo.ready.call(this); + } + }, + // API Ready + ready: function ready$$1() { + var _this2 = this; + + var player = this; + var config = player.config.vimeo; // Get Vimeo params for the iframe + + var params = buildUrlParams(extend({}, { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative + }, config)); // Get the source URL or ID + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is$1.empty(source)) { + source = player.media.getAttribute(player.config.attributes.embed.id); + } + + var id = parseId(source); // Build an iframe + + var iframe = createElement('iframe'); + var src = format(player.config.urls.vimeo.iframe, id, params); + iframe.setAttribute('src', src); + iframe.setAttribute('allowfullscreen', ''); + iframe.setAttribute('allowtransparency', ''); + iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set + + var poster = player.poster; // Inject the package + + var wrapper = createElement('div', { + poster: poster, + class: player.config.classNames.embedContainer + }); + wrapper.appendChild(iframe); + player.media = replaceElement(wrapper, player.media); // Get poster image + + fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { + if (is$1.empty(response)) { + return; + } // Get the URL for thumbnail + + + var url = new URL(response[0].thumbnail_large); // Get original image + + url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster + + ui.setPoster.call(player, url.href).catch(function () {}); + }); // Setup instance + // https://github.com/vimeo/player.js + + player.embed = new window.Vimeo.Player(iframe, { + autopause: player.config.autopause, + muted: player.muted + }); + player.media.paused = true; + player.media.currentTime = 0; // Disable native text track rendering + + if (player.supported.ui) { + player.embed.disableTextTrack(); + } // Create a faux HTML5 API using the Vimeo API + + + player.media.play = function () { + assurePlaybackState.call(player, true); + return player.embed.play(); + }; + + player.media.pause = function () { + assurePlaybackState.call(player, false); + return player.embed.pause(); + }; + + player.media.stop = function () { + player.pause(); + player.currentTime = 0; + }; // Seeking + + + var currentTime = player.media.currentTime; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return currentTime; + }, + set: function set(time) { + // Vimeo will automatically play on seek if the video hasn't been played before + // Get current paused state and volume etc + var embed = player.embed, + media = player.media, + paused = player.paused, + volume = player.volume; + var restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event + + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete + + Promise.resolve(restorePause && embed.setVolume(0)) // Seek + .then(function () { + return embed.setCurrentTime(time); + }) // Restore paused + .then(function () { + return restorePause && embed.pause(); + }) // Restore volume + .then(function () { + return restorePause && embed.setVolume(volume); + }).catch(function () {// Do nothing + }); + } + }); // Playback speed + + var speed = player.config.speed.selected; + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return speed; + }, + set: function set(input) { + player.embed.setPlaybackRate(input).then(function () { + speed = input; + triggerEvent.call(player, player.media, 'ratechange'); + }).catch(function (error) { + // Hide menu item (and menu if empty) + if (error.name === 'Error') { + controls.setSpeedMenu.call(player, []); + } + }); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + player.embed.setVolume(input).then(function () { + volume = input; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : false; + player.embed.setVolume(toggle ? 0 : player.config.volume).then(function () { + muted = toggle; + triggerEvent.call(player, player.media, 'volumechange'); + }); + } + }); // Loop + + var loop = player.config.loop; + Object.defineProperty(player.media, 'loop', { + get: function get() { + return loop; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : player.config.loop.active; + player.embed.setLoop(toggle).then(function () { + loop = toggle; + }); + } + }); // Source + + var currentSrc; + player.embed.getVideoUrl().then(function (value) { + currentSrc = value; + controls.setDownloadLink.call(player); + }).catch(function (error) { + _this2.debug.warn(error); + }); + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return currentSrc; + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Set aspect ratio based on video size + + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(function (dimensions) { + var _dimensions = _slicedToArray(dimensions, 2), + width = _dimensions[0], + height = _dimensions[1]; + + player.embed.ratio = "".concat(width, ":").concat(height); + setAspectRatio.call(_this2, player.embed.ratio); + }); // Set autopause + + player.embed.setAutopause(player.config.autopause).then(function (state) { + player.config.autopause = state; + }); // Get title + + player.embed.getVideoTitle().then(function (title) { + player.config.title = title; + ui.setTitle.call(_this2); + }); // Get current time + + player.embed.getCurrentTime().then(function (value) { + currentTime = value; + triggerEvent.call(player, player.media, 'timeupdate'); + }); // Get duration + + player.embed.getDuration().then(function (value) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + }); // Get captions + + player.embed.getTextTracks().then(function (tracks) { + player.media.textTracks = tracks; + captions.setup.call(player); + }); + player.embed.on('cuechange', function (_ref) { + var _ref$cues = _ref.cues, + cues = _ref$cues === void 0 ? [] : _ref$cues; + var strippedCues = cues.map(function (cue) { + return stripHTML(cue.text); + }); + captions.updateCues.call(player, strippedCues); + }); + player.embed.on('loaded', function () { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(function (paused) { + assurePlaybackState.call(player, !paused); + + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); + + if (is$1.element(player.embed.element) && player.supported.ui) { + var frame = player.embed.element; // Fix keyboard focus issues + // https://github.com/sampotts/plyr/issues/317 + + frame.setAttribute('tabindex', -1); + } + }); + player.embed.on('play', function () { + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); + }); + player.embed.on('pause', function () { + assurePlaybackState.call(player, false); + }); + player.embed.on('timeupdate', function (data) { + player.media.seeking = false; + currentTime = data.seconds; + triggerEvent.call(player, player.media, 'timeupdate'); + }); + player.embed.on('progress', function (data) { + player.media.buffered = data.percent; + triggerEvent.call(player, player.media, 'progress'); // Check all loaded + + if (parseInt(data.percent, 10) === 1) { + triggerEvent.call(player, player.media, 'canplaythrough'); + } // Get duration as if we do it before load, it gives an incorrect value + // https://github.com/sampotts/plyr/issues/891 + + + player.embed.getDuration().then(function (value) { + if (value !== player.media.duration) { + player.media.duration = value; + triggerEvent.call(player, player.media, 'durationchange'); + } + }); + }); + player.embed.on('seeked', function () { + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + }); + player.embed.on('ended', function () { + player.media.paused = true; + triggerEvent.call(player, player.media, 'ended'); + }); + player.embed.on('error', function (detail) { + player.media.error = detail; + triggerEvent.call(player, player.media, 'error'); + }); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 0); + } +}; + +function parseId$1(url) { + if (is$1.empty(url)) { + return null; + } + + var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; +} // Set playback state and trigger change (only on actual change) + + +function assurePlaybackState$1(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } +} + +var youtube = { + setup: function setup() { + var _this = this; + + // Add embed class for responsive + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio + + setAspectRatio.call(this); // Setup API + + if (is$1.object(window.YT) && is$1.function(window.YT.Player)) { + youtube.ready.call(this); + } else { + // Load the API + loadScript(this.config.urls.youtube.sdk).catch(function (error) { + _this.debug.warn('YouTube API failed to load', error); + }); // Setup callback for the API + // YouTube has it's own system of course... + + window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue + + window.onYouTubeReadyCallbacks.push(function () { + youtube.ready.call(_this); + }); // Set callback to process queue + + window.onYouTubeIframeAPIReady = function () { + window.onYouTubeReadyCallbacks.forEach(function (callback) { + callback(); + }); + }; + } + }, + // Get the media title + getTitle: function getTitle(videoId) { + var _this2 = this; + + // Try via undocumented API method first + // This method disappears now and then though... + // https://github.com/sampotts/plyr/issues/709 + if (is$1.function(this.embed.getVideoData)) { + var _this$embed$getVideoD = this.embed.getVideoData(), + title = _this$embed$getVideoD.title; + + if (is$1.empty(title)) { + this.config.title = title; + ui.setTitle.call(this); + return; + } + } // Or via Google API + + + var key = this.config.keys.google; + + if (is$1.string(key) && !is$1.empty(key)) { + var url = format(this.config.urls.youtube.api, videoId, key); + fetch(url).then(function (result) { + if (is$1.object(result)) { + _this2.config.title = result.items[0].snippet.title; + ui.setTitle.call(_this2); + } + }).catch(function () {}); + } + }, + // API ready + ready: function ready$$1() { + var player = this; // Ignore already setup (race condition) + + var currentId = player.media.getAttribute('id'); + + if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) { + return; + } // Get the source URL or ID + + + var source = player.media.getAttribute('src'); // Get from <div> if needed + + if (is$1.empty(source)) { + source = player.media.getAttribute(this.config.attributes.embed.id); + } // Replace the <iframe> with a <div> due to YouTube API issues + + + var videoId = parseId$1(source); + var id = generateId(player.provider); // Get poster, if already set + + var poster = player.poster; // Replace media element + + var container = createElement('div', { + id: id, + poster: poster + }); + player.media = replaceElement(container, player.media); // Id to poster wrapper + + var posterSrc = function posterSrc(format$$1) { + return "https://img.youtube.com/vi/".concat(videoId, "/").concat(format$$1, "default.jpg"); + }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + + + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(function () { + return loadImage(posterSrc('sd'), 121); + }) // 480p padded 4:3 + .catch(function () { + return loadImage(posterSrc('hq')); + }) // 360p padded 4:3. Always exists + .then(function (image) { + return ui.setPoster.call(player, image.src); + }).then(function (posterSrc) { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }).catch(function () {}); + var config = player.config.youtube; // Setup instance + // https://developers.google.com/youtube/iframe_api_reference + + player.embed = new window.YT.Player(id, { + videoId: videoId, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend({}, { + autoplay: player.config.autoplay ? 1 : 0, + // Autoplay + hl: player.config.hl, + // iframe interface language + controls: player.supported.ui ? 0 : 1, + // Only show controls if not fully supported + disablekb: 1, + // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, + // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null + }, config), + events: { + onError: function onError(event) { + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + var code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + + var message = { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.' + }[code] || 'An unknown error occured'; + player.media.error = { + code: code, + message: message + }; + triggerEvent.call(player, player.media, 'error'); + } + }, + onPlaybackRateChange: function onPlaybackRateChange(event) { + // Get the instance + var instance = event.target; // Get current speed + + player.media.playbackRate = instance.getPlaybackRate(); + triggerEvent.call(player, player.media, 'ratechange'); + }, + onReady: function onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is$1.function(player.media.play)) { + return; + } // Get the instance + + + var instance = event.target; // Get the title + + youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API + + player.media.play = function () { + assurePlaybackState$1.call(player, true); + instance.playVideo(); + }; + + player.media.pause = function () { + assurePlaybackState$1.call(player, false); + instance.pauseVideo(); + }; + + player.media.stop = function () { + instance.stopVideo(); + }; + + player.media.duration = instance.getDuration(); + player.media.paused = true; // Seeking + + player.media.currentTime = 0; + Object.defineProperty(player.media, 'currentTime', { + get: function get() { + return Number(instance.getCurrentTime()); + }, + set: function set(time) { + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } // Set seeking state and trigger event + + + player.media.seeking = true; + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent + + instance.seekTo(time); + } + }); // Playback speed + + Object.defineProperty(player.media, 'playbackRate', { + get: function get() { + return instance.getPlaybackRate(); + }, + set: function set(input) { + instance.setPlaybackRate(input); + } + }); // Volume + + var volume = player.config.volume; + Object.defineProperty(player.media, 'volume', { + get: function get() { + return volume; + }, + set: function set(input) { + volume = input; + instance.setVolume(volume * 100); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Muted + + var muted = player.config.muted; + Object.defineProperty(player.media, 'muted', { + get: function get() { + return muted; + }, + set: function set(input) { + var toggle = is$1.boolean(input) ? input : muted; + muted = toggle; + instance[toggle ? 'mute' : 'unMute'](); + triggerEvent.call(player, player.media, 'volumechange'); + } + }); // Source + + Object.defineProperty(player.media, 'currentSrc', { + get: function get() { + return instance.getVideoUrl(); + } + }); // Ended + + Object.defineProperty(player.media, 'ended', { + get: function get() { + return player.currentTime === player.duration; + } + }); // Get available speeds + + player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe + + if (player.supported.ui) { + player.media.setAttribute('tabindex', -1); + } + + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer + + clearInterval(player.timers.buffering); // Setup buffering + + player.timers.buffering = setInterval(function () { + // Get loaded % from YouTube + player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something + + if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { + triggerEvent.call(player, player.media, 'progress'); + } // Set last buffer point + + + player.media.lastBuffered = player.media.buffered; // Bail if we're at 100% + + if (player.media.buffered === 1) { + clearInterval(player.timers.buffering); // Trigger event + + triggerEvent.call(player, player.media, 'canplaythrough'); + } + }, 200); // Rebuild UI + + setTimeout(function () { + return ui.build.call(player); + }, 50); + }, + onStateChange: function onStateChange(event) { + // Get the instance + var instance = event.target; // Reset timer + + clearInterval(player.timers.playing); + var seeked = player.media.seeking && [1, 2].includes(event.data); + + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } // Handle events + // -1 Unstarted + // 0 Ended + // 1 Playing + // 2 Paused + // 3 Buffering + // 5 Video cued + + + switch (event.data) { + case -1: + // Update scrubber + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube + + player.media.buffered = instance.getVideoLoadedFraction(); + triggerEvent.call(player, player.media, 'progress'); + break; + + case 0: + assurePlaybackState$1.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. + + if (player.media.loop) { + // YouTube needs a call to `stopVideo` before playing again + instance.stopVideo(); + instance.playVideo(); + } else { + triggerEvent.call(player, player.media, 'ended'); + } + + break; + + case 1: + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState$1.call(player, true); + triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress + + player.timers.playing = setInterval(function () { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + triggerEvent.call(player, player.media, 'durationchange'); + } + } + + break; + + case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } + + assurePlaybackState$1.call(player, false); + break; + + default: + break; + } + + triggerEvent.call(player, player.elements.container, 'statechange', false, { + code: event.data + }); + } + } + }); + } +}; + +var media = { + // Setup media + setup: function setup() { + // If there's no media, bail + if (!this.media) { + this.debug.warn('No media element found!'); + return; + } // Add type class + + + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class + + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds + // This will require changes if audio embeds are added + + if (this.isEmbed) { + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + } // Inject the player wrapper + + + if (this.isVideo) { + // Create the wrapper div + this.elements.wrapper = createElement('div', { + class: this.config.classNames.video + }); // Wrap the video in a container + + wrap(this.media, this.elements.wrapper); // Faux poster container + + this.elements.poster = createElement('div', { + class: this.config.classNames.poster + }); + this.elements.wrapper.appendChild(this.elements.poster); + } + + if (this.isHTML5) { + html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); + } + } +}; + +var Ads = +/*#__PURE__*/ +function () { + /** + * Ads constructor. + * @param {object} player + * @return {Ads} + */ + function Ads(player) { + var _this = this; + + _classCallCheck(this, Ads); + + this.player = player; + this.config = player.config.ads; + this.playing = false; + this.initialized = false; + this.elements = { + container: null, + displayContainer: null + }; + this.manager = null; + this.loader = null; + this.cuePoints = null; + this.events = {}; + this.safetyTimer = null; + this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready + + this.managerPromise = new Promise(function (resolve, reject) { + // The ad is loaded and ready + _this.on('loaded', resolve); // Ads failed + + + _this.on('error', reject); + }); + this.load(); + } + + _createClass(Ads, [{ + key: "load", + + /** + * Load the IMA SDK + */ + value: function load() { + var _this2 = this; + + if (this.enabled) { + // Check if the Google IMA3 SDK is loaded or load it ourselves + if (!is$1.object(window.google) || !is$1.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); + } + } + } + /** + * Get the ads instance ready + */ + + }, { + key: "ready", + value: function ready$$1() { + var _this3 = this; + + // Start ticking our safety timer. If the whole advertisement + // thing doesn't resolve within our set time; we bail + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer + + this.managerPromise.then(function () { + _this3.clearSafetyTimer('onAdsManagerLoaded()'); + }); // Set listeners on the Plyr instance + + this.listeners(); // Setup the IMA SDK + + this.setupIMA(); + } // Build the tag URL + + }, { + key: "setupIMA", + + /** + * In order for the SDK to display ads for our video, we need to tell it where to put them, + * so here we define our ad container. This div is set up to render on top of the video player. + * Using the code below, we tell the SDK to render ads within that div. We also provide a + * handle to the content video player - the SDK will poll the current time of our player to + * properly place mid-rolls. After we create the ad display container, we initialize it. On + * mobile devices, this initialization is done as the result of a user action. + */ + value: function setupIMA() { + // Create the container for our advertisements + this.elements.container = createElement('div', { + class: this.player.config.classNames.ads + }); + this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2 + + google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language + + google.ima.settings.setLocale(this.player.config.ads.language); // We assume the adContainer is the video container of the plyr element + // that will house the ads + + this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container); // Request video ads to be pre-loaded + + this.requestAds(); + } + /** + * Request advertisements + */ + + }, { + key: "requestAds", + value: function requestAds() { + var _this4 = this; + + var container = this.player.elements.container; + + try { + // Create ads loader + this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events + + this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) { + return _this4.onAdsManagerLoaded(event); + }, false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this4.onAdError(error); + }, false); // Request video ads + + var request = new google.ima.AdsRequest(); + request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK + // to select the correct creative if multiple are returned + + request.linearAdSlotWidth = container.offsetWidth; + request.linearAdSlotHeight = container.offsetHeight; + request.nonLinearAdSlotWidth = container.offsetWidth; + request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video. + + request.forceNonLinearFullSlot = false; // Mute based on current state + + request.setAdWillPlayMuted(!this.player.muted); + this.loader.requestAds(request); + } catch (e) { + this.onAdError(e); + } + } + /** + * Update the ad countdown + * @param {boolean} start + */ + + }, { + key: "pollCountdown", + value: function pollCountdown() { + var _this5 = this; + + var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (!start) { + clearInterval(this.countdownTimer); + this.elements.container.removeAttribute('data-badge-text'); + return; + } + + var update = function update() { + var time = formatTime(Math.max(_this5.manager.getRemainingTime(), 0)); + var label = "".concat(i18n.get('advertisement', _this5.player.config), " - ").concat(time); + + _this5.elements.container.setAttribute('data-badge-text', label); + }; + + this.countdownTimer = setInterval(update, 100); + } + /** + * This method is called whenever the ads are ready inside the AdDisplayContainer + * @param {Event} adsManagerLoadedEvent + */ + + }, { + key: "onAdsManagerLoaded", + value: function onAdsManagerLoaded(event) { + var _this6 = this; + + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } // Get the ads manager + + + var settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf + + settings.restoreCustomPlaybackStateOnAdBreakComplete = true; + settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration + // so it can determine when to start the mid- and post-roll + + this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll + + this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available + + if (!is$1.empty(this.cuePoints)) { + this.cuePoints.forEach(function (cuePoint) { + if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < _this6.player.duration) { + var seekElement = _this6.player.elements.progress; + + if (is$1.element(seekElement)) { + var cuePercentage = 100 / _this6.player.duration * cuePoint; + var cue = createElement('span', { + class: _this6.player.config.classNames.cues + }); + cue.style.left = "".concat(cuePercentage.toString(), "%"); + seekElement.appendChild(cue); + } + } + }); + } // Set volume to match player + + + this.manager.setVolume(this.player.volume); // Add listeners to the required events + // Advertisement error events + + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { + return _this6.onAdError(error); + }); // Advertisement regular events + + Object.keys(google.ima.AdEvent.Type).forEach(function (type) { + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { + return _this6.onAdEvent(event); + }); + }); // Resolve our adsManager + + this.trigger('loaded'); + } + /** + * This is where all the event handling takes place. Retrieve the ad from the event. Some + * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated + * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type + * @param {Event} event + */ + + }, { + key: "onAdEvent", + value: function onAdEvent(event) { + var _this7 = this; + + var container = this.player.elements.container; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) + // don't have ad object associated + + var ad = event.getAd(); + var adData = event.getAdData(); // Proxy event + + var dispatchEvent = function dispatchEvent(type) { + var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); + triggerEvent.call(_this7.player, _this7.player.media, event); + }; + + switch (event.type) { + case google.ima.AdEvent.Type.LOADED: + // This is the first event sent for an ad - it is possible to determine whether the + // ad is a video ad or an overlay + this.trigger('loaded'); // Bubble event + + dispatchEvent(event.type); // Start countdown + + this.pollCountdown(true); + + if (!ad.isLinear()) { + // Position AdDisplayContainer correctly for overlay + ad.width = container.offsetWidth; + ad.height = container.offsetHeight; + } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex()); + // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset()); + + + break; + + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: + // All ads for the current videos are done. We can now request new advertisements + // in case the video is re-played + // Fire event + dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // So here we load a new video when all ads are done. + // Then we load new ads within a new adsManager. When the video + // Is started - after - the ads are loaded, then we get ads. + // You can also easily test cancelling and reloading by running + // player.ads.cancel() and player.ads.play from the console I guess. + // this.player.source = { + // type: 'video', + // title: 'View From A Blue Moon', + // sources: [{ + // src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type: + // 'video/mp4', }], poster: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks: + // [ { kind: 'captions', label: 'English', srclang: 'en', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt', + // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src: + // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ], + // }; + // TODO: So there is still this thing where a video should only be allowed to start + // playing when the IMA SDK is ready or has failed + + this.loadAds(); + break; + + case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: + // This event indicates the ad has started - the video player can adjust the UI, + // for example display a pause button and remaining time. Fired when content should + // be paused. This usually happens right before an ad is about to cover the content + dispatchEvent(event.type); + this.pauseContent(); + break; + + case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: + // This event indicates the ad has finished - the video player can perform + // appropriate UI actions, such as removing the timer for remaining time detection. + // Fired when content should be resumed. This usually happens when an ad finishes + // or collapses + dispatchEvent(event.type); + this.pollCountdown(); + this.resumeContent(); + break; + + case google.ima.AdEvent.Type.STARTED: + case google.ima.AdEvent.Type.MIDPOINT: + case google.ima.AdEvent.Type.COMPLETE: + case google.ima.AdEvent.Type.IMPRESSION: + case google.ima.AdEvent.Type.CLICK: + dispatchEvent(event.type); + break; + + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); + } + + break; + + default: + break; + } + } + /** + * Any ad error handling comes through here + * @param {Event} event + */ + + }, { + key: "onAdError", + value: function onAdError(event) { + this.cancel(); + this.player.debug.warn('Ads error', event); + } + /** + * Setup hooks for Plyr and window events. This ensures + * the mid- and post-roll launch at the correct time. And + * resize the advertisement when the player resizes + */ + + }, { + key: "listeners", + value: function listeners() { + var _this8 = this; + + var container = this.player.elements.container; + var time; // Add listeners to the required events + + this.player.on('ended', function () { + _this8.loader.contentComplete(); + }); + this.player.on('timeupdate', function () { + time = _this8.player.currentTime; + }); + this.player.on('seeked', function () { + var seekedTime = _this8.player.currentTime; + + if (is$1.empty(_this8.cuePoints)) { + return; + } + + _this8.cuePoints.forEach(function (cuePoint, index) { + if (time < cuePoint && cuePoint < seekedTime) { + _this8.manager.discardAdBreak(); + + _this8.cuePoints.splice(index, 1); + } + }); + }); // Listen to the resizing of the window. And resize ad accordingly + // TODO: eventually implement ResizeObserver + + window.addEventListener('resize', function () { + if (_this8.manager) { + _this8.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); + } + }); + } + /** + * Initialize the adsManager and start playing advertisements + */ + + }, { + key: "play", + value: function play() { + var _this9 = this; + + var container = this.player.elements.container; + + if (!this.managerPromise) { + this.resumeContent(); + } // Play the requested advertisement whenever the adsManager is ready + + + this.managerPromise.then(function () { + // Initialize the container. Must be done via a user action on mobile devices + _this9.elements.displayContainer.initialize(); + + try { + if (!_this9.initialized) { + // Initialize the ads manager. Ad rules playlist will start at this time + _this9.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will + // start at this time; the call will be ignored for ad rules + + + _this9.manager.start(); + } + + _this9.initialized = true; + } catch (adError) { + // An error may be thrown if there was a problem with the + // VAST response + _this9.onAdError(adError); + } + }).catch(function () {}); + } + /** + * Resume our video + */ + + }, { + key: "resumeContent", + value: function resumeContent() { + // Hide the advertisement container + this.elements.container.style.zIndex = ''; // Ad is stopped + + this.playing = false; // Play our video + + if (this.player.currentTime < this.player.duration) { + this.player.play(); + } + } + /** + * Pause our video + */ + + }, { + key: "pauseContent", + value: function pauseContent() { + // Show the advertisement container + this.elements.container.style.zIndex = 3; // Ad is playing. + + this.playing = true; // Pause our video. + + this.player.pause(); + } + /** + * Destroy the adsManager so we can grab new ads after this. If we don't then we're not + * allowed to call new ads based on google policies, as they interpret this as an accidental + * video requests. https://developers.google.com/interactive- + * media-ads/docs/sdks/android/faq#8 + */ + + }, { + key: "cancel", + value: function cancel() { + // Pause our video + if (this.initialized) { + this.resumeContent(); + } // Tell our instance that we're done for now + + + this.trigger('error'); // Re-create our adsManager + + this.loadAds(); + } + /** + * Re-create our adsManager + */ + + }, { + key: "loadAds", + value: function loadAds() { + var _this10 = this; + + // Tell our adsManager to go bye bye + this.managerPromise.then(function () { + // Destroy our adsManager + if (_this10.manager) { + _this10.manager.destroy(); + } // Re-set our adsManager promises + + + _this10.managerPromise = new Promise(function (resolve) { + _this10.on('loaded', resolve); + + _this10.player.debug.log(_this10.manager); + }); // Now request some new advertisements + + _this10.requestAds(); + }).catch(function () {}); + } + /** + * Handles callbacks after an ad event was invoked + * @param {string} event - Event type + */ + + }, { + key: "trigger", + value: function trigger(event) { + var _this11 = this; + + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var handlers = this.events[event]; + + if (is$1.array(handlers)) { + handlers.forEach(function (handler) { + if (is$1.function(handler)) { + handler.apply(_this11, args); + } + }); + } + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + * @return {Ads} + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + if (!is$1.array(this.events[event])) { + this.events[event] = []; + } + + this.events[event].push(callback); + return this; + } + /** + * Setup a safety timer for when the ad network doesn't respond for whatever reason. + * The advertisement has 12 seconds to get its things together. We stop this timer when the + * advertisement is playing, or when a user action is required to start, then we clear the + * timer on ad ready + * @param {number} time + * @param {string} from + */ + + }, { + key: "startSafetyTimer", + value: function startSafetyTimer(time, from) { + var _this12 = this; + + this.player.debug.log("Safety timer invoked from: ".concat(from)); + this.safetyTimer = setTimeout(function () { + _this12.cancel(); + + _this12.clearSafetyTimer('startSafetyTimer()'); + }, time); + } + /** + * Clear our safety timer(s) + * @param {string} from + */ + + }, { + key: "clearSafetyTimer", + value: function clearSafetyTimer(from) { + if (!is$1.nullOrUndefined(this.safetyTimer)) { + this.player.debug.log("Safety timer cleared from: ".concat(from)); + clearTimeout(this.safetyTimer); + this.safetyTimer = null; + } + } + }, { + key: "enabled", + get: function get() { + var config = this.config; + return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is$1.empty(config.publisherId) || is$1.url(config.tagUrl)); + } + }, { + key: "tagUrl", + get: function get() { + var config = this.config; + + if (is$1.url(config.tagUrl)) { + return config.tagUrl; + } + + var params = { + AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', + AV_CHANNELID: '5a0458dc28a06145e4519d21', + AV_URL: window.location.hostname, + cb: Date.now(), + AV_WIDTH: 640, + AV_HEIGHT: 480, + AV_CDIM2: this.publisherId + }; + var base = 'https://go.aniview.com/api/adserver6/vast/'; + return "".concat(base, "?").concat(buildUrlParams(params)); + } + }]); + + return Ads; +}(); + +// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined) + +var $find$1 = _arrayMethods(6); +var KEY$1 = 'findIndex'; +var forced$1 = true; +// Shouldn't skip holes +if (KEY$1 in []) Array(1)[KEY$1](function () { forced$1 = false; }); +_export(_export.P + _export.F * forced$1, 'Array', { + findIndex: function findIndex(callbackfn /* , that = undefined */) { + return $find$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); +_addToUnscopables(KEY$1); + +var parseVtt = function parseVtt(vttDataString) { + var processedList = []; + var frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + frames.forEach(function (frame) { + var result = {}; + var lines = frame.split(/\r\n|\n|\r/); + lines.forEach(function (line) { + if (!is$1.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + var matchTimes = line.match(/([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = Number(matchTimes[1]) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number("0.".concat(matchTimes[4])); + result.endTime = Number(matchTimes[6]) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number("0.".concat(matchTimes[9])); + } + } else if (!is$1.empty(line.trim()) && is$1.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + var lineSplit = line.trim().split('#xywh='); + + var _lineSplit = _slicedToArray(lineSplit, 1); + + result.text = _lineSplit[0]; + + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + var _lineSplit$1$split = lineSplit[1].split(','); + + var _lineSplit$1$split2 = _slicedToArray(_lineSplit$1$split, 4); + + result.x = _lineSplit$1$split2[0]; + result.y = _lineSplit$1$split2[1]; + result.w = _lineSplit$1$split2[2]; + result.h = _lineSplit$1$split2[3]; + } + } + }); + + if (result.text) { + processedList.push(result); + } + }); + return processedList; +}; +/** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + + +var PreviewThumbnails = +/*#__PURE__*/ +function () { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + function PreviewThumbnails(player) { + _classCallCheck(this, PreviewThumbnails); + + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + this.elements = { + thumb: {}, + scrubbing: {} + }; + this.load(); + } + + _createClass(PreviewThumbnails, [{ + key: "load", + value: function load() { + var _this = this; + + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; + } + + if (!this.enabled) { + return; + } + + this.getThumbnails().then(function () { + // Render DOM elements + _this.render(); // Check to see if thumb container size was specified manually in CSS + + + _this.determineContainerAutoSizing(); + + _this.loaded = true; + }); + } // Download VTT files and parse them + + }, { + key: "getThumbnails", + value: function getThumbnails() { + var _this2 = this; + + return new Promise(function (resolve) { + var src = _this2.player.config.previewThumbnails.src; + + if (is$1.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } // If string, convert into single-element list + + + var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails + + var promises = urls.map(function (u) { + return _this2.getThumbnail(u); + }); + Promise.all(promises).then(function () { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + _this2.thumbnails.sort(function (x, y) { + return x.height - y.height; + }); + + _this2.player.debug.log('Preview thumbnails', _this2.thumbnails); + + resolve(); + }); + }); + } // Process individual VTT file + + }, { + key: "getThumbnail", + value: function getThumbnail(url) { + var _this3 = this; + + return new Promise(function (resolve) { + fetch(url).then(function (response) { + var thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '' + }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank + + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } // Download the first frame, so that we can determine/set the height of this thumbnailsDef + + + var tempImage = new Image(); + + tempImage.onload = function () { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; + + _this3.thumbnails.push(thumbnail); + + resolve(); + }; + + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } + }, { + key: "startMove", + value: function startMove(event) { + if (!this.loaded) { + return; + } + + if (!is$1.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } // Wait until media has a duration + + + if (!this.player.media.duration) { + return; + } + + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + var clientRect = this.player.elements.progress.getBoundingClientRect(); + var percentage = 100 / clientRect.width * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); + + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } + + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } + + this.mousePosX = event.pageX; // Set time text inside image container + + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } // Download and show image + + + this.showImageAtCurrentTime(); + } + }, { + key: "endMove", + value: function endMove() { + this.toggleThumbContainer(false, true); + } + }, { + key: "startScrubbing", + value: function startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; // Wait until media has a duration + + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); // Download and show image + + this.showImageAtCurrentTime(); + } + } + } + }, { + key: "finishScrubbing", + value: function finishScrubbing() { + var _this4 = this; + + this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview + + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', function () { + // Re-check mousedown - we might have already started scrubbing again + if (!_this4.mouseDown) { + _this4.toggleScrubbingContainer(false); + } + }); + } + } + /** + * Setup hooks for Plyr and window events + */ + + }, { + key: "listeners", + value: function listeners() { + var _this5 = this; + + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', function () { + _this5.toggleThumbContainer(false, true); + }); + this.player.on('seeked', function () { + _this5.toggleThumbContainer(false); + }); + this.player.on('timeupdate', function () { + _this5.lastTime = _this5.player.media.currentTime; + }); + } + /** + * Create HTML elements for image containers + */ + + }, { + key: "render", + value: function render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer + }); // Wrapper for the image for styling + + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00) + + var timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer + }); + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb + + this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container + + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer + }); + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + }, { + key: "showImageAtCurrentTime", + value: function showImageAtCurrentTime() { + var _this6 = this; + + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null + + + var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) { + return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime; + }); + var hasThumb = thumbNum >= 0; + var qualityIndex = 0; + this.toggleThumbContainer(hasThumb); // No matching thumb found + + if (!hasThumb) { + return; + } // Check to see if we've already downloaded higher quality versions of this image + + + this.thumbnails.forEach(function (thumbnail, index) { + if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); // Only proceed if either thumbnum or thumbfilename has changed + + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); + } + } // Show the image that's currently specified in this.showingThumb + + }, { + key: "loadImage", + value: function loadImage() { + var _this7 = this; + + var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var thumbNum = this.showingThumb; + var thumbnail = this.thumbnails[qualityIndex]; + var urlPrefix = thumbnail.urlPrefix; + var frame = thumbnail.frames[thumbNum]; + var thumbFilename = thumbnail.frames[thumbNum].text; + var thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + + + var previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + + previewImage.onload = function () { + return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + }; + + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); + } + } + }, { + key: "showImage", + value: function showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename) { + var newImage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this.player.debug.log("Showing thumb: ".concat(thumbFilename, ". num: ").concat(thumbNum, ". qual: ").concat(qualityIndex, ". newimg: ").concat(newImage)); + this.setImageSizeAndOffset(previewImage, frame); + + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; + + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading + + + this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } // Remove all preview images that aren't the designated current image + + }, { + key: "removeOldImages", + value: function removeOldImages(currentImage) { + var _this8 = this; + + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(function (image) { + if (image.tagName.toLowerCase() !== 'img') { + return; + } + + var removeDelay = _this8.usingSprites ? 500 : 1000; + + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub + + var currentImageContainer = _this8.currentImageContainer; + setTimeout(function () { + currentImageContainer.removeChild(image); + + _this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename)); + }, removeDelay); + } + }); + } // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality + + }, { + key: "preloadNearby", + value: function preloadNearby(thumbNum) { + var _this9 = this; + + var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return new Promise(function (resolve) { + setTimeout(function () { + var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text; + + if (_this9.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + var thumbnailsClone; + + if (forward) { + thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } + + var foundOne = false; + thumbnailsClone.forEach(function (frame) { + var newThumbFilename = frame.text; + + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!_this9.loadedImages.includes(newThumbFilename)) { + foundOne = true; + + _this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename)); + + var urlPrefix = _this9.thumbnails[0].urlPrefix; + var thumbURL = urlPrefix + newThumbFilename; + var previewImage = new Image(); + previewImage.src = thumbURL; + + previewImage.onload = function () { + _this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename)); + + if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded + + resolve(); + }; + } + } + }); // If there are none to preload then we want to resolve immediately + + if (!foundOne) { + resolve(); + } + } + }, 300); + }); + } // If user has been hovering current image for half a second, look for a higher quality one + + }, { + key: "getHigherQuality", + value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + var _this10 = this; + + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + var previewImageHeight = previewImage.naturalHeight; + + if (this.usingSprites) { + previewImageHeight = frame.h; + } + + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(function () { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (_this10.showingThumbFilename === thumbFilename) { + _this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename)); + + _this10.loadImage(currentQualityIndex + 1); + } + }, 300); + } + } + } + }, { + key: "toggleThumbContainer", + value: function toggleThumbContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var clearShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); + + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "toggleScrubbingContainer", + value: function toggleScrubbingContainer() { + var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); + + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + }, { + key: "determineContainerAutoSizing", + value: function determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS + + }, { + key: "setThumbContainerSizeAndPos", + value: function setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px"); + this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px"); + } + + this.setThumbContainerPos(); + } + }, { + key: "setThumbContainerPos", + value: function setThumbContainerPos() { + var seekbarRect = this.player.elements.progress.getBoundingClientRect(); + var plyrRect = this.player.elements.container.getBoundingClientRect(); + var container = this.elements.thumb.container; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container + + var minVal = plyrRect.left - seekbarRect.left + 10; + var maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth + + var previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; + + if (previewPos < minVal) { + previewPos = minVal; + } + + if (previewPos > maxVal) { + previewPos = maxVal; + } + + container.style.left = "".concat(previewPos, "px"); + } // Can't use 100% width, in case the video is a different aspect ratio to the video container + + }, { + key: "setScrubbingContainerSize", + value: function setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below + + this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px"); + } // Sprites need to be offset to the correct location + + }, { + key: "setImageSizeAndOffset", + value: function setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } // Find difference between height and preview container height + + + var multiplier = this.thumbContainerHeight / frame.h; + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); + } + }, { + key: "enabled", + get: function get() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + }, { + key: "currentImageContainer", + get: function get() { + if (this.mouseDown) { + return this.elements.scrubbing.container; + } + + return this.elements.thumb.imageContainer; + } + }, { + key: "usingSprites", + get: function get() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } + }, { + key: "thumbAspectRatio", + get: function get() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; + } + + return this.thumbnails[0].width / this.thumbnails[0].height; + } + }, { + key: "thumbContainerHeight", + get: function get() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); + } + + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + }, { + key: "currentImageElement", + get: function get() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } + + return this.currentThumbnailImageElement; + }, + set: function set(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; + } + } + }]); + + return PreviewThumbnails; +}(); + +var source = { + // Add elements to HTML5 media (source, tracks, etc) + insertElements: function insertElements(type, attributes) { + var _this = this; + + if (is$1.string(attributes)) { + insertElement(type, this.media, { + src: attributes + }); + } else if (is$1.array(attributes)) { + attributes.forEach(function (attribute) { + insertElement(type, _this.media, attribute); + }); + } + }, + // Update source + // Sources are not checked for support so be careful + change: function change(input) { + var _this2 = this; + + if (!getDeep(input, 'sources.length')) { + this.debug.warn('Invalid source format'); + return; + } // Cancel current network requests + + + html5.cancelRequests.call(this); // Destroy instance and re-setup + + this.destroy.call(this, function () { + // Reset quality options + _this2.options.quality = []; // Remove elements + + removeElement(_this2.media); + _this2.media = null; // Reset class name + + if (is$1.element(_this2.elements.container)) { + _this2.elements.container.removeAttribute('class'); + } // Set the type and provider + + + var sources = input.sources, + type = input.type; + + var _sources = _slicedToArray(sources, 1), + _sources$ = _sources[0], + _sources$$provider = _sources$.provider, + provider = _sources$$provider === void 0 ? providers.html5 : _sources$$provider, + src = _sources$.src; + + var tagName = provider === 'html5' ? type : 'div'; + var attributes = provider === 'html5' ? {} : { + src: src + }; + Object.assign(_this2, { + provider: provider, + type: type, + // Check for support + supported: support.check(type, provider, _this2.config.playsinline), + // Create new element + media: createElement(tagName, attributes) + }); // Inject the new element + + _this2.elements.container.appendChild(_this2.media); // Autoplay the new source? + + + if (is$1.boolean(input.autoplay)) { + _this2.config.autoplay = input.autoplay; + } // Set attributes for audio and video + + + if (_this2.isHTML5) { + if (_this2.config.crossorigin) { + _this2.media.setAttribute('crossorigin', ''); + } + + if (_this2.config.autoplay) { + _this2.media.setAttribute('autoplay', ''); + } + + if (!is$1.empty(input.poster)) { + _this2.poster = input.poster; + } + + if (_this2.config.loop.active) { + _this2.media.setAttribute('loop', ''); + } + + if (_this2.config.muted) { + _this2.media.setAttribute('muted', ''); + } + + if (_this2.config.playsinline) { + _this2.media.setAttribute('playsinline', ''); + } + } // Restore class hook + + + ui.addStyleHook.call(_this2); // Set new sources for html5 + + if (_this2.isHTML5) { + source.insertElements.call(_this2, 'source', sources); + } // Set video title + + + _this2.config.title = input.title; // Set up from scratch + + media.setup.call(_this2); // HTML5 stuff + + if (_this2.isHTML5) { + // Setup captions + if (Object.keys(input).includes('tracks')) { + source.insertElements.call(_this2, 'track', input.tracks); + } + } // If HTML5 or embed but not fully supported, setupInterface and call ready now + + + if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) { + // Setup interface + ui.build.call(_this2); + } // Load HTML5 sources + + + if (_this2.isHTML5) { + _this2.media.load(); + } // Reload thumbnails + + + if (_this2.previewThumbnails) { + _this2.previewThumbnails.load(); + } // Update the fullscreen support + + + _this2.fullscreen.update(); + }, true); + } +}; + +// TODO: Use a WeakMap for private globals +// const globals = new WeakMap(); +// Plyr instance + +var Plyr = +/*#__PURE__*/ +function () { + function Plyr(target, options) { + var _this = this; + + _classCallCheck(this, Plyr); + + this.timers = {}; // State + + this.ready = false; + this.loading = false; + this.failed = false; // Touch device + + this.touch = support.touch; // Set the media element + + this.media = target; // String selector passed + + if (is$1.string(this.media)) { + this.media = document.querySelectorAll(this.media); + } // jQuery, NodeList or Array passed, use first element + + + if (window.jQuery && this.media instanceof jQuery || is$1.nodeList(this.media) || is$1.array(this.media)) { + // eslint-disable-next-line + this.media = this.media[0]; + } // Set config + + + this.config = extend({}, defaults, Plyr.defaults, options || {}, function () { + try { + return JSON.parse(_this.media.getAttribute('data-plyr-config')); + } catch (e) { + return {}; + } + }()); // Elements cache + + this.elements = { + container: null, + captions: null, + buttons: {}, + display: {}, + progress: {}, + inputs: {}, + settings: { + popup: null, + menu: null, + panels: {}, + buttons: {} + } + }; // Captions + + this.captions = { + active: null, + currentTrack: -1, + meta: new WeakMap() + }; // Fullscreen + + this.fullscreen = { + active: false + }; // Options + + this.options = { + speed: [], + quality: [] + }; // Debugging + // TODO: move to globals + + this.debug = new Console(this.config.debug); // Log config options and support + + this.debug.log('Config', this.config); + this.debug.log('Support', support); // We need an element to setup + + if (is$1.nullOrUndefined(this.media) || !is$1.element(this.media)) { + this.debug.error('Setup failed: no suitable element passed'); + return; + } // Bail if the element is initialized + + + if (this.media.plyr) { + this.debug.warn('Target already setup'); + return; + } // Bail if not enabled + + + if (!this.config.enabled) { + this.debug.error('Setup failed: disabled by config'); + return; + } // Bail if disabled or no basic support + // You may want to disable certain UAs etc + + + if (!support.check().api) { + this.debug.error('Setup failed: no support'); + return; + } // Cache original element state for .destroy() + + + var clone = this.media.cloneNode(true); + clone.autoplay = false; + this.elements.original = clone; // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube + + var type = this.media.tagName.toLowerCase(); // Embed properties + + var iframe = null; + var url = null; // Different setup based on type + + switch (type) { + case 'div': + // Find the frame + iframe = this.media.querySelector('iframe'); // <iframe> type + + if (is$1.element(iframe)) { + // Detect provider + url = parseUrl(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements + + this.elements.container = this.media; + this.media = iframe; // Reset classname + + this.elements.container.className = ''; // Get attributes from URL and set config + + if (url.search.length) { + var truthy = ['1', 'true']; + + if (truthy.includes(url.searchParams.get('autoplay'))) { + this.config.autoplay = true; + } + + if (truthy.includes(url.searchParams.get('loop'))) { + this.config.loop.active = true; + } // TODO: replace fullscreen.iosNative with this playsinline config option + // YouTube requires the playsinline in the URL + + + if (this.isYouTube) { + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? + } else { + this.config.playsinline = true; + } + } + } else { + // <div> with attributes + this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute + + this.media.removeAttribute(this.config.attributes.embed.provider); + } // Unsupported or missing provider + + + if (is$1.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + this.debug.error('Setup failed: Invalid provider'); + return; + } // Audio will come later for external providers + + + this.type = types.video; + break; + + case 'video': + case 'audio': + this.type = type; + this.provider = providers.html5; // Get config from attributes + + if (this.media.hasAttribute('crossorigin')) { + this.config.crossorigin = true; + } + + if (this.media.hasAttribute('autoplay')) { + this.config.autoplay = true; + } + + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { + this.config.playsinline = true; + } + + if (this.media.hasAttribute('muted')) { + this.config.muted = true; + } + + if (this.media.hasAttribute('loop')) { + this.config.loop.active = true; + } + + break; + + default: + this.debug.error('Setup failed: unsupported type'); + return; + } // Check for support again but with type + + + this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail + + if (!this.supported.api) { + this.debug.error('Setup failed: no support'); + return; + } + + this.eventListeners = []; // Create listeners + + this.listeners = new Listeners(this); // Setup local storage for user settings + + this.storage = new Storage(this); // Store reference + + this.media.plyr = this; // Wrap media + + if (!is$1.element(this.elements.container)) { + this.elements.container = createElement('div', { + tabindex: 0 + }); + wrap(this.media, this.elements.container); + } // Add style hook + + + ui.addStyleHook.call(this); // Setup media + + media.setup.call(this); // Listen for events if debugging + + if (this.config.debug) { + on.call(this, this.elements.container, this.config.events.join(' '), function (event) { + _this.debug.log("event: ".concat(event.type)); + }); + } // Setup interface + // If embed but not fully supported, build interface now to avoid flash of controls + + + if (this.isHTML5 || this.isEmbed && !this.supported.ui) { + ui.build.call(this); + } // Container listeners + + + this.listeners.container(); // Global listeners + + this.listeners.global(); // Setup fullscreen + + this.fullscreen = new Fullscreen(this); // Setup ads if provided + + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required + + + if (this.config.autoplay) { + this.play(); + } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek + + + this.lastSeekTime = 0; // Setup preview thumbnails if enabled + + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } + } // --------------------------------------- + // API + // --------------------------------------- + + /** + * Types and provider helpers + */ + + + _createClass(Plyr, [{ + key: "play", + + /** + * Play the media, or play the advertisement (if they are not blocked) + */ + value: function play() { + if (!is$1.function(this.media.play)) { + return null; + } // Return the promise (for HTML5) + + + return this.media.play(); + } + /** + * Pause the media + */ + + }, { + key: "pause", + value: function pause() { + if (!this.playing || !is$1.function(this.media.pause)) { + return; + } + + this.media.pause(); + } + /** + * Get playing state + */ + + }, { + key: "togglePlay", + + /** + * Toggle playback based on current status + * @param {boolean} input + */ + value: function togglePlay(input) { + // Toggle based on current state if nothing passed + var toggle = is$1.boolean(input) ? input : !this.playing; + + if (toggle) { + this.play(); + } else { + this.pause(); + } + } + /** + * Stop playback + */ + + }, { + key: "stop", + value: function stop() { + if (this.isHTML5) { + this.pause(); + this.restart(); + } else if (is$1.function(this.media.stop)) { + this.media.stop(); + } + } + /** + * Restart playback + */ + + }, { + key: "restart", + value: function restart() { + this.currentTime = 0; + } + /** + * Rewind + * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime + */ + + }, { + key: "rewind", + value: function rewind(seekTime) { + this.currentTime = this.currentTime - (is$1.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Fast forward + * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime + */ + + }, { + key: "forward", + value: function forward(seekTime) { + this.currentTime = this.currentTime + (is$1.number(seekTime) ? seekTime : this.config.seekTime); + } + /** + * Seek to a time + * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) + */ + + }, { + key: "increaseVolume", + + /** + * Increase volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + value: function increaseVolume(step) { + var volume = this.media.muted ? 0 : this.volume; + this.volume = volume + (is$1.number(step) ? step : 0); + } + /** + * Decrease volume + * @param {boolean} step - How much to decrease by (between 0 and 1) + */ + + }, { + key: "decreaseVolume", + value: function decreaseVolume(step) { + this.increaseVolume(-step); + } + /** + * Set muted state + * @param {boolean} mute + */ + + }, { + key: "toggleCaptions", + + /** + * Toggle captions + * @param {boolean} input - Whether to enable captions + */ + value: function toggleCaptions(input) { + captions.toggle.call(this, input, false); + } + /** + * Set the caption track by index + * @param {number} - Caption index + */ + + }, { + key: "airplay", + + /** + * Trigger the airplay dialog + * TODO: update player with state, support, enabled + */ + value: function airplay() { + // Show dialog if supported + if (support.airplay) { + this.media.webkitShowPlaybackTargetPicker(); + } + } + /** + * Toggle the player controls + * @param {boolean} [toggle] - Whether to show the controls + */ + + }, { + key: "toggleControls", + value: function toggleControls(toggle) { + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + var isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls + + var force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state + + var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu + + if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); + } // Trigger event on change + + + if (hiding !== isHidden) { + var eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); + } + + return !hiding; + } + + return false; + } + /** + * Add event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "on", + value: function on$$1(event, callback) { + on.call(this, this.elements.container, event, callback); + } + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "once", + value: function once$$1(event, callback) { + once.call(this, this.elements.container, event, callback); + } + /** + * Remove event listeners + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + + }, { + key: "off", + value: function off$$1(event, callback) { + off(this.elements.container, event, callback); + } + /** + * Destroy an instance + * Event listeners are removed when elements are removed + * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + * @param {function} callback - Callback for when destroy is complete + * @param {boolean} soft - Whether it's a soft destroy (for source changes etc) + */ + + }, { + key: "destroy", + value: function destroy(callback) { + var _this2 = this; + + var soft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!this.ready) { + return; + } + + var done = function done() { + // Reset overflow (incase destroyed while in fullscreen) + document.body.style.overflow = ''; // GC for embed + + _this2.embed = null; // If it's a soft destroy, make minimal changes + + if (soft) { + if (Object.keys(_this2.elements).length) { + // Remove elements + removeElement(_this2.elements.buttons.play); + removeElement(_this2.elements.captions); + removeElement(_this2.elements.controls); + removeElement(_this2.elements.wrapper); // Clear for GC + + _this2.elements.buttons.play = null; + _this2.elements.captions = null; + _this2.elements.controls = null; + _this2.elements.wrapper = null; + } // Callback + + + if (is$1.function(callback)) { + callback(); + } + } else { + // Unbind listeners + unbindListeners.call(_this2); // Replace the container with the original element provided + + replaceElement(_this2.elements.original, _this2.elements.container); // Event + + triggerEvent.call(_this2, _this2.elements.original, 'destroyed', true); // Callback + + if (is$1.function(callback)) { + callback.call(_this2.elements.original); + } // Reset state + + + _this2.ready = false; // Clear for garbage collection + + setTimeout(function () { + _this2.elements = null; + _this2.media = null; + }, 200); + } + }; // Stop playback + + + this.stop(); // Provider specific stuff + + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); // Restore native video controls + + ui.toggleNativeControls.call(this, true); // Clean up + + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); // Destroy YouTube API + + if (this.embed !== null && is$1.function(this.embed.destroy)) { + this.embed.destroy(); + } // Clean up + + + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } // Vimeo does not always return + + + setTimeout(done, 200); + } + } + /** + * Check for support for a mime type (HTML5 only) + * @param {string} type - Mime type + */ + + }, { + key: "supports", + value: function supports(type) { + return support.mime.call(this, type); + } + /** + * Check for support + * @param {string} type - Player type (audio/video) + * @param {string} provider - Provider (html5/youtube/vimeo) + * @param {bool} inline - Where player has `playsinline` sttribute + */ + + }, { + key: "isHTML5", + get: function get() { + return Boolean(this.provider === providers.html5); + } + }, { + key: "isEmbed", + get: function get() { + return Boolean(this.isYouTube || this.isVimeo); + } + }, { + key: "isYouTube", + get: function get() { + return Boolean(this.provider === providers.youtube); + } + }, { + key: "isVimeo", + get: function get() { + return Boolean(this.provider === providers.vimeo); + } + }, { + key: "isVideo", + get: function get() { + return Boolean(this.type === types.video); + } + }, { + key: "isAudio", + get: function get() { + return Boolean(this.type === types.audio); + } + }, { + key: "playing", + get: function get() { + return Boolean(this.ready && !this.paused && !this.ended); + } + /** + * Get paused state + */ + + }, { + key: "paused", + get: function get() { + return Boolean(this.media.paused); + } + /** + * Get stopped state + */ + + }, { + key: "stopped", + get: function get() { + return Boolean(this.paused && this.currentTime === 0); + } + /** + * Get ended state + */ + + }, { + key: "ended", + get: function get() { + return Boolean(this.media.ended); + } + }, { + key: "currentTime", + set: function set(input) { + // Bail if media duration isn't available yet + if (!this.duration) { + return; + } // Validate input + + + var inputIsValid = is$1.number(input) && input > 0; // Set + + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging + + this.debug.log("Seeking to ".concat(this.currentTime, " seconds")); + } + /** + * Get current time + */ + , + get: function get() { + return Number(this.media.currentTime); + } + /** + * Get buffered + */ + + }, { + key: "buffered", + get: function get() { + var buffered = this.media.buffered; // YouTube / Vimeo return a float between 0-1 + + if (is$1.number(buffered)) { + return buffered; + } // HTML5 + // TODO: Handle buffered chunks of the media + // (i.e. seek to another section buffers only that section) + + + if (buffered && buffered.length && this.duration > 0) { + return buffered.end(0) / this.duration; + } + + return 0; + } + /** + * Get seeking status + */ + + }, { + key: "seeking", + get: function get() { + return Boolean(this.media.seeking); + } + /** + * Get the duration of the current media + */ + + }, { + key: "duration", + get: function get() { + // Faux duration set via config + var fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded + + var realDuration = (this.media || {}).duration; + var duration = !is$1.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration + + return fauxDuration || duration; + } + /** + * Set the player volume + * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage + */ + + }, { + key: "volume", + set: function set(value) { + var volume = value; + var max = 1; + var min = 0; + + if (is$1.string(volume)) { + volume = Number(volume); + } // Load volume from storage if no value specified + + + if (!is$1.number(volume)) { + volume = this.storage.get('volume'); + } // Use config if all else fails + + + if (!is$1.number(volume)) { + volume = this.config.volume; + } // Maximum is volumeMax + + + if (volume > max) { + volume = max; + } // Minimum is volumeMin + + + if (volume < min) { + volume = min; + } // Update config + + + this.config.volume = volume; // Set the player volume + + this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state + + if (!is$1.empty(value) && this.muted && volume > 0) { + this.muted = false; + } + } + /** + * Get the current player volume + */ + , + get: function get() { + return Number(this.media.volume); + } + }, { + key: "muted", + set: function set(mute) { + var toggle = mute; // Load muted state from storage + + if (!is$1.boolean(toggle)) { + toggle = this.storage.get('muted'); + } // Use config if all else fails + + + if (!is$1.boolean(toggle)) { + toggle = this.config.muted; + } // Update config + + + this.config.muted = toggle; // Set mute on the player + + this.media.muted = toggle; + } + /** + * Get current muted state + */ + , + get: function get() { + return Boolean(this.media.muted); + } + /** + * Check if the media has audio + */ + + }, { + key: "hasAudio", + get: function get() { + // Assume yes for all non HTML5 (as we can't tell...) + if (!this.isHTML5) { + return true; + } + + if (this.isAudio) { + return true; + } // Get audio tracks + + + return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length); + } + /** + * Set playback speed + * @param {number} speed - the speed of playback (0.5-2.0) + */ + + }, { + key: "speed", + set: function set(input) { + var speed = null; + + if (is$1.number(input)) { + speed = input; + } + + if (!is$1.number(speed)) { + speed = this.storage.get('speed'); + } + + if (!is$1.number(speed)) { + speed = this.config.speed.selected; + } // Set min/max + + + if (speed < 0.1) { + speed = 0.1; + } + + if (speed > 2.0) { + speed = 2.0; + } + + if (!this.config.speed.options.includes(speed)) { + this.debug.warn("Unsupported speed (".concat(speed, ")")); + return; + } // Update config + + + this.config.speed.selected = speed; // Set media speed + + this.media.playbackRate = speed; + } + /** + * Get current playback speed + */ + , + get: function get() { + return Number(this.media.playbackRate); + } + /** + * Set playback quality + * Currently HTML5 & YouTube only + * @param {number} input - Quality level + */ + + }, { + key: "quality", + set: function set(input) { + var config = this.config.quality; + var options = this.options.quality; + + if (!options.length) { + return; + } + + var quality = [!is$1.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is$1.number); + var updateStorage = true; + + if (!options.includes(quality)) { + var value = closest(options, quality); + this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); + quality = value; // Don't update storage if quality is not supported + + updateStorage = false; + } // Update config + + + config.selected = quality; // Set quality + + this.media.quality = quality; // Save to storage + + if (updateStorage) { + this.storage.set({ + quality: quality + }); + } + } + /** + * Get current quality level + */ + , + get: function get() { + return this.media.quality; + } + /** + * Toggle loop + * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config + * @param {boolean} input - Whether to loop or not + */ + + }, { + key: "loop", + set: function set(input) { + var toggle = is$1.boolean(input) ? input : this.config.loop.active; + this.config.loop.active = toggle; + this.media.loop = toggle; // Set default to be a true toggle + + /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle'; + switch (type) { + case 'start': + if (this.config.loop.end && this.config.loop.end <= this.currentTime) { + this.config.loop.end = null; + } + this.config.loop.start = this.currentTime; + // this.config.loop.indicator.start = this.elements.display.played.value; + break; + case 'end': + if (this.config.loop.start >= this.currentTime) { + return this; + } + this.config.loop.end = this.currentTime; + // this.config.loop.indicator.end = this.elements.display.played.value; + break; + case 'all': + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + this.config.loop.indicator.start = 0; + this.config.loop.indicator.end = 100; + break; + case 'toggle': + if (this.config.loop.active) { + this.config.loop.start = 0; + this.config.loop.end = null; + } else { + this.config.loop.start = 0; + this.config.loop.end = this.duration - 2; + } + break; + default: + this.config.loop.start = 0; + this.config.loop.end = null; + break; + } */ + } + /** + * Get current loop state + */ + , + get: function get() { + return Boolean(this.media.loop); + } + /** + * Set new media source + * @param {object} input - The new source object (see docs) + */ + + }, { + key: "source", + set: function set(input) { + source.change.call(this, input); + } + /** + * Get current source + */ + , + get: function get() { + return this.media.currentSrc; + } + /** + * Get a download URL (either source or custom) + */ + + }, { + key: "download", + get: function get() { + var download = this.config.urls.download; + return is$1.url(download) ? download : this.source; + } + /** + * Set the poster image for a video + * @param {input} - the URL for the new poster image + */ + + }, { + key: "poster", + set: function set(input) { + if (!this.isVideo) { + this.debug.warn('Poster can only be set for video'); + return; + } + + ui.setPoster.call(this, input, false).catch(function () {}); + } + /** + * Get the current poster image + */ + , + get: function get() { + if (!this.isVideo) { + return null; + } + + return this.media.getAttribute('poster'); + } + /** + * Set the autoplay state + * @param {boolean} input - Whether to autoplay or not + */ + + }, { + key: "autoplay", + set: function set(input) { + var toggle = is$1.boolean(input) ? input : this.config.autoplay; + this.config.autoplay = toggle; + } + /** + * Get the current autoplay state + */ + , + get: function get() { + return Boolean(this.config.autoplay); + } + }, { + key: "currentTrack", + set: function set(input) { + captions.set.call(this, input, false); + } + /** + * Get the current caption track index (-1 if disabled) + */ + , + get: function get() { + var _this$captions = this.captions, + toggled = _this$captions.toggled, + currentTrack = _this$captions.currentTrack; + return toggled ? currentTrack : -1; + } + /** + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track + * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) + */ + + }, { + key: "language", + set: function set(input) { + captions.setLanguage.call(this, input, false); + } + /** + * Get the current track's language + */ + , + get: function get() { + return (captions.getCurrentTrack.call(this) || {}).language; + } + /** + * Toggle picture-in-picture playback on WebKit/MacOS + * TODO: update player with state, support, enabled + * TODO: detect outside changes + */ + + }, { + key: "pip", + set: function set(input) { + // Bail if no support + if (!support.pip) { + return; + } // Toggle based on current state if not passed + + + var toggle = is$1.boolean(input) ? input : !this.pip; // Toggle based on current state + // Safari + + if (is$1.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } // Chrome + + + if (is$1.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } + } + } + /** + * Get the current picture-in-picture state + */ + , + get: function get() { + if (!support.pip) { + return null; + } // Safari + + + if (!is$1.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } // Chrome + + + return this.media === document.pictureInPictureElement; + } + }], [{ + key: "supported", + value: function supported(type, provider, inline) { + return support.check(type, provider, inline); + } + /** + * Load an SVG sprite into the page + * @param {string} url - URL for the SVG sprite + * @param {string} [id] - Unique ID + */ + + }, { + key: "loadSprite", + value: function loadSprite$$1(url, id) { + return loadSprite(url, id); + } + /** + * Setup multiple instances + * @param {*} selector + * @param {object} options + */ + + }, { + key: "setup", + value: function setup(selector) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var targets = null; + + if (is$1.string(selector)) { + targets = Array.from(document.querySelectorAll(selector)); + } else if (is$1.nodeList(selector)) { + targets = Array.from(selector); + } else if (is$1.array(selector)) { + targets = selector.filter(is$1.element); + } + + if (is$1.empty(targets)) { + return null; + } + + return targets.map(function (t) { + return new Plyr(t, options); + }); + } + }]); + + return Plyr; +}(); + +Plyr.defaults = cloneDeep(defaults); + +// ========================================================================== + +export default Plyr; diff --git a/dist/plyr.svg b/dist/plyr.svg index 3db87c38..be7c210d 100644 --- a/dist/plyr.svg +++ b/dist/plyr.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="plyr-airplay" viewBox="0 0 18 18"><path d="M16 1H2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3v-2H3V3h12v8h-2v2h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/><path d="M4 17h10l-5-6z"/></symbol><symbol id="plyr-captions-off" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd" fill-opacity=".5"/></symbol><symbol id="plyr-captions-on" viewBox="0 0 18 18"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd"/></symbol><symbol id="plyr-enter-fullscreen" viewBox="0 0 18 18"><path d="M10 3h3.6l-4 4L11 8.4l4-4V8h2V1h-7zM7 9.6l-4 4V10H1v7h7v-2H4.4l4-4z"/></symbol><symbol id="plyr-exit-fullscreen" viewBox="0 0 18 18"><path d="M1 12h3.6l-4 4L2 17.4l4-4V17h2v-7H1zM16 .6l-4 4V1h-2v7h7V6h-3.6l4-4z"/></symbol><symbol id="plyr-fast-forward" viewBox="0 0 18 18"><path d="M7.875 7.171L0 1v16l7.875-6.171V17L18 9 7.875 1z"/></symbol><symbol id="plyr-muted" viewBox="0 0 18 18"><path d="M12.4 12.5l2.1-2.1 2.1 2.1 1.4-1.4L15.9 9 18 6.9l-1.4-1.4-2.1 2.1-2.1-2.1L11 6.9 13.1 9 11 11.1zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol><symbol id="plyr-pause" viewBox="0 0 18 18"><path d="M6 1H3c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1zM12 1c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1h-3z"/></symbol><symbol id="plyr-pip" viewBox="0 0 18 18"><path d="M13.293 3.293L7.022 9.564l1.414 1.414 6.271-6.271L17 7V1h-6z"/><path d="M13 15H3V5h5V3H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-6h-2v5z"/></symbol><symbol id="plyr-play" viewBox="0 0 18 18"><path d="M15.562 8.1L3.87.225C3.052-.337 2 .225 2 1.125v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"/></symbol><symbol id="plyr-restart" viewBox="0 0 18 18"><path d="M9.7 1.2l.7 6.4 2.1-2.1c1.9 1.9 1.9 5.1 0 7-.9 1-2.2 1.5-3.5 1.5-1.3 0-2.6-.5-3.5-1.5-1.9-1.9-1.9-5.1 0-7 .6-.6 1.4-1.1 2.3-1.3l-.6-1.9C6 2.6 4.9 3.2 4 4.1 1.3 6.8 1.3 11.2 4 14c1.3 1.3 3.1 2 4.9 2 1.9 0 3.6-.7 4.9-2 2.7-2.7 2.7-7.1 0-9.9L16 1.9l-6.3-.7z"/></symbol><symbol id="plyr-rewind" viewBox="0 0 18 18"><path d="M10.125 1L0 9l10.125 8v-6.171L18 17V1l-7.875 6.171z"/></symbol><symbol id="plyr-settings" viewBox="0 0 18 18"><path d="M16.135 7.784a2 2 0 0 1-1.23-2.969c.322-.536.225-.998-.094-1.316l-.31-.31c-.318-.318-.78-.415-1.316-.094a2 2 0 0 1-2.969-1.23C10.065 1.258 9.669 1 9.219 1h-.438c-.45 0-.845.258-.997.865a2 2 0 0 1-2.969 1.23c-.536-.322-.999-.225-1.317.093l-.31.31c-.318.318-.415.781-.093 1.317a2 2 0 0 1-1.23 2.969C1.26 7.935 1 8.33 1 8.781v.438c0 .45.258.845.865.997a2 2 0 0 1 1.23 2.969c-.322.536-.225.998.094 1.316l.31.31c.319.319.782.415 1.316.094a2 2 0 0 1 2.969 1.23c.151.607.547.865.997.865h.438c.45 0 .845-.258.997-.865a2 2 0 0 1 2.969-1.23c.535.321.997.225 1.316-.094l.31-.31c.318-.318.415-.781.094-1.316a2 2 0 0 1 1.23-2.969c.607-.151.865-.547.865-.997v-.438c0-.451-.26-.846-.865-.997zM9 12a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol id="plyr-volume" viewBox="0 0 18 18"><path d="M15.6 3.3c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4C15.4 5.9 16 7.4 16 9c0 1.6-.6 3.1-1.8 4.3-.4.4-.4 1 0 1.4.2.2.5.3.7.3.3 0 .5-.1.7-.3C17.1 13.2 18 11.2 18 9s-.9-4.2-2.4-5.7z"/><path d="M11.282 5.282a.909.909 0 0 0 0 1.316c.735.735.995 1.458.995 2.402 0 .936-.425 1.917-.995 2.487a.909.909 0 0 0 0 1.316c.145.145.636.262 1.018.156a.725.725 0 0 0 .298-.156C13.773 11.733 14.13 10.16 14.13 9c0-.17-.002-.34-.011-.51-.053-.992-.319-2.005-1.522-3.208a.909.909 0 0 0-1.316 0zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol></svg>
\ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol id="plyr-airplay"><path d="M16 1H2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3v-2H3V3h12v8h-2v2h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/><path d="M4 17h10l-5-6z"/></symbol><symbol id="plyr-captions-off"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd" fill-opacity=".5"/></symbol><symbol id="plyr-captions-on"><path d="M1 1c-.6 0-1 .4-1 1v11c0 .6.4 1 1 1h4.6l2.7 2.7c.2.2.4.3.7.3.3 0 .5-.1.7-.3l2.7-2.7H17c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1H1zm4.52 10.15c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41C8.47 4.96 7.46 3.76 5.5 3.76c-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69zm7.57 0c1.99 0 3.01-1.32 3.28-2.41l-1.29-.39c-.19.66-.78 1.45-1.99 1.45-1.14 0-2.2-.83-2.2-2.34 0-1.61 1.12-2.37 2.18-2.37 1.23 0 1.78.75 1.95 1.43l1.3-.41c-.28-1.15-1.29-2.35-3.25-2.35-1.9 0-3.61 1.44-3.61 3.7 0 2.26 1.65 3.69 3.63 3.69z" fill-rule="evenodd"/></symbol><symbol id="plyr-download"><path d="M9 13c.3 0 .5-.1.7-.3L15.4 7 14 5.6l-4 4V1H8v8.6l-4-4L2.6 7l5.7 5.7c.2.2.4.3.7.3zM2 15h14v2H2z"/></symbol><symbol id="plyr-enter-fullscreen"><path d="M10 3h3.6l-4 4L11 8.4l4-4V8h2V1h-7zM7 9.6l-4 4V10H1v7h7v-2H4.4l4-4z"/></symbol><symbol id="plyr-exit-fullscreen"><path d="M1 12h3.6l-4 4L2 17.4l4-4V17h2v-7H1zM16 .6l-4 4V1h-2v7h7V6h-3.6l4-4z"/></symbol><symbol id="plyr-fast-forward"><path d="M7.875 7.171L0 1v16l7.875-6.171V17L18 9 7.875 1z"/></symbol><symbol id="plyr-logo-vimeo"><path d="M17 5.3c-.1 1.6-1.2 3.7-3.3 6.4-2.2 2.8-4 4.2-5.5 4.2-.9 0-1.7-.9-2.4-2.6C5 10.9 4.4 6 3 6c-.1 0-.5.3-1.2.8l-.8-1c.8-.7 3.5-3.4 4.7-3.5 1.2-.1 2 .7 2.3 2.5.3 2 .8 6.1 1.8 6.1.9 0 2.5-3.4 2.6-4 .1-.9-.3-1.9-2.3-1.1.8-2.6 2.3-3.8 4.5-3.8 1.7.1 2.5 1.2 2.4 3.3z"/></symbol><symbol id="plyr-logo-youtube"><path d="M16.8 5.8c-.2-1.3-.8-2.2-2.2-2.4C12.4 3 9 3 9 3s-3.4 0-5.6.4C2 3.6 1.3 4.5 1.2 5.8 1 7.1 1 9 1 9s0 1.9.2 3.2c.2 1.3.8 2.2 2.2 2.4C5.6 15 9 15 9 15s3.4 0 5.6-.4c1.4-.3 2-1.1 2.2-2.4.2-1.3.2-3.2.2-3.2s0-1.9-.2-3.2zM7 12V6l5 3-5 3z"/></symbol><symbol id="plyr-muted"><path d="M12.4 12.5l2.1-2.1 2.1 2.1 1.4-1.4L15.9 9 18 6.9l-1.4-1.4-2.1 2.1-2.1-2.1L11 6.9 13.1 9 11 11.1zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol><symbol id="plyr-pause"><path d="M6 1H3c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1zM12 1c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h3c.6 0 1-.4 1-1V2c0-.6-.4-1-1-1h-3z"/></symbol><symbol id="plyr-pip"><path d="M13.293 3.293L7.022 9.564l1.414 1.414 6.271-6.271L17 7V1h-6z"/><path d="M13 15H3V5h5V3H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-6h-2v5z"/></symbol><symbol id="plyr-play"><path d="M15.562 8.1L3.87.225C3.052-.337 2 .225 2 1.125v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"/></symbol><symbol id="plyr-restart"><path d="M9.7 1.2l.7 6.4 2.1-2.1c1.9 1.9 1.9 5.1 0 7-.9 1-2.2 1.5-3.5 1.5-1.3 0-2.6-.5-3.5-1.5-1.9-1.9-1.9-5.1 0-7 .6-.6 1.4-1.1 2.3-1.3l-.6-1.9C6 2.6 4.9 3.2 4 4.1 1.3 6.8 1.3 11.2 4 14c1.3 1.3 3.1 2 4.9 2 1.9 0 3.6-.7 4.9-2 2.7-2.7 2.7-7.1 0-9.9L16 1.9l-6.3-.7z"/></symbol><symbol id="plyr-rewind"><path d="M10.125 1L0 9l10.125 8v-6.171L18 17V1l-7.875 6.171z"/></symbol><symbol id="plyr-settings"><path d="M16.135 7.784a2 2 0 0 1-1.23-2.969c.322-.536.225-.998-.094-1.316l-.31-.31c-.318-.318-.78-.415-1.316-.094a2 2 0 0 1-2.969-1.23C10.065 1.258 9.669 1 9.219 1h-.438c-.45 0-.845.258-.997.865a2 2 0 0 1-2.969 1.23c-.536-.322-.999-.225-1.317.093l-.31.31c-.318.318-.415.781-.093 1.317a2 2 0 0 1-1.23 2.969C1.26 7.935 1 8.33 1 8.781v.438c0 .45.258.845.865.997a2 2 0 0 1 1.23 2.969c-.322.536-.225.998.094 1.316l.31.31c.319.319.782.415 1.316.094a2 2 0 0 1 2.969 1.23c.151.607.547.865.997.865h.438c.45 0 .845-.258.997-.865a2 2 0 0 1 2.969-1.23c.535.321.997.225 1.316-.094l.31-.31c.318-.318.415-.781.094-1.316a2 2 0 0 1 1.23-2.969c.607-.151.865-.547.865-.997v-.438c0-.451-.26-.846-.865-.997zM9 12a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol id="plyr-volume"><path d="M15.6 3.3c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4C15.4 5.9 16 7.4 16 9c0 1.6-.6 3.1-1.8 4.3-.4.4-.4 1 0 1.4.2.2.5.3.7.3.3 0 .5-.1.7-.3C17.1 13.2 18 11.2 18 9s-.9-4.2-2.4-5.7z"/><path d="M11.282 5.282a.909.909 0 0 0 0 1.316c.735.735.995 1.458.995 2.402 0 .936-.425 1.917-.995 2.487a.909.909 0 0 0 0 1.316c.145.145.636.262 1.018.156a.725.725 0 0 0 .298-.156C13.773 11.733 14.13 10.16 14.13 9c0-.17-.002-.34-.011-.51-.053-.992-.319-2.005-1.522-3.208a.909.909 0 0 0-1.316 0zM3.786 6.008H.714C.286 6.008 0 6.31 0 6.76v4.512c0 .452.286.752.714.752h3.072l4.071 3.858c.5.3 1.143 0 1.143-.602V2.752c0-.601-.643-.977-1.143-.601L3.786 6.008z"/></symbol></svg>
\ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index eec51aba..b536662b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -12,7 +12,7 @@ const concat = require('gulp-concat'); const filter = require('gulp-filter'); const sass = require('gulp-sass'); const cleancss = require('gulp-clean-css'); -const run = require('run-sequence'); +const header = require('gulp-header'); const prefix = require('gulp-autoprefixer'); const gitbranch = require('git-branch'); const svgstore = require('gulp-svgstore'); @@ -28,53 +28,46 @@ const sourcemaps = require('gulp-sourcemaps'); const uglify = require('gulp-uglify-es').default; const commonjs = require('rollup-plugin-commonjs'); const resolve = require('rollup-plugin-node-resolve'); +const FastlyPurge = require('fastly-purge'); +const through = require('through2'); const bundles = require('./bundles.json'); const pkg = require('./package.json'); -// Get AWS config -let aws = {}; -try { - aws = require('./aws.json'); //eslint-disable-line -} catch (e) { - // Do nothing -} - const minSuffix = '.min'; // Paths -const root = __dirname; const paths = { plyr: { // Source paths src: { - sass: path.join(root, 'src/sass/**/*.scss'), - js: path.join(root, 'src/js/**/*'), - sprite: path.join(root, 'src/sprite/*.svg'), + sass: path.join(__dirname, 'src/sass/**/*.scss'), + js: path.join(__dirname, 'src/js/**/*.js'), + sprite: path.join(__dirname, 'src/sprite/*.svg'), }, // Output paths - output: path.join(root, 'dist/'), + output: path.join(__dirname, 'dist/'), }, demo: { // Source paths src: { - sass: path.join(root, 'demo/src/sass/**/*.scss'), - js: path.join(root, 'demo/src/js/**/*'), + sass: path.join(__dirname, 'demo/src/sass/**/*.scss'), + js: path.join(__dirname, 'demo/src/js/**/*.js'), }, // Output paths - output: path.join(root, 'demo/dist/'), + output: path.join(__dirname, 'demo/dist/'), // Demo - root: path.join(root, 'demo/'), + root: path.join(__dirname, 'demo/'), }, upload: [ - path.join(root, `dist/*${minSuffix}.*`), - path.join(root, 'dist/*.css'), - path.join(root, 'dist/*.svg'), - path.join(root, `demo/dist/*${minSuffix}.*`), - path.join(root, 'demo/dist/*.css'), + path.join(__dirname, `dist/*${minSuffix}.*`), + path.join(__dirname, 'dist/*.css'), + path.join(__dirname, 'dist/*.svg'), + path.join(__dirname, `demo/dist/*${minSuffix}.*`), + path.join(__dirname, 'demo/dist/*.css'), ], }; @@ -93,62 +86,63 @@ const sizeOptions = { showFiles: true, gzip: true }; const browsers = ['> 1%']; // Babel config -const babelrc = { - presets: [[ - 'env', - { - targets: { - browsers, +const babelrc = (polyfill = false) => ({ + presets: [ + [ + '@babel/preset-env', + { + targets: { + browsers, + }, + useBuiltIns: polyfill ? 'usage' : false, + modules: false, }, - useBuiltIns: true, - modules: false, - }, - ]], - plugins: ['external-helpers'], + ], + ], babelrc: false, exclude: 'node_modules/**', -}; +}); // Clean out /dist -gulp.task('clean', () => { - const dirs = [ - paths.plyr.output, - paths.demo.output, - ].map(dir => path.join(dir, '**/*')); +gulp.task('clean', done => { + const dirs = [paths.plyr.output, paths.demo.output].map(dir => path.join(dir, '**/*')); // Don't delete the mp4 dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`); del(dirs); + + done(); }); const build = { js(files, bundle, options) { Object.keys(files).forEach(key => { - const name = `js:${key}`; + const { format } = options; + const name = `js:${key}:${format}`; tasks.js.push(name); const { output } = paths[bundle]; + const polyfill = name.includes('polyfilled'); + const extension = format === 'es' ? '.mjs' : '.js'; return gulp.task(name, () => gulp .src(bundles[bundle].js[key]) .pipe(sourcemaps.init()) .pipe(concat(key)) + .pipe( rollup( { - plugins: [ - resolve(), - commonjs(), - babel(babelrc), - ], + plugins: [resolve(), commonjs(), babel(babelrc(polyfill))], }, options, ), ) - .pipe(sourcemaps.write('')) + .pipe(header('typeof navigator === "object" && ')) // "Support" SSR (#935) + .pipe(rename({ extname: extension })) .pipe(gulp.dest(output)) - .pipe(filter('**/*.js')) + .pipe(filter(`**/*${extension}`)) .pipe(uglify()) .pipe(size(sizeOptions)) .pipe(rename({ suffix: minSuffix })) @@ -185,21 +179,26 @@ const build = { .src(paths[bundle].src.sprite) .pipe( svgmin({ - plugins: [{ - removeDesc: true, - }], + plugins: [ + { + removeDesc: true, + }, + ], }), ) .pipe(svgstore()) .pipe(rename({ basename: bundle })) .pipe(size(sizeOptions)) - .pipe(gulp.dest(paths[bundle].output)), + .pipe(gulp.dest(paths[bundle].output)) + .pipe(gulp.dest(paths.demo.output)), ); }, }; // Plyr core files -build.js(bundles.plyr.js, 'plyr', { name: 'Plyr', format: 'umd' }); +const namespace = 'Plyr'; +build.js(bundles.plyr.js, 'plyr', { name: namespace, format: 'umd' }); +build.js(bundles.plyr.js, 'plyr', { name: namespace, format: 'es' }); build.sass(bundles.plyr.sass, 'plyr'); build.sprite('plyr'); @@ -208,43 +207,47 @@ build.sass(bundles.demo.sass, 'demo'); build.js(bundles.demo.js, 'demo', { format: 'iife' }); // Build all JS -gulp.task('js', () => { - run(tasks.js); -}); +gulp.task('js', () => gulp.parallel(...tasks.js)); // Watch for file changes gulp.task('watch', () => { // Plyr core - gulp.watch(paths.plyr.src.js, tasks.js); - gulp.watch(paths.plyr.src.sass, tasks.sass); - gulp.watch(paths.plyr.src.sprite, tasks.sprite); + gulp.watch(paths.plyr.src.js, gulp.parallel(...tasks.js)); + gulp.watch(paths.plyr.src.sass, gulp.parallel(...tasks.sass)); + gulp.watch(paths.plyr.src.sprite, gulp.parallel(...tasks.sprite)); // Demo - gulp.watch(paths.demo.src.js, tasks.js); - gulp.watch(paths.demo.src.sass, tasks.sass); + gulp.watch(paths.demo.src.js, gulp.parallel(...tasks.js)); + gulp.watch(paths.demo.src.sass, gulp.parallel(...tasks.sass)); }); +// Build distribution +gulp.task('build', gulp.series(tasks.clean, gulp.parallel(...tasks.js, ...tasks.sass, ...tasks.sprite))); + // Default gulp task -gulp.task('default', () => { - run(tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'watch'); -}); +gulp.task('default', gulp.series('build', 'watch')); // Publish a version to CDN and demo // -------------------------------------------- -// If aws is setup -if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { +// Get deployment config +let credentials = {}; +try { + credentials = require('./credentials.json'); //eslint-disable-line +} catch (e) { + // Do nothing +} + +// If deployment is setup +if (Object.keys(credentials).includes('aws') && Object.keys(credentials).includes('fastly')) { const { version } = pkg; + const { aws, fastly } = credentials; // Get branch info const branch = { current: gitbranch.sync(), master: 'master', - beta: 'beta', + develop: 'develop', }; - const allowed = [ - branch.master, - branch.beta, - ]; const maxAge = 31536000; // 1 year const options = { @@ -255,7 +258,7 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { }, }, demo: { - uploadPath: branch.current === branch.beta ? 'beta/' : null, + uploadPath: branch.current === branch.develop ? 'beta/' : null, headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', Vary: 'Accept-Encoding', @@ -272,33 +275,51 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { }, }; - const regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?'; + const regex = + '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?'; const semver = new RegExp(`v${regex}`, 'gi'); const localPath = new RegExp('(../)?dist', 'gi'); const versionPath = `https://${aws.cdn.domain}/${version}`; const cdnpath = new RegExp(`${aws.cdn.domain}/${regex}/`, 'gi'); + const renameFile = rename(p => { + p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line + p.dirname = p.dirname.replace('.', version); // eslint-disable-line + }); + + // Check we're on the correct branch to deploy + const canDeploy = () => { + const allowed = [branch.master, branch.develop]; + + if (!allowed.includes(branch.current)) { + console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`); + + return false; + } + + return true; + }; + gulp.task('version', () => { + if (!canDeploy()) { + return null; + } + console.log(`Updating versions to '${version}'...`); // Replace versioned URLs in source - const files = [ - 'plyr.js', - 'plyr.polyfilled.js', - 'defaults.js', - ]; + const files = ['plyr.js', 'plyr.polyfilled.js', 'config/defaults.js']; return gulp - .src(files.map(file => path.join(root, `src/js/${file}`))) + .src(files.map(file => path.join(__dirname, `src/js/${file}`)), { base: '.' }) .pipe(replace(semver, `v${version}`)) .pipe(replace(cdnpath, `${aws.cdn.domain}/${version}/`)) - .pipe(gulp.dest(path.join(root, 'src/js/'))); + .pipe(gulp.dest('./')); }); // Publish version to CDN bucket gulp.task('cdn', () => { - if (!allowed.includes(branch.current)) { - console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`); + if (!canDeploy()) { return null; } @@ -308,14 +329,14 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { return ( gulp .src(paths.upload) + .pipe(renameFile) + // Remove min suffix from source map URL .pipe( - rename(p => { - p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line - p.dirname = p.dirname.replace('.', version); // eslint-disable-line - }), + replace( + /sourceMappingURL=([\w-?.]+)/, + (match, p1) => `sourceMappingURL=${p1.replace(minSuffix, '')}`, + ), ) - // Remove min suffix from source map URL - .pipe(replace(/sourceMappingURL=([\w-?.]+)/, (match, p1) => `sourceMappingURL=${p1.replace(minSuffix, '')}`)) .pipe( size({ showFiles: true, @@ -327,20 +348,48 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { ); }); + // Purge the fastly cache incase any 403/404 are cached + gulp.task('purge', () => { + const list = []; + + return gulp + .src(paths.upload) + .pipe( + through.obj((file, enc, cb) => { + const filename = file.path.split('/').pop(); + list.push(`${versionPath}/${filename}`); + cb(null); + }), + ) + .on('end', () => { + const purge = new FastlyPurge(fastly.token); + + list.forEach(url => { + console.log(`Purging ${url}...`); + + purge.url(url, (error, result) => { + if (error) { + console.log(error); + } else if (result) { + console.log(result); + } + }); + }); + }); + }); + // Publish to demo bucket gulp.task('demo', () => { - if (!allowed.includes(branch.current)) { - console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`); + if (!canDeploy()) { return null; } console.log(`Uploading '${version}' demo to ${aws.demo.domain}...`); // Replace versioned files in readme.md - gulp - .src([`${root}/readme.md`]) + gulp.src([`${__dirname}/readme.md`]) .pipe(replace(cdnpath, `${aws.cdn.domain}/${version}/`)) - .pipe(gulp.dest(root)); + .pipe(gulp.dest(__dirname)); // Replace local file paths with remote paths in demo HTML // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js" @@ -352,8 +401,7 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { pages.push(error); } - gulp - .src(pages) + gulp.src(pages) .pipe(replace(localPath, versionPath)) .pipe(s3(aws.demo, options.demo)); @@ -392,22 +440,28 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { })); }); */ - // Open the demo site to check it's sweet - gulp.task('open', () => { - console.log(`Opening ${aws.demo.domain}...`); - - // A file must be specified or gulp will skip the task - // Doesn't matter which file since we set the URL above - // Weird, I know... - return gulp.src([`${paths.demo.root}index.html`]).pipe( - open('', { - url: `http://${aws.demo.domain}`, + // Open the demo site to check it's ok + gulp.task('open', callback => { + gulp.src(__filename).pipe( + open({ + uri: `https://${aws.demo.domain}`, }), ); + + callback(); }); // Do everything - gulp.task('publish', callback => { - run('version', tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'cdn', 'demo', callback); - }); + gulp.task( + 'deploy', + gulp.series( + 'version', + tasks.clean, + gulp.parallel(...tasks.js, ...tasks.sass, ...tasks.sprite), + 'cdn', + 'demo', + 'purge', + 'open', + ), + ); } diff --git a/package.json b/package.json index 96e6459a..1a57d3ee 100644 --- a/package.json +++ b/package.json @@ -1,60 +1,29 @@ { "name": "plyr", - "version": "3.3.6", + "version": "3.5.0-beta.1", "description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player", "homepage": "https://plyr.io", - "main": "./dist/plyr.js", - "browser": "./dist/plyr.min.js", - "sass": "./src/sass/plyr.scss", - "style": "./dist/plyr.css", - "devDependencies": { - "babel-core": "^6.26.3", - "babel-eslint": "^8.2.3", - "babel-plugin-external-helpers": "^6.22.0", - "babel-preset-env": "^1.6.1", - "del": "^3.0.0", - "eslint": "^4.19.1", - "eslint-config-airbnb-base": "^12.1.0", - "eslint-config-prettier": "^2.9.0", - "eslint-plugin-import": "^2.11.0", - "git-branch": "^2.0.1", - "gulp": "^3.9.1", - "gulp-autoprefixer": "^5.0.0", - "gulp-better-rollup": "^3.1.0", - "gulp-clean-css": "^3.9.4", - "gulp-concat": "^2.6.1", - "gulp-filter": "^5.1.0", - "gulp-open": "^3.0.1", - "gulp-rename": "^1.2.2", - "gulp-replace": "^0.6.1", - "gulp-s3": "^0.11.0", - "gulp-sass": "^4.0.1", - "gulp-size": "^3.0.0", - "gulp-sourcemaps": "^2.6.4", - "gulp-svgmin": "^1.2.4", - "gulp-svgstore": "^6.1.1", - "gulp-uglify-es": "^1.0.1", - "gulp-util": "^3.0.8", - "prettier-eslint": "^8.8.1", - "prettier-stylelint": "^0.4.2", - "rollup-plugin-babel": "^3.0.4", - "rollup-plugin-commonjs": "^9.1.3", - "rollup-plugin-node-resolve": "^3.3.0", - "run-sequence": "^2.2.1", - "stylelint": "^9.2.0", - "stylelint-config-prettier": "^3.2.0", - "stylelint-config-recommended": "^2.1.0", - "stylelint-config-sass-guidelines": "^5.0.0", - "stylelint-order": "^0.8.1", - "stylelint-scss": "^3.1.0", - "stylelint-selector-bem-pattern": "^2.0.0" - }, - "keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"], + "author": "Sam Potts <sam@potts.es>", + "main": "dist/plyr.js", + "module": "dist/plyr.mjs", + "jsnext:main": "dist/plyr.mjs", + "browser": "dist/plyr.min.js", + "sass": "src/sass/plyr.scss", + "style": "dist/plyr.css", + "keywords": [ + "HTML5 Video", + "HTML5 Audio", + "Media Player", + "DASH", + "Shaka", + "WordPress", + "HLS" + ], + "license": "MIT", "repository": { "type": "git", "url": "git://github.com/sampotts/plyr.git" }, - "license": "MIT", "bugs": { "url": "https://github.com/sampotts/plyr/issues" }, @@ -62,14 +31,63 @@ "doc": "readme.md" }, "scripts": { + "build": "gulp build", + "lint": "eslint src/js && npm run-script remark", + "remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'", "test": "echo \"Error: no test specified\" && exit 1" }, - "author": "Sam Potts <sam@potts.es>", + "devDependencies": { + "@babel/core": "^7.2.2", + "babel-eslint": "^10.0.1", + "@babel/preset-env": "^7.3.1", + "del": "^3.0.0", + "eslint": "^5.12.1", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-config-prettier": "^4.0.0", + "eslint-plugin-import": "^2.15.0", + "fastly-purge": "^1.0.1", + "git-branch": "^2.0.1", + "gulp": "^4.0.0", + "gulp-autoprefixer": "^6.0.0", + "gulp-better-rollup": "^3.4.0", + "gulp-clean-css": "^4.0.0", + "gulp-concat": "^2.6.1", + "gulp-filter": "^5.1.0", + "gulp-header": "^2.0.7", + "gulp-open": "^3.0.1", + "gulp-postcss": "^8.0.0", + "gulp-rename": "^1.4.0", + "gulp-replace": "^1.0.0", + "gulp-s3": "^0.11.0", + "gulp-sass": "^4.0.2", + "gulp-size": "^3.0.0", + "gulp-sourcemaps": "^2.6.4", + "gulp-svgmin": "^2.1.0", + "gulp-svgstore": "^7.0.1", + "gulp-uglify-es": "^1.0.4", + "gulp-util": "^3.0.8", + "postcss-custom-properties": "^8.0.9", + "prettier-eslint": "^8.8.2", + "prettier-stylelint": "^0.4.2", + "remark-cli": "^6.0.1", + "remark-validate-links": "^8.0.0", + "rollup-plugin-babel": "^4.3.2", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-node-resolve": "^4.0.0", + "stylelint": "^9.10.1", + "stylelint-config-prettier": "^4.0.0", + "stylelint-config-recommended": "^2.1.0", + "stylelint-config-sass-guidelines": "^5.3.0", + "stylelint-order": "^2.0.0", + "stylelint-scss": "^3.5.1", + "stylelint-selector-bem-pattern": "^2.0.0", + "through2": "^3.0.0" + }, "dependencies": { - "babel-polyfill": "^6.26.0", - "custom-event-polyfill": "^0.3.0", - "loadjs": "^3.5.4", - "npm": "^6.0.0", - "raven-js": "^3.24.2" + "core-js": "^2.6.3", + "custom-event-polyfill": "^1.0.6", + "loadjs": "^3.5.5", + "raven-js": "^3.27.0", + "url-polyfill": "^1.1.3" } } diff --git a/plyr.code-workspace b/plyr.code-workspace index c0b30608..12c3e85b 100644 --- a/plyr.code-workspace +++ b/plyr.code-workspace @@ -1,31 +1,35 @@ { - "folders": [ - { - "path": "." - } - ], - "settings": { - // Exclude from the editor - "files.exclude": { - "**/node_modules": true - }, - // Exclude from search - "search.exclude": { - "dist/": true - }, - // Linting - "stylelint.enable": true, - "css.validate": false, - "scss.validate": false, - "javascript.validate.enable": false, - // Prettier - "prettier.eslintIntegration": true, - "prettier.stylelintIntegration": true, - // Formatting - "editor.tabSize": 4, - "editor.insertSpaces": true, - "editor.formatOnSave": true, - // Trim on save - "files.trimTrailingWhitespace": true - } -}
\ No newline at end of file + "folders": [ + { + "path": "." + } + ], + "settings": { + // Exclude from the editor + "files.exclude": { + "**/node_modules": true + }, + // Exclude from search + "search.exclude": { + "dist/": true, + "demo/dist/": true + }, + // Linting + "stylelint.enable": true, + "css.validate": false, + "scss.validate": false, + "javascript.validate.enable": false, + // Prettier + "prettier.eslintIntegration": true, + "prettier.stylelintIntegration": true, + // Formatting + "editor.tabSize": 4, + "editor.insertSpaces": true, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true + }, + // Trim on save + "files.trimTrailingWhitespace": true + } +} @@ -8,26 +8,27 @@ A simple, lightweight, accessible and customizable HTML5, YouTube and Vimeo medi ## Features -* **Accessible** - full support for VTT captions and screen readers -* **[Customisable](#html)** - make the player look how you want with the markup you want -* **Good HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no +- **Accessible** - full support for VTT captions and screen readers +- **[Customisable](#html)** - make the player look how you want with the markup you want +- **Good HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks -* **Responsive** - works with any screen size -* **HTML Video & Audio** - support for both formats -* **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback -* **[Monetization](#ads)** - make money from your videos -* **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback -* **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API -* **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats -* **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes -* **[Shortcuts](#shortcuts)** - supports keyboard shortcuts -* **Picture-in-Picture** - supports Safari's picture-in-picture mode -* **Playsinline** - supports the `playsinline` attribute -* **Speed controls** - adjust speed on the fly -* **Multiple captions** - support for multiple caption tracks -* **i18n support** - support for internationalization of controls -* **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required -* **SASS** - to include in your build processes +- **Responsive** - works with any screen size +- **HTML Video & Audio** - support for both formats +- **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback +- **[Monetization](#ads)** - make money from your videos +- **[Streaming](#try-plyr-online)** - support for hls.js, Shaka and dash.js streaming playback +- **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API +- **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats +- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes +- **[Shortcuts](#shortcuts)** - supports keyboard shortcuts +- **Picture-in-Picture** - supports Safari's picture-in-picture mode +- **Playsinline** - supports the `playsinline` attribute +- **Speed controls** - adjust speed on the fly +- **Multiple captions** - support for multiple caption tracks +- **i18n support** - support for internationalization of controls +- **[Preview thumbnails](#preview-thumbnails)** - support for displaying preview thumbnails +- **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required +- **SASS** - to include in your build processes Oh and yes, it works with Bootstrap. @@ -42,6 +43,7 @@ Some awesome folks have made plugins for CMSs and Components for JavaScript fram | Type | Maintainer | Link | | --------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | WordPress | Brandon Lavigne ([@drrobotnik](https://github.com/drrobotnik)) | [https://wordpress.org/plugins/plyr/](https://wordpress.org/plugins/plyr/) | +| Angular | Simon Bobrov ([@smnbbrv](https://github.com/smnbbrv)) | [https://github.com/smnbbrv/ngx-plyr](https://github.com/smnbbrv/ngx-plyr) | | React | Jose Miguel Bejarano ([@xDae](https://github.com/xDae)) | [https://github.com/xDae/react-plyr](https://github.com/xDae/react-plyr) | | Vue | Gabe Dunn ([@redxtech](https://github.com/redxtech)) | [https://github.com/redxtech/vue-plyr](https://github.com/redxtech/vue-plyr) | | Neos | Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) | [https://packagist.org/packages/jonnitto/plyr](https://packagist.org/packages/jonnitto/plyr) | @@ -51,6 +53,10 @@ Some awesome folks have made plugins for CMSs and Components for JavaScript fram Here's a quick run through on getting up and running. There's also a [demo on Codepen](http://codepen.io/sampotts/pen/jARJYp). You can grab all of the source with [NPM](https://www.npmjs.com/package/plyr) using `npm install plyr`. +### Try Plyr online + +You can try Plyr in Codepen using our minimal templates: [HTML5 video](https://codepen.io/pen?template=bKeqpr), [HTML5 audio](https://codepen.io/pen?template=rKLywR), [YouTube](https://codepen.io/pen?template=GGqbbJ), [Vimeo](https://codepen.io/pen?template=bKeXNq). For Streaming we also have example integrations with: [Dash.js](https://codepen.io/pen?template=zaBgBy), [Hls.js](https://codepen.io/pen?template=oyLKQb) and [Shaka Player](https://codepen.io/pen?template=ZRpzZO) + ### HTML Plyr extends upon the standard [HTML5 media element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement) markup so that's all you need for those types. @@ -59,11 +65,11 @@ Plyr extends upon the standard [HTML5 media element](https://developer.mozilla.o ```html <video poster="/path/to/poster.jpg" id="player" playsinline controls> - <source src="/path/to/video.mp4" type="video/mp4"> - <source src="/path/to/video.webm" type="video/webm"> + <source src="/path/to/video.mp4" type="video/mp4" /> + <source src="/path/to/video.webm" type="video/webm" /> <!-- Captions are optional --> - <track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default> + <track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default /> </video> ``` @@ -71,12 +77,12 @@ Plyr extends upon the standard [HTML5 media element](https://developer.mozilla.o ```html <audio id="player" controls> - <source src="/path/to/audio.mp3" type="audio/mp3"> - <source src="/path/to/audio.ogg" type="audio/ogg"> + <source src="/path/to/audio.mp3" type="audio/mp3" /> + <source src="/path/to/audio.ogg" type="audio/ogg" /> </audio> ``` -For YouTube and Vimeo players, Plyr uses progressive enhancement to enhance the default `<iframe>` embeds. Below are some examples. The `plyr__video-embed` classname will make the embed responsive. You can add the `autoplay`, `loop` and `playsinline` (YouTube only) query parameters to the URL and they will be set as config options automatically. For YouTube, the `origin` should be updated to reflect the domain you're hosting the embed on, or you can opt to omit it. +For YouTube and Vimeo players, Plyr uses progressive enhancement to enhance the default `<iframe>` embeds. Below are some examples. The `plyr__video-embed` classname will make the embed responsive. You can add the `autoplay`, `loop`, `hl` (YouTube only) and `playsinline` (YouTube only) query parameters to the URL and they will be set as config options automatically. For YouTube, the `origin` should be updated to reflect the domain you're hosting the embed on, or you can opt to omit it. #### YouTube embed @@ -84,7 +90,12 @@ We recommend [progressive enhancement](https://www.smashingmagazine.com/2009/04/ ```html <div class="plyr__video-embed" id="player"> - <iframe src="https://www.youtube.com/embed/bTqVqk7FSmY?origin=https://plyr.io&iv_load_policy=3&modestbranding=1&playsinline=1&showinfo=0&rel=0&enablejsapi=1" allowfullscreen allowtransparency allow="autoplay"></iframe> + <iframe + src="https://www.youtube.com/embed/bTqVqk7FSmY?origin=https://plyr.io&iv_load_policy=3&modestbranding=1&playsinline=1&showinfo=0&rel=0&enablejsapi=1" + allowfullscreen + allowtransparency + allow="autoplay" + ></iframe> </div> ``` @@ -104,7 +115,12 @@ Much the same as YouTube above. ```html <div class="plyr__video-embed" id="player"> - <iframe src="https://player.vimeo.com/video/76979871?loop=false&byline=false&portrait=false&title=false&speed=true&transparent=0&gesture=media" allowfullscreen allowtransparency allow="autoplay"></iframe> + <iframe + src="https://player.vimeo.com/video/76979871?loop=false&byline=false&portrait=false&title=false&speed=true&transparent=0&gesture=media" + allowfullscreen + allowtransparency + allow="autoplay" + ></iframe> </div> ``` @@ -120,45 +136,51 @@ Include the `plyr.js` script before the closing `</body>` tag and then in your J ```html <script src="path/to/plyr.js"></script> -<script>const player = new Plyr('#player');</script> +<script> + const player = new Plyr('#player'); +</script> ``` See [initialising](#initialising) for more information on advanced setups. -If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following: +You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build. ```html -<script src="https://cdn.plyr.io/3.3.6/plyr.js"></script> +<script src="https://cdn.plyr.io/3.4.8/plyr.js"></script> ``` -_Note_: Be sure to read the [polyfills](#polyfills) section below about browser compatibility +...or... + +```html +<script src="https://cdn.plyr.io/3.4.8/plyr.polyfilled.js"></script> +``` ### CSS Include the `plyr.css` stylsheet into your `<head>` ```html -<link rel="stylesheet" href="path/to/plyr.css"> +<link rel="stylesheet" href="path/to/plyr.css" /> ``` If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following: ```html -<link rel="stylesheet" href="https://cdn.plyr.io/3.3.6/plyr.css"> +<link rel="stylesheet" href="https://cdn.plyr.io/3.4.8/plyr.css" /> ``` ### SVG Sprite The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For -reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.6/plyr.svg`. +reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.4.8/plyr.svg`. ## Ads -Plyr has partnered up with [vi.ai](http://vi.ai/publisher-video-monetization/?aid=plyrio) to offer monetization options for your videos. Getting setup is easy: +Plyr has partnered up with [vi.ai](https://vi.ai/publisher-video-monetization/?aid=plyrio) to offer monetization options for your videos. Getting setup is easy: -* [Sign up for a vi.ai account](http://vi.ai/publisher-video-monetization/?aid=plyrio) -* Grab your publisher ID from the code snippet -* Enable ads in the [config options](#options) and enter your publisher ID +- [Sign up for a vi.ai account](https://vi.ai/publisher-video-monetization/?aid=plyrio) +- Grab your publisher ID from the code snippet +- Enable ads in the [config options](#options) and enter your publisher ID Any questions regarding the ads can be sent straight to vi.ai and any issues with rendering raised through GitHub issues. @@ -167,7 +189,7 @@ Any questions regarding the ads can be sent straight to vi.ai and any issues wit ### SASS You can use `bundle.scss` file included in `/src` as part of your build and change variables to suit your design. The SASS require you to -use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you be should already!) as all declarations use the W3C definitions. +use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you should be already!) as all declarations use the W3C definitions. The HTML markup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options to match any custom CSS you write. Check out the JavaScript source for more on this. @@ -205,10 +227,10 @@ WebVTT captions are supported. To add a caption track, check the HTML example ab You can specify a range of arguments for the constructor to use: -* A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) -* A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement) -* A [`NodeList]`(https://developer.mozilla.org/en-US/docs/Web/API/NodeList) -* A [jQuery](https://jquery.com) object +- A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) +- A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement) +- A [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) +- A [jQuery](https://jquery.com) object _Note_: If a `NodeList`, `Array`, or jQuery object are passed, the first element will be used for setup. To setup multiple players, see [setting up multiple players](#setting-up-multiple-players) below. @@ -267,46 +289,55 @@ In all cases, the constructor will return a Plyr object that can be used with th Options can be passed as an object to the constructor as above or as JSON in `data-plyr-config` attribute on each of your target elements: ```html -<video src="/path/to/video.mp4" id="player" controls data-plyr-config='{ "title": "This is an example video", "volume": 1, "debug": true }'></video> +<video + src="/path/to/video.mp4" + id="player" + controls + data-plyr-config="{ "title": "This is an example video", "volume": 1, "debug": true }" +></video> ``` Note the single quotes encapsulating the JSON and double quotes on the object keys. Only string values need double quotes. -| Option | Type | Default | Description | -| -------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `enabled` | Boolean | `true` | Completely disable Plyr. This would allow you to do a User Agent check or similar to programmatically enable or disable Plyr for a certain UA. Example below. | -| `debug` | Boolean | `false` | Display debugging information in the console | -| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. | -| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu | -| `i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the text within the UI. | -| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. | -| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. | -| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. | -| `blankUrl` | String | `https://cdn.plyr.io/static/blank.mp4` | Specify a URL or path to a blank video file used to properly cancel network requests. | -| `autoplay` | Boolean | `false` | Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. If the `autoplay` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | -| `autopause`¹ | Boolean | `true` | Only allow one player playing at once. | -| `seekTime` | Number | `10` | The time, in seconds, to seek when a user hits fast forward or rewind. | -| `volume` | Number | `1` | A number, between 0 and 1, representing the initial volume of the player. | -| `muted` | Boolean | `false` | Whether to start playback muted. If the `muted` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | -| `clickToPlay` | Boolean | `true` | Click (or tap) of the video container will toggle play/pause. | -| `disableContextMenu` | Boolean | `true` | Disable right click menu on video to <em>help</em> as very primitive obfuscation to prevent downloads of content. | -| `hideControls` | Boolean | `true` | Hide video controls automatically after 2s of no mouse or focus movement, on control element blur (tab out), on playback start or entering fullscreen. As soon as the mouse is moved, a control element is focused or playback is paused, the controls reappear instantly. | -| `resetOnEnd` | Boolean | false | Reset the playback to the start once playback is complete. | -| `keyboard` | Object | `{ focused: true, global: false }` | Enable [keyboard shortcuts](#shortcuts) for focused players only or globally | -| `tooltips` | Object | `{ controls: false, seek: true }` | `controls`: Display control labels as tooltips on `:hover` & `:focus` (by default, the labels are screen reader only). `seek`: Display a seek tooltip to indicate on click where the media would seek to. | -| `duration` | Number | `null` | Specify a custom duration for media. | -| `displayDuration` | Boolean | `true` | Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see `controls` option). | -| `invertTime` | Boolean | `true` | Display the current time as a countdown rather than an incremental counter. | -| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. | -| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. | -| `captions` | Object | `{ active: false, language: window.navigator.language.split('-')[0] }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). | -| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution. `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls) | -| `ratio` | String | `16:9` | The aspect ratio you want to use for embedded players. | -| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. | -| `speed` | Object | `{ selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }` | `selected`: The default speed for playback. `options`: Options to display in the menu. Most browsers will refuse to play slower than 0.5. | -| `quality` | Object | `{ default: 'default', options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'] }` | Currently only supported by YouTube. `default` is the default quality level, determined by YouTube. `options` are the options to display. | -| `loop` | Object | `{ active: false }` | `active`: Whether to loop the current video. If the `loop` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true This is an object to support future functionality. | -| `ads` | Object | `{ enabled: false, publisherId: '' }` | `enabled`: Whether to enable vi.ai ads. `publisherId`: Your unique vi.ai publisher ID. | +| Option | Type | Default | Description | +| -------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `enabled` | Boolean | `true` | Completely disable Plyr. This would allow you to do a User Agent check or similar to programmatically enable or disable Plyr for a certain UA. Example below. | +| `debug` | Boolean | `false` | Display debugging information in the console | +| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. | +| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu | +| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. | +| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. | +| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. | +| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. | +| `blankVideo` | String | `https://cdn.plyr.io/static/blank.mp4` | Specify a URL or path to a blank video file used to properly cancel network requests. | +| `autoplay` | Boolean | `false` | Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. If the `autoplay` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | +| `autopause`¹ | Boolean | `true` | Only allow one player playing at once. | +| `seekTime` | Number | `10` | The time, in seconds, to seek when a user hits fast forward or rewind. | +| `volume` | Number | `1` | A number, between 0 and 1, representing the initial volume of the player. | +| `muted` | Boolean | `false` | Whether to start playback muted. If the `muted` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. | +| `clickToPlay` | Boolean | `true` | Click (or tap) of the video container will toggle play/pause. | +| `disableContextMenu` | Boolean | `true` | Disable right click menu on video to <em>help</em> as very primitive obfuscation to prevent downloads of content. | +| `hideControls` | Boolean | `true` | Hide video controls automatically after 2s of no mouse or focus movement, on control element blur (tab out), on playback start or entering fullscreen. As soon as the mouse is moved, a control element is focused or playback is paused, the controls reappear instantly. | +| `resetOnEnd` | Boolean | false | Reset the playback to the start once playback is complete. | +| `keyboard` | Object | `{ focused: true, global: false }` | Enable [keyboard shortcuts](#shortcuts) for focused players only or globally | +| `tooltips` | Object | `{ controls: false, seek: true }` | `controls`: Display control labels as tooltips on `:hover` & `:focus` (by default, the labels are screen reader only). `seek`: Display a seek tooltip to indicate on click where the media would seek to. | +| `duration` | Number | `null` | Specify a custom duration for media. | +| `displayDuration` | Boolean | `true` | Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see `controls` option). | +| `invertTime` | Boolean | `true` | Display the current time as a countdown rather than an incremental counter. | +| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. | +| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. | +| `captions` | Object | `{ active: false, language: 'auto', update: false }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). 'auto' uses the browser language. `update`: Listen to changes to tracks and update menu. This is needed for some streaming libraries, but can result in unselectable language options). | +| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution (`true`/`false`/`'force'`). `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls) | +| `ratio` | String | `16:9` | The aspect ratio you want to use for embedded players. | +| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. | +| `speed` | Object | `{ selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }` | `selected`: The default speed for playback. `options`: Options to display in the menu. Most browsers will refuse to play slower than 0.5. | +| `quality` | Object | `{ default: 'default', options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'] }` | Currently only supported by YouTube. `default` is the default quality level, determined by YouTube. `options` are the options to display. | +| `loop` | Object | `{ active: false }` | `active`: Whether to loop the current video. If the `loop` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true This is an object to support future functionality. | +| `ads` | Object | `{ enabled: false, publisherId: '' }` | `enabled`: Whether to enable advertisements. `publisherId`: Your unique [vi.ai](https://vi.ai/publisher-video-monetization/?aid=plyrio) publisher ID. | +| `urls` | Object | See source. | If you wish to override any API URLs then you can do so here. You can also set a custom download URL for the download button. | +| `vimeo` | Object | `{ byline: false, portrait: false, title: false, speed: true, transparent: false }` | See [Vimeo embed options](https://github.com/vimeo/player.js/#embed-options). Some are set automatically based on other config options, namely: `loop`, `autoplay`, `muted`, `gesture`, `playsinline` | +| `youtube` | Object | `{ noCookie: false, rel: 0, showinfo: 0, iv_load_policy: 3, modestbranding: 1 }` | See [YouTube embed options](https://developers.google.com/youtube/player_parameters#Parameters). The only custom option is `noCookie` to use an alternative to YouTube that doesn't use cookies (useful for GDPR, etc). Some are set automatically based on other config options, namely: `autoplay`, `hl`, `controls`, `disablekb`, `playsinline`, `cc_load_policy`, `cc_lang_pref`, `widget_referrer` | +| `previewThumbnails` | Object | `{ enabled: false, src: '' }` | `enabled`: Whether to enable the preview thumbnails (they must be generated by you). `src` must be either a string or an array of strings representing URLs for the VTT files containing the image URL(s). Learn more about [preview thumbnails](#preview-thumbnails) below. | 1. Vimeo only @@ -357,8 +388,9 @@ player.fullscreen.enter(); // Enter fullscreen | `fullscreen.exit()` | - | Exit fullscreen. | | `fullscreen.toggle()` | - | Toggle fullscreen. | | `airplay()` | - | Trigger the airplay dialog on supported devices. | -| `toggleControls(toggle)` | Boolean | Toggle the controls based on the specified boolean. | +| `toggleControls(toggle)` | Boolean | Toggle the controls (video only). Takes optional truthy value to force it on/off. | | `on(event, function)` | String, Function | Add an event listener for the specified event. | +| `once(event, function)` | String, Function | Add an event listener for the specified event once. | | `off(event, function)` | String, Function | Remove an event listener for the specified event. | | `supports(type)` | String | Check support for a mime type. | | `destroy()` | - | Destroy the instance and garbage collect any elements. | @@ -382,31 +414,32 @@ player.currentTime; // 10 player.fullscreen.active; // false; ``` -| Property | Getter | Setter | Description | -| -------------------- | ------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `isHTML5` | ✓ | - | Returns a boolean indicating if the current player is HTML5. | -| `isEmbed` | ✓ | - | Returns a boolean indicating if the current player is an embedded player. | -| `playing` | ✓ | - | Returns a boolean indicating if the current player is playing. | -| `paused` | ✓ | - | Returns a boolean indicating if the current player is paused. | -| `stopped` | ✓ | - | Returns a boolean indicating if the current player is stopped. | -| `ended` | ✓ | - | Returns a boolean indicating if the current player has finished playback. | -| `buffered` | ✓ | - | Returns a float between 0 and 1 indicating how much of the media is buffered | -| `currentTime` | ✓ | ✓ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. | -| `seeking` | ✓ | - | Returns a boolean indicating if the current player is seeking. | -| `duration` | ✓ | - | Returns the duration for the current media. | -| `volume` | ✓ | ✓ | Gets or sets the volume for the player. The setter accepts a float between 0 and 1. | -| `muted` | ✓ | ✓ | Gets or sets the muted state of the player. The setter accepts a boolean. | -| `hasAudio` | ✓ | - | Returns a boolean indicating if the current media has an audio track. | -| `speed` | ✓ | ✓ | Gets or sets the speed for the player. The setter accepts a value in the options specified in your config. Generally the minimum should be 0.5. | -| `quality`¹ | ✓ | ✓ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. | -| `loop` | ✓ | ✓ | Gets or sets the current loop state of the player. The setter accepts a boolean. | -| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#source-setter) below for examples. | -| `poster` | ✓ | ✓ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. | -| `autoplay` | ✓ | ✓ | Gets or sets the autoplay state of the player. The setter accepts a boolean. | -| `language` | ✓ | ✓ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. | -| `fullscreen.active` | ✓ | - | Returns a boolean indicating if the current player is in fullscreen mode. | -| `fullscreen.enabled` | ✓ | - | Returns a boolean indicating if the current player has fullscreen enabled. | -| `pip` | ✓ | ✓ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ on MacOS Sierra+ and iOS 10+. | +| Property | Getter | Setter | Description | +| -------------------- | ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `isHTML5` | ✓ | - | Returns a boolean indicating if the current player is HTML5. | +| `isEmbed` | ✓ | - | Returns a boolean indicating if the current player is an embedded player. | +| `playing` | ✓ | - | Returns a boolean indicating if the current player is playing. | +| `paused` | ✓ | - | Returns a boolean indicating if the current player is paused. | +| `stopped` | ✓ | - | Returns a boolean indicating if the current player is stopped. | +| `ended` | ✓ | - | Returns a boolean indicating if the current player has finished playback. | +| `buffered` | ✓ | - | Returns a float between 0 and 1 indicating how much of the media is buffered | +| `currentTime` | ✓ | ✓ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. | +| `seeking` | ✓ | - | Returns a boolean indicating if the current player is seeking. | +| `duration` | ✓ | - | Returns the duration for the current media. | +| `volume` | ✓ | ✓ | Gets or sets the volume for the player. The setter accepts a float between 0 and 1. | +| `muted` | ✓ | ✓ | Gets or sets the muted state of the player. The setter accepts a boolean. | +| `hasAudio` | ✓ | - | Returns a boolean indicating if the current media has an audio track. | +| `speed` | ✓ | ✓ | Gets or sets the speed for the player. The setter accepts a value in the options specified in your config. Generally the minimum should be 0.5. | +| `quality`¹ | ✓ | ✓ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. | +| `loop` | ✓ | ✓ | Gets or sets the current loop state of the player. The setter accepts a boolean. | +| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#the-source-setter) below for examples. | +| `poster` | ✓ | ✓ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. | +| `autoplay` | ✓ | ✓ | Gets or sets the autoplay state of the player. The setter accepts a boolean. | +| `currentTrack` | ✓ | ✓ | Gets or sets the caption track by index. `-1` means the track is missing or captions is not active | +| `language` | ✓ | ✓ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. If your captions don't have any language data, or if you have multiple tracks with the same language, you may want to use `currentTrack` instead. | +| `fullscreen.active` | ✓ | - | Returns a boolean indicating if the current player is in fullscreen mode. | +| `fullscreen.enabled` | ✓ | - | Returns a boolean indicating if the current player has fullscreen enabled. | +| `pip`² | ✓ | ✓ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ (on MacOS Sierra+ and iOS 10+) and Chrome 70+. | 1. YouTube only. HTML5 will follow. 2. HTML5 only @@ -425,10 +458,12 @@ player.source = { { src: '/path/to/movie.mp4', type: 'video/mp4', + size: 720, }, { src: '/path/to/movie.webm', type: 'video/webm', + size: 1080, }, ], poster: '/path/to/poster.jpg', @@ -553,6 +588,7 @@ player.on('ready', event => { | `loadstart` | Sent when loading of the media begins. | | `loadeddata` | The first frame of the media has finished loading. | | `loadedmetadata` | The media's metadata has finished loading; all attributes now contain as much useful information as they're going to. | +| `qualitychange` | The quality of playback has changed. | | `canplay` | Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the `HAVE_ENOUGH_DATA` `readyState`. | | `canplaythrough` | Sent when the ready state changes to `CAN_PLAY_THROUGH`, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. _Note:_ Manually setting the `currentTime` will eventually fire a `canplaythrough` event in firefox. Other browsers might not fire this event. | | `stalled` | Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. | @@ -563,11 +599,9 @@ player.on('ready', event => { #### YouTube only -| Event Type | Description | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. | -| `qualitychange` | The quality of playback has changed. | -| `qualityrequested` | A change to playback quality has been requested. _Note:_ A change to quality can only be _requested_ via the API. There is no guarantee the quality will change to the level requested. You should listen to the `qualitychange` event for true changes. | +| Event Type | Description | +| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. | _Note:_ These events also bubble up the DOM. The event target will be the container element. @@ -579,8 +613,8 @@ YouTube and Vimeo are currently supported and function much like a HTML5 video. to access the API's directly. You can do so via the `embed` property of your player object - e.g. `player.embed`. You can then use the relevant methods from the third party APIs. More info on the respective API's here: -* [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference) -* [Vimeo player.js Reference](https://github.com/vimeo/player.js) +- [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference) +- [Vimeo player.js Reference](https://github.com/vimeo/player.js) _Note_: Not all API methods may work 100%. Your mileage may vary. It's better to use the Plyr API where possible. @@ -603,17 +637,6 @@ document then the shortcuts will work when any element has focus, apart from an | `C` | Toggle captions | | `L` | Toggle loop | -## Streaming - -Because Plyr is an extension of the standard HTML5 video and audio elements, third party streaming plugins can be used with Plyr. Massive thanks to Matias -Russitto ([@russitto](https://github.com/russitto)) for working on this. Here's a few examples: - -* Using [hls.js](https://github.com/dailymotion/hls.js) - [Demo](http://codepen.io/sampotts/pen/JKEMqB) -* Using [Shaka](https://github.com/google/shaka-player) - [Demo](http://codepen.io/sampotts/pen/zBNpVR) -* Using [dash.js](https://github.com/Dash-Industry-Forum/dash.js) - [Demo](http://codepen.io/sampotts/pen/BzpJXN) - -_Note_: These need updating to use the new v3 syntax but would still work. - ## Fullscreen Fullscreen in Plyr is supported by all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). @@ -637,6 +660,12 @@ Plyr supports the last 2 versions of most _modern_ browsers. 2. Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported. No native fullscreen support, fallback can be used (see [options](#options)). 3. Polyfills required. See below. +## Preview thumbnails + +It's possible to display preview thumbnails as per the demo when you hover over the scrubber or while you are scrubbing in the main video area. This can be used for all video types but is easiest with HTML5 of course. You will need to generate the sprite or images yourself. This is possible using something like AWS transcoder to generate the frames and then combine them into a sprite image. Sprites are recommended for performance reasons - they will be much faster to download and easier to compress into a small file size making them load faster. + +You can see the example VTT files [here](https://cdn.plyr.io/static/demo/thumbs/100p.vtt) and [here](https://cdn.plyr.io/static/demo/thumbs/240p.vtt) for how the sprites are done. The coordinates are set as the `xywh` hash on the URL in the order X Offset, Y Offset, Width, Height (e.g. `240p-00001.jpg#xywh=1708,480,427,240` is offset `1708px` from the left, `480px` from the top and is `427x240px`. If you want to include images per frame, this is also possible but will be slower, resulting in a degraded experience. + ### Polyfills Plyr uses ES6 which isn't supported in all browsers quite yet. This means some features will need to be polyfilled to be available otherwise you'll run into issues. We've elected to not burden the ~90% of users that do support these features with extra JS and instead leave polyfilling to you to work out based on your needs. The easiest method I've found is to use [polyfill.io](https://polyfill.io) which provides polyfills based on user agent. This is the method the demo uses. @@ -651,9 +680,9 @@ const supported = Plyr.supported('video', 'html5', true); The arguments are: -* Media type (`audio` or `video`) -* Provider (`html5`, `youtube` or `vimeo`) -* Whether the player has the `playsinline` attribute (only applicable to iOS 10+) +- Media type (`audio` or `video`) +- Provider (`html5`, `youtube` or `vimeo`) +- Whether the player has the `playsinline` attribute (only applicable to iOS 10+) ### Disable support programatically @@ -686,33 +715,34 @@ Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me] Plyr costs money to run, not only my time. I donate my time for free as I enjoy building Plyr but unfortunately have to pay for domains, hosting, and more. Any help with costs is appreciated... -* [Donate via Patron](https://www.patreon.com/plyr) -* [Donate via PayPal](https://www.paypal.me/pottsy/20usd) +- [Donate via Patreon](https://www.patreon.com/plyr) +- [Donate via PayPal](https://www.paypal.me/pottsy/20usd) ## Mentions -* [ProductHunt](https://www.producthunt.com/tech/plyr) -* [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) -* [HTML5 Weekly #177](http://html5weekly.com/issues/177) -* [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f) -* [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) -* [Hacker News](https://news.ycombinator.com/item?id=9136774) -* [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) -* [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) -* [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images) -* [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html) +- [ProductHunt](https://www.producthunt.com/tech/plyr) +- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) +- [HTML5 Weekly #177](http://html5weekly.com/issues/177) +- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f) +- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) +- [Hacker News](https://news.ycombinator.com/item?id=9136774) +- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) +- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) +- [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images) +- [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html) ## Used by -* [Selz.com](https://selz.com) -* [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html) -* [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html) -* [TomTom.com](http://prioritydriving.tomtom.com/) -* [DIGBMX](http://digbmx.com/) -* [Grime Archive](https://grimearchive.com/) -* [koel - A personal music streaming server that works.](http://koel.phanan.net/) -* [Oscar Radio](http://oscar-radio.xyz/) -* [Sparkk TV](https://www.sparkktv.com/) +- [Selz.com](https://selz.com) +- [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html) +- [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html) +- [TomTom.com](http://prioritydriving.tomtom.com/) +- [DIGBMX](http://digbmx.com/) +- [Grime Archive](https://grimearchive.com/) +- [koel - A personal music streaming server that works.](http://koel.phanan.net/) +- [Oscar Radio](http://oscar-radio.xyz/) +- [Sparkk TV](https://www.sparkktv.com/) +- [@halfhalftravel](https://www.halfhalftravel.com/) Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the above list. It'd be awesome to see how you're using Plyr :-) @@ -720,8 +750,8 @@ Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the abo Credit to the PayPal HTML5 Video player from which Plyr's caption functionality was originally ported from: -* [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player) -* [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw) +- [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player) +- [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw) ## Thanks diff --git a/src/js/captions.js b/src/js/captions.js index e0692dcf..ae4642aa 100644 --- a/src/js/captions.js +++ b/src/js/captions.js @@ -4,9 +4,23 @@ // ========================================================================== import controls from './controls'; -import i18n from './i18n'; import support from './support'; -import utils from './utils'; +import { dedupe } from './utils/arrays'; +import browser from './utils/browser'; +import { + createElement, + emptyElement, + getAttributesFromSelector, + insertAfter, + removeElement, + toggleClass, +} from './utils/elements'; +import { on, triggerEvent } from './utils/events'; +import fetch from './utils/fetch'; +import i18n from './utils/i18n'; +import is from './utils/is'; +import { getHTML } from './utils/strings'; +import { parseUrl } from './utils/urls'; const captions = { // Setup captions @@ -16,32 +30,14 @@ const captions = { return; } - // Set default language if not set - const stored = this.storage.get('language'); - - if (!utils.is.empty(stored)) { - this.captions.language = stored; - } - - if (utils.is.empty(this.captions.language)) { - this.captions.language = this.config.captions.language.toLowerCase(); - } - - // Set captions enabled state if not set - if (!utils.is.boolean(this.captions.active)) { - const active = this.storage.get('captions'); - - if (utils.is.boolean(active)) { - this.captions.active = active; - } else { - this.captions.active = this.config.captions.active; - } - } - // Only Vimeo and HTML5 video supported at this point if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) { // Clear menu and hide - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + if ( + is.array(this.config.controls) && + this.config.controls.includes('settings') && + this.config.settings.includes('captions') + ) { controls.setCaptionsMenu.call(this); } @@ -49,26 +45,12 @@ const captions = { } // Inject the container - if (!utils.is.element(this.elements.captions)) { - this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions)); + if (!is.element(this.elements.captions)) { + this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions)); - utils.insertAfter(this.elements.captions, this.elements.wrapper); + insertAfter(this.elements.captions, this.elements.wrapper); } - // Set the class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); - - // Get tracks - const tracks = captions.getTracks.call(this); - - // If no caption file exists, hide container for caption text - if (utils.is.empty(tracks)) { - return; - } - - // Get browser info - const browser = utils.getBrowser(); - // Fix IE captions if CORS is used // Fetch captions and inject as blobs instead (data URIs not supported!) if (browser.isIE && window.URL) { @@ -76,116 +58,275 @@ const captions = { Array.from(elements).forEach(track => { const src = track.getAttribute('src'); - const href = utils.parseUrl(src); - - if (href.hostname !== window.location.href.hostname && [ - 'http:', - 'https:', - ].includes(href.protocol)) { - utils - .fetch(src, 'blob') + const url = parseUrl(src); + + if ( + url !== null && + url.hostname !== window.location.href.hostname && + ['http:', 'https:'].includes(url.protocol) + ) { + fetch(src, 'blob') .then(blob => { track.setAttribute('src', window.URL.createObjectURL(blob)); }) .catch(() => { - utils.removeElement(track); + removeElement(track); }); } }); } - // Set language - captions.setLanguage.call(this); + // Get and set initial data + // The "preferred" options are not realized unless / until the wanted language has a match + // * languages: Array of user's browser languages. + // * language: The language preferred by user settings or config + // * active: The state preferred by user settings or config + // * toggled: The real captions state - // Enable UI - captions.show.call(this); + const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; + const languages = dedupe(browserLanguages.map(language => language.split('-')[0])); - // Set available languages in list - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { - controls.setCaptionsMenu.call(this); + let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); + + // Use first browser language when language is 'auto' + if (language === 'auto') { + [language] = languages; + } + + let active = this.storage.get('captions'); + if (!is.boolean(active)) { + ({ active } = this.config.captions); + } + + Object.assign(this.captions, { + toggled: false, + active, + language, + languages, + }); + + // Watch changes to textTracks and update captions menu + if (this.isHTML5) { + const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack'; + on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this)); } + + // Update available languages in list next tick (the event must not be triggered before the listeners) + setTimeout(captions.update.bind(this), 0); }, - // Set the captions language - setLanguage() { - // Setup HTML5 track rendering + // Update available language options in settings based on tracks + update() { + const tracks = captions.getTracks.call(this, true); + // Get the wanted language + const { active, language, meta, currentTrackNode } = this.captions; + const languageExists = Boolean(tracks.find(track => track.language === language)); + + // Handle tracks (add event listener and "pseudo"-default) if (this.isHTML5 && this.isVideo) { - captions.getTracks.call(this).forEach(track => { - // Show track - utils.on(track, 'cuechange', event => captions.setCue.call(this, event)); + tracks.filter(track => !meta.get(track)).forEach(track => { + this.debug.log('Track added', track); + // Attempt to store if the original dom element was "default" + meta.set(track, { + default: track.mode === 'showing', + }); // Turn off native caption rendering to avoid double captions - // eslint-disable-next-line track.mode = 'hidden'; + + // Add event listener for cue changes + on.call(this, track, 'cuechange', () => captions.updateCues.call(this)); }); + } - // Get current track - const currentTrack = captions.getCurrentTrack.call(this); + // Update language first time it matches, or if the previous matching track was removed + if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) { + captions.setLanguage.call(this, language); + captions.toggle.call(this, active && languageExists); + } - // Check if suported kind - if (utils.is.track(currentTrack)) { - // If we change the active track while a cue is already displayed we need to update it - if (Array.from(currentTrack.activeCues || []).length) { - captions.setCue.call(this, currentTrack); - } - } - } else if (this.isVimeo && this.captions.active) { - this.embed.enableTextTrack(this.language); + // Enable or disable captions based on track length + toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks)); + + // Update available languages in list + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { + controls.setCaptionsMenu.call(this); } }, - // Get the tracks - getTracks() { - // Return empty array at least - if (utils.is.nullOrUndefined(this.media)) { - return []; + // Toggle captions display + // Used internally for the toggleCaptions method, with the passive option forced to false + toggle(input, passive = true) { + // If there's no full support + if (!this.supported.ui) { + return; } - // Only get accepted kinds - return Array.from(this.media.textTracks || []).filter(track => [ - 'captions', - 'subtitles', - ].includes(track.kind)); + const { toggled } = this.captions; // Current state + const activeClass = this.config.classNames.captions.active; + + // Get the next state + // If the method is called without parameter, toggle based on current value + const active = is.nullOrUndefined(input) ? !toggled : input; + + // Update state and trigger event + if (active !== toggled) { + // When passive, don't override user preferences + if (!passive) { + this.captions.active = active; + this.storage.set({ captions: active }); + } + + // Force language if the call isn't passive and there is no matching language to toggle to + if (!this.language && active && !passive) { + const tracks = captions.getTracks.call(this); + const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true); + + // Override user preferences to avoid switching languages if a matching track is added + this.captions.language = track.language; + + // Set caption, but don't store in localStorage as user preference + captions.set.call(this, tracks.indexOf(track)); + return; + } + + // Toggle button if it's enabled + if (this.elements.buttons.captions) { + this.elements.buttons.captions.pressed = active; + } + + // Add class hook + toggleClass(this.elements.container, activeClass, active); + + this.captions.toggled = active; + + // Update settings menu + controls.updateSetting.call(this, 'captions'); + + // Trigger event (not used internally) + triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); + } }, - // Get the current track for the current language - getCurrentTrack() { + // Set captions by track index + // Used internally for the currentTrack setter with the passive option forced to false + set(index, passive = true) { const tracks = captions.getTracks.call(this); - if (!tracks.length) { - return null; + // Disable captions if setting to -1 + if (index === -1) { + captions.toggle.call(this, false, passive); + return; } - // Get track based on current language - let track = tracks.find(track => track.language.toLowerCase() === this.language); + if (!is.number(index)) { + this.debug.warn('Invalid caption argument', index); + return; + } - // Get the <track> with default attribute - if (!track) { - track = utils.getElement.call(this, 'track[default]'); + if (!(index in tracks)) { + this.debug.warn('Track not found', index); + return; } - // Get the first track - if (!track) { - [track] = tracks; + if (this.captions.currentTrack !== index) { + this.captions.currentTrack = index; + const track = tracks[index]; + const { language } = track || {}; + + // Store reference to node for invalidation on remove + this.captions.currentTrackNode = track; + + // Update settings menu + controls.updateSetting.call(this, 'captions'); + + // When passive, don't override user preferences + if (!passive) { + this.captions.language = language; + this.storage.set({ language }); + } + + // Handle Vimeo captions + if (this.isVimeo) { + this.embed.enableTextTrack(language); + } + + // Trigger event + triggerEvent.call(this, this.media, 'languagechange'); + } + + // Show captions + captions.toggle.call(this, true, passive); + + if (this.isHTML5 && this.isVideo) { + // If we change the active track while a cue is already displayed we need to update it + captions.updateCues.call(this); + } + }, + + // Set captions by language + // Used internally for the language setter with the passive option forced to false + setLanguage(input, passive = true) { + if (!is.string(input)) { + this.debug.warn('Invalid language argument', input); + return; } + // Normalize + const language = input.toLowerCase(); + this.captions.language = language; + + // Set currentTrack + const tracks = captions.getTracks.call(this); + const track = captions.findTrack.call(this, [language]); + captions.set.call(this, tracks.indexOf(track), passive); + }, - return track; + // Get current valid caption tracks + // If update is false it will also ignore tracks without metadata + // This is used to "freeze" the language options when captions.update is false + getTracks(update = false) { + // Handle media or textTracks missing or null + const tracks = Array.from((this.media || {}).textTracks || []); + // For HTML5, use cache instead of current tracks when it exists (if captions.update is false) + // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) + return tracks + .filter(track => !this.isHTML5 || update || this.captions.meta.has(track)) + .filter(track => ['captions', 'subtitles'].includes(track.kind)); + }, + + // Match tracks based on languages and get the first + findTrack(languages, force = false) { + const tracks = captions.getTracks.call(this); + const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default); + const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a)); + let track; + languages.every(language => { + track = sorted.find(track => track.language === language); + return !track; // Break iteration if there is a match + }); + // If no match is found but is required, get first + return track || (force ? sorted[0] : undefined); + }, + + // Get the current track + getCurrentTrack() { + return captions.getTracks.call(this)[this.currentTrack]; }, // Get UI label for track getLabel(track) { let currentTrack = track; - if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) { + if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) { currentTrack = captions.getCurrentTrack.call(this); } - if (utils.is.track(currentTrack)) { - if (!utils.is.empty(currentTrack.label)) { + if (is.track(currentTrack)) { + if (!is.empty(currentTrack.label)) { return currentTrack.label; } - if (!utils.is.empty(currentTrack.language)) { + if (!is.empty(currentTrack.language)) { return track.language.toUpperCase(); } @@ -195,74 +336,48 @@ const captions = { return i18n.get('disabled', this.config); }, - // Display active caption if it contains text - setCue(input) { - // Get the track from the event if needed - const track = utils.is.event(input) ? input.target : input; - const { activeCues } = track; - const active = activeCues.length && activeCues[0]; - const currentTrack = captions.getCurrentTrack.call(this); - - // Only display current track - if (track !== currentTrack) { + // Update captions using current track's active cues + // Also optional array argument in case there isn't any track (ex: vimeo) + updateCues(input) { + // Requires UI + if (!this.supported.ui) { return; } - // Display a cue, if there is one - if (utils.is.cue(active)) { - captions.setText.call(this, active.getCueAsHTML()); - } else { - captions.setText.call(this, null); + if (!is.element(this.elements.captions)) { + this.debug.warn('No captions element to render to'); + return; } - utils.dispatchEvent.call(this, this.media, 'cuechange'); - }, - - // Set the current caption - setText(input) { - // Requires UI - if (!this.supported.ui) { + // Only accept array or empty input + if (!is.nullOrUndefined(input) && !Array.isArray(input)) { + this.debug.warn('updateCues: Invalid input', input); return; } - if (utils.is.element(this.elements.captions)) { - const content = utils.createElement('span'); - - // Empty the container - utils.emptyElement(this.elements.captions); - - // Default to empty - const caption = !utils.is.nullOrUndefined(input) ? input : ''; - - // Set the span content - if (utils.is.string(caption)) { - content.textContent = caption.trim(); - } else { - content.appendChild(caption); - } + let cues = input; - // Set new caption text - this.elements.captions.appendChild(content); - } else { - this.debug.warn('No captions element to render to'); + // Get cues from track + if (!cues) { + const track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []) + .map(cue => cue.getCueAsHTML()) + .map(getHTML); } - }, - // Display captions container and button (for initialization) - show() { - // Try to load the value from storage - let active = this.storage.get('captions'); + // Set new caption text + const content = cues.map(cueText => cueText.trim()).join('\n'); + const changed = content !== this.elements.captions.innerHTML; - // Otherwise fall back to the default config - if (!utils.is.boolean(active)) { - ({ active } = this.config.captions); - } else { - this.captions.active = active; - } + if (changed) { + // Empty the container and create a new child element + emptyElement(this.elements.captions); + const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption)); + caption.innerHTML = content; + this.elements.captions.appendChild(caption); - if (active) { - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true); - utils.toggleState(this.elements.buttons.captions, true); + // Trigger event + triggerEvent.call(this, this.media, 'cuechange'); } }, }; diff --git a/src/js/defaults.js b/src/js/config/defaults.js index a28f56ee..0044d409 100644 --- a/src/js/defaults.js +++ b/src/js/config/defaults.js @@ -18,6 +18,10 @@ const defaults = { // Only allow one media playing at once (vimeo only) autopause: true, + // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present) + // TODO: Remove iosNative fullscreen option in favour of this (logic needs work) + playsinline: true, + // Default time to skip when rewind/fast forward seekTime: 10, @@ -56,7 +60,7 @@ const defaults = { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.4.8/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', @@ -64,19 +68,7 @@ const defaults = { // Quality default quality: { default: 576, - options: [ - 4320, - 2880, - 2160, - 1440, - 1080, - 720, - 576, - 480, - 360, - 240, - 'default', // YouTube's "auto" - ], + options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240], }, // Set loops @@ -89,15 +81,7 @@ const defaults = { // Speed default and options to display speed: { selected: 1, - options: [ - 0.5, - 0.75, - 1, - 1.25, - 1.5, - 1.75, - 2, - ], + options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2], }, // Keyboard shortcut settings @@ -115,13 +99,16 @@ const defaults = { // Captions settings captions: { active: false, - language: (navigator.language || navigator.userLanguage).split('-')[0], + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false, }, // Fullscreen settings fullscreen: { enabled: true, // Allow fullscreen? - fallback: true, // Fallback for vintage browsers + fallback: true, // Fallback using full viewport/window iosNative: false, // Use the native fullscreen in iOS (disables custom controls) }, @@ -146,13 +133,10 @@ const defaults = { 'settings', 'pip', 'airplay', + // 'download', 'fullscreen', ], - settings: [ - 'captions', - 'quality', - 'speed', - ], + settings: ['captions', 'quality', 'speed'], // Localisation i18n: { @@ -162,6 +146,7 @@ const defaults = { pause: 'Pause', fastForward: 'Forward {seektime}s', seek: 'Seek', + seekLabel: '{currentTime} of {duration}', played: 'Played', buffered: 'Buffered', currentTime: 'Current time', @@ -171,11 +156,13 @@ const defaults = { unmute: 'Unmute', enableCaptions: 'Enable captions', disableCaptions: 'Disable captions', + download: 'Download', enterFullscreen: 'Enter fullscreen', exitFullscreen: 'Exit fullscreen', frameTitle: 'Player for {title}', captions: 'Captions', settings: 'Settings', + menuBack: 'Go back to previous menu', speed: 'Speed', normal: 'Normal', quality: 'Quality', @@ -187,10 +174,19 @@ const defaults = { disabled: 'Disabled', enabled: 'Enabled', advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD', + }, }, // URLs urls: { + download: null, vimeo: { sdk: 'https://player.vimeo.com/api/player.js', iframe: 'https://player.vimeo.com/video/{0}?{1}', @@ -198,8 +194,8 @@ const defaults = { }, youtube: { sdk: 'https://www.youtube.com/iframe_api', - api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', - poster: 'https://img.youtube.com/vi/{0}/maxresdefault.jpg,https://img.youtube.com/vi/{0}/hqdefault.jpg', + api: + 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js', @@ -217,6 +213,7 @@ const defaults = { mute: null, volume: null, captions: null, + download: null, fullscreen: null, pip: null, airplay: null, @@ -252,6 +249,7 @@ const defaults = { 'cuechange', // Custom events + 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', @@ -263,8 +261,9 @@ const defaults = { // YouTube 'statechange', + + // Quality 'qualitychange', - 'qualityrequested', // Ads 'adsloaded', @@ -296,6 +295,7 @@ const defaults = { fastForward: '[data-plyr="fast-forward"]', mute: '[data-plyr="mute"]', captions: '[data-plyr="captions"]', + download: '[data-plyr="download"]', fullscreen: '[data-plyr="fullscreen"]', pip: '[data-plyr="pip"]', airplay: '[data-plyr="airplay"]', @@ -312,13 +312,13 @@ const defaults = { display: { currentTime: '.plyr__time--current', duration: '.plyr__time--duration', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played', - loop: '.plyr__progress--loop', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', // Used later volume: '.plyr__volume--display', }, progress: '.plyr__progress', captions: '.plyr__captions', + caption: '.plyr__caption', menu: { quality: '.js-plyr__menu__list--quality', }, @@ -332,13 +332,14 @@ const defaults = { embed: 'plyr__video-embed', embedContainer: 'plyr__video-embed__container', poster: 'plyr__poster', + posterEnabled: 'plyr__poster-enabled', ads: 'plyr__ads', control: 'plyr__control', + controlPressed: 'plyr__control--pressed', playing: 'plyr--playing', paused: 'plyr--paused', stopped: 'plyr--stopped', loading: 'plyr--loading', - error: 'plyr--has-error', hover: 'plyr--hover', tooltip: 'plyr__tooltip', cues: 'plyr__cues', @@ -348,6 +349,9 @@ const defaults = { isTouch: 'plyr--is-touch', uiSupported: 'plyr--full-ui', noTransition: 'plyr--no-transition', + display: { + time: 'plyr__time', + }, menu: { value: 'plyr__menu__value', badge: 'plyr__badge', @@ -370,6 +374,16 @@ const defaults = { active: 'plyr--airplay-active', }, tabFocus: 'plyr__tab-focus', + previewThumbnails: { + // Tooltip thumbs + thumbContainer: 'plyr__preview-thumb', + thumbContainerShown: 'plyr__preview-thumb--is-shown', + imageContainer: 'plyr__preview-thumb__image-container', + timeContainer: 'plyr__preview-thumb__time-container', + // Scrubbing + scrubbingContainer: 'plyr__preview-scrubbing', + scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown', + }, }, // Embed attributes @@ -390,6 +404,31 @@ const defaults = { ads: { enabled: false, publisherId: '', + tagUrl: '', + }, + + // Preview Thumbnails plugin + previewThumbnails: { + enabled: false, + src: '', + }, + + // Vimeo plugin + vimeo: { + byline: false, + portrait: false, + title: false, + speed: true, + transparent: false, + }, + + // YouTube plugin + youtube: { + noCookie: false, // Whether to use an alternative version of YouTube without cookies + rel: 0, // No related vids + showinfo: 0, // Hide info + iv_load_policy: 3, // Hide annotations + modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) }, }; diff --git a/src/js/config/states.js b/src/js/config/states.js new file mode 100644 index 00000000..7dd1476b --- /dev/null +++ b/src/js/config/states.js @@ -0,0 +1,10 @@ +// ========================================================================== +// Plyr states +// ========================================================================== + +export const pip = { + active: 'picture-in-picture', + inactive: 'inline', +}; + +export default { pip }; diff --git a/src/js/config/types.js b/src/js/config/types.js new file mode 100644 index 00000000..e0ccdaff --- /dev/null +++ b/src/js/config/types.js @@ -0,0 +1,34 @@ +// ========================================================================== +// Plyr supported types and providers +// ========================================================================== + +export const providers = { + html5: 'html5', + youtube: 'youtube', + vimeo: 'vimeo', +}; + +export const types = { + audio: 'audio', + video: 'video', +}; + +/** + * Get provider by URL + * @param {String} url + */ +export function getProviderByUrl(url) { + // YouTube + if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) { + return providers.youtube; + } + + // Vimeo + if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { + return providers.vimeo; + } + + return null; +} + +export default { providers, types }; diff --git a/src/js/console.js b/src/js/console.js index 7c5ec1b4..e8099569 100644 --- a/src/js/console.js +++ b/src/js/console.js @@ -17,10 +17,12 @@ export default class Console { // eslint-disable-next-line no-console return this.enabled ? Function.prototype.bind.call(console.log, console) : noop; } + get warn() { // eslint-disable-next-line no-console return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop; } + get error() { // eslint-disable-next-line no-console return this.enabled ? Function.prototype.bind.call(console.error, console) : noop; diff --git a/src/js/controls.js b/src/js/controls.js index ec64977e..953ca293 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -1,40 +1,38 @@ // ========================================================================== // Plyr controls +// TODO: This needs to be split into smaller files and cleaned up // ========================================================================== import captions from './captions'; import html5 from './html5'; -import i18n from './i18n'; import support from './support'; -import ui from './ui'; -import utils from './utils'; - -// Sniff out the browser -const browser = utils.getBrowser(); - +import { repaint, transitionEndEvent } from './utils/animation'; +import { dedupe } from './utils/arrays'; +import browser from './utils/browser'; +import { + createElement, + emptyElement, + getAttributesFromSelector, + getElement, + getElements, + hasClass, + matches, + removeElement, + setAttributes, + setFocus, + toggleClass, + toggleHidden, +} from './utils/elements'; +import { off, on } from './utils/events'; +import i18n from './utils/i18n'; +import is from './utils/is'; +import loadSprite from './utils/loadSprite'; +import { extend } from './utils/objects'; +import { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings'; +import { formatTime, getHours } from './utils/time'; + +// TODO: Don't export a massive object - break down and create class const controls = { - // Webkit polyfill for lower fill range - updateRangeFill(target) { - // Get range from event if event passed - const range = utils.is.event(target) ? target.target : target; - - // Needs to be a valid <input type='range'> - if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { - return; - } - - // Set aria value for https://github.com/sampotts/plyr/issues/905 - range.setAttribute('aria-valuenow', range.value); - - // WebKit only - if (!browser.isWebkit) { - return; - } - - // Set CSS custom property - range.style.setProperty('--value', `${range.value / range.max * 100}%`); - }, - // Get icon URL getIconUrl() { const url = new URL(this.config.iconUrl, window.location); @@ -46,46 +44,47 @@ const controls = { }; }, - // Find the UI controls and store references in custom controls - // TODO: Allow settings menus with custom controls + // Find the UI controls findElements() { try { - this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper); + this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons this.elements.buttons = { - play: utils.getElements.call(this, this.config.selectors.buttons.play), - pause: utils.getElement.call(this, this.config.selectors.buttons.pause), - restart: utils.getElement.call(this, this.config.selectors.buttons.restart), - rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind), - fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward), - mute: utils.getElement.call(this, this.config.selectors.buttons.mute), - pip: utils.getElement.call(this, this.config.selectors.buttons.pip), - airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay), - settings: utils.getElement.call(this, this.config.selectors.buttons.settings), - captions: utils.getElement.call(this, this.config.selectors.buttons.captions), - fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen), + play: getElements.call(this, this.config.selectors.buttons.play), + pause: getElement.call(this, this.config.selectors.buttons.pause), + restart: getElement.call(this, this.config.selectors.buttons.restart), + rewind: getElement.call(this, this.config.selectors.buttons.rewind), + fastForward: getElement.call(this, this.config.selectors.buttons.fastForward), + mute: getElement.call(this, this.config.selectors.buttons.mute), + pip: getElement.call(this, this.config.selectors.buttons.pip), + airplay: getElement.call(this, this.config.selectors.buttons.airplay), + settings: getElement.call(this, this.config.selectors.buttons.settings), + captions: getElement.call(this, this.config.selectors.buttons.captions), + fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen), }; // Progress - this.elements.progress = utils.getElement.call(this, this.config.selectors.progress); + this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs this.elements.inputs = { - seek: utils.getElement.call(this, this.config.selectors.inputs.seek), - volume: utils.getElement.call(this, this.config.selectors.inputs.volume), + seek: getElement.call(this, this.config.selectors.inputs.seek), + volume: getElement.call(this, this.config.selectors.inputs.volume), }; // Display this.elements.display = { - buffer: utils.getElement.call(this, this.config.selectors.display.buffer), - currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime), - duration: utils.getElement.call(this, this.config.selectors.display.duration), + buffer: getElement.call(this, this.config.selectors.display.buffer), + currentTime: getElement.call(this, this.config.selectors.display.currentTime), + duration: getElement.call(this, this.config.selectors.display.duration), }; // Seek tooltip - if (utils.is.element(this.elements.progress)) { - this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`); + if (is.element(this.elements.progress)) { + this.elements.display.seekTooltip = this.elements.progress.querySelector( + `.${this.config.classNames.tooltip}`, + ); } return true; @@ -108,9 +107,9 @@ const controls = { // Create <svg> const icon = document.createElementNS(namespace, 'svg'); - utils.setAttributes( + setAttributes( icon, - utils.extend(attributes, { + extend(attributes, { role: 'presentation', focusable: 'false', }), @@ -125,10 +124,11 @@ const controls = { // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href if ('href' in use) { use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path); - } else { - use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); } + // Always set the older attribute even though it's "deprecated" (it'll be around for ages) + use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); + // Add <use> to <svg> icon.appendChild(use); @@ -136,44 +136,28 @@ const controls = { }, // Create hidden text label - createLabel(type, attr) { - let text = i18n.get(type, this.config); - const attributes = Object.assign({}, attr); - - switch (type) { - case 'pip': - text = 'PIP'; - break; - - case 'airplay': - text = 'AirPlay'; - break; + createLabel(key, attr = {}) { + const text = i18n.get(key, this.config); - default: - break; - } - - if ('class' in attributes) { - attributes.class += ` ${this.config.classNames.hidden}`; - } else { - attributes.class = this.config.classNames.hidden; - } + const attributes = Object.assign({}, attr, { + class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' '), + }); - return utils.createElement('span', attributes, text); + return createElement('span', attributes, text); }, // Create a badge createBadge(text) { - if (utils.is.empty(text)) { + if (is.empty(text)) { return null; } - const badge = utils.createElement('span', { + const badge = createElement('span', { class: this.config.classNames.menu.value, }); badge.appendChild( - utils.createElement( + createElement( 'span', { class: this.config.classNames.menu.badge, @@ -187,22 +171,33 @@ const controls = { // Create a <button> createButton(buttonType, attr) { - const button = utils.createElement('button'); const attributes = Object.assign({}, attr); - let type = utils.toCamelCase(buttonType); + let type = toCamelCase(buttonType); - let toggle = false; - let label; - let icon; - let labelPressed; - let iconPressed; + const props = { + element: 'button', + toggle: false, + label: null, + icon: null, + labelPressed: null, + iconPressed: null, + }; - if (!('type' in attributes)) { + ['element', 'icon', 'label'].forEach(key => { + if (Object.keys(attributes).includes(key)) { + props[key] = attributes[key]; + delete attributes[key]; + } + }); + + // Default to 'button' type to prevent form submission + if (props.element === 'button' && !Object.keys(attributes).includes('type')) { attributes.type = 'button'; } - if ('class' in attributes) { - if (attributes.class.includes(this.config.classNames.control)) { + // Set class name + if (Object.keys(attributes).includes('class')) { + if (!attributes.class.includes(this.config.classNames.control)) { attributes.class += ` ${this.config.classNames.control}`; } } else { @@ -212,74 +207,92 @@ const controls = { // Large play button switch (buttonType) { case 'play': - toggle = true; - label = 'play'; - labelPressed = 'pause'; - icon = 'play'; - iconPressed = 'pause'; + props.toggle = true; + props.label = 'play'; + props.labelPressed = 'pause'; + props.icon = 'play'; + props.iconPressed = 'pause'; break; case 'mute': - toggle = true; - label = 'mute'; - labelPressed = 'unmute'; - icon = 'volume'; - iconPressed = 'muted'; + props.toggle = true; + props.label = 'mute'; + props.labelPressed = 'unmute'; + props.icon = 'volume'; + props.iconPressed = 'muted'; break; case 'captions': - toggle = true; - label = 'enableCaptions'; - labelPressed = 'disableCaptions'; - icon = 'captions-off'; - iconPressed = 'captions-on'; + props.toggle = true; + props.label = 'enableCaptions'; + props.labelPressed = 'disableCaptions'; + props.icon = 'captions-off'; + props.iconPressed = 'captions-on'; break; case 'fullscreen': - toggle = true; - label = 'enterFullscreen'; - labelPressed = 'exitFullscreen'; - icon = 'enter-fullscreen'; - iconPressed = 'exit-fullscreen'; + props.toggle = true; + props.label = 'enterFullscreen'; + props.labelPressed = 'exitFullscreen'; + props.icon = 'enter-fullscreen'; + props.iconPressed = 'exit-fullscreen'; break; case 'play-large': attributes.class += ` ${this.config.classNames.control}--overlaid`; type = 'play'; - label = 'play'; - icon = 'play'; + props.label = 'play'; + props.icon = 'play'; break; default: - label = type; - icon = buttonType; + if (is.empty(props.label)) { + props.label = type; + } + if (is.empty(props.icon)) { + props.icon = buttonType; + } } + const button = createElement(props.element); + // Setup toggle icon and labels - if (toggle) { + if (props.toggle) { // Icon - button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' })); - button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' })); + button.appendChild( + controls.createIcon.call(this, props.iconPressed, { + class: 'icon--pressed', + }), + ); + button.appendChild( + controls.createIcon.call(this, props.icon, { + class: 'icon--not-pressed', + }), + ); // Label/Tooltip - button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' })); - button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' })); - - // Add aria attributes - attributes['aria-pressed'] = false; + button.appendChild( + controls.createLabel.call(this, props.labelPressed, { + class: 'label--pressed', + }), + ); + button.appendChild( + controls.createLabel.call(this, props.label, { + class: 'label--not-pressed', + }), + ); } else { - button.appendChild(controls.createIcon.call(this, icon)); - button.appendChild(controls.createLabel.call(this, label)); + button.appendChild(controls.createIcon.call(this, props.icon)); + button.appendChild(controls.createLabel.call(this, props.label)); } - // Merge attributes - utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); - - utils.setAttributes(button, attributes); + // Merge and set attributes + extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); + setAttributes(button, attributes); // We have multiple play buttons if (type === 'play') { - if (!utils.is.array(this.elements.buttons[type])) { + if (!is.array(this.elements.buttons[type])) { this.elements.buttons[type] = []; } @@ -293,22 +306,11 @@ const controls = { // Create an <input type='range'> createRange(type, attributes) { - // Seek label - const label = utils.createElement( - 'label', - { - for: attributes.id, - id: `${attributes.id}-label`, - class: this.config.classNames.hidden, - }, - i18n.get(type, this.config), - ); - // Seek input - const input = utils.createElement( + const input = createElement( 'input', - utils.extend( - utils.getAttributesFromSelector(this.config.selectors.inputs[type]), + extend( + getAttributesFromSelector(this.config.selectors.inputs[type]), { type: 'range', min: 0, @@ -318,7 +320,7 @@ const controls = { autocomplete: 'off', // A11y fixes for https://github.com/sampotts/plyr/issues/905 role: 'slider', - 'aria-labelledby': `${attributes.id}-label`, + 'aria-label': i18n.get(type, this.config), 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': 0, @@ -332,18 +334,15 @@ const controls = { // Set the fill for webkit now controls.updateRangeFill.call(this, input); - return { - label, - input, - }; + return input; }, // Create a <progress> createProgress(type, attributes) { - const progress = utils.createElement( + const progress = createElement( 'progress', - utils.extend( - utils.getAttributesFromSelector(this.config.selectors.display[type]), + extend( + getAttributesFromSelector(this.config.selectors.display[type]), { min: 0, max: 100, @@ -357,23 +356,15 @@ const controls = { // Create the label inside if (type !== 'volume') { - progress.appendChild(utils.createElement('span', null, '0')); - - let suffix = ''; - switch (type) { - case 'played': - suffix = i18n.get('played', this.config); - break; - - case 'buffer': - suffix = i18n.get('buffered', this.config); - break; + progress.appendChild(createElement('span', null, '0')); - default: - break; - } + const suffixKey = { + played: 'played', + buffer: 'buffered', + }[type]; + const suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; - progress.textContent = `% ${suffix.toLowerCase()}`; + progress.innerText = `% ${suffix.toLowerCase()}`; } this.elements.display[type] = progress; @@ -383,12 +374,16 @@ const controls = { // Create time display createTime(type) { - const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]); + const attributes = getAttributesFromSelector(this.config.selectors.display[type]); - const container = utils.createElement('div', utils.extend(attributes, { - class: `plyr__time ${attributes.class}`, - 'aria-label': i18n.get(type, this.config), - }), '00:00'); + const container = createElement( + 'div', + extend(attributes, { + class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(), + 'aria-label': i18n.get(type, this.config), + }), + '00:00', + ); // Reference for updates this.elements.display[type] = container; @@ -396,37 +391,296 @@ const controls = { return container; }, - // Create a settings menu item - createMenuItem(value, list, type, title, badge = null, checked = false) { - const item = utils.createElement('li'); + // Bind keyboard shortcuts for a menu item + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + bindMenuItemShortcuts(menuItem, type) { + // Navigate through menus via arrow keys and space + on( + menuItem, + 'keydown keyup', + event => { + // We only care about space and ⬆️ ⬇️️ ➡️ + if (![32, 38, 39, 40].includes(event.which)) { + return; + } + + // Prevent play / seek + event.preventDefault(); + event.stopPropagation(); + + // We're just here to prevent the keydown bubbling + if (event.type === 'keydown') { + return; + } + + const isRadioButton = matches(menuItem, '[role="menuitemradio"]'); - const label = utils.createElement('label', { - class: this.config.classNames.control, + // Show the respective menu + if (!isRadioButton && [32, 39].includes(event.which)) { + controls.showMenuPanel.call(this, type, true); + } else { + let target; + + if (event.which !== 32) { + if (event.which === 40 || (isRadioButton && event.which === 39)) { + target = menuItem.nextElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.firstElementChild; + } + } else { + target = menuItem.previousElementSibling; + + if (!is.element(target)) { + target = menuItem.parentNode.lastElementChild; + } + } + + setFocus.call(this, target, true); + } + } + }, + false, + ); + + // Enter will fire a `click` event but we still need to manage focus + // So we bind to keyup which fires after and set focus here + on(menuItem, 'keyup', event => { + if (event.which !== 13) { + return; + } + + controls.focusFirstMenuItem.call(this, null, true); }); + }, - const radio = utils.createElement( - 'input', - utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { - type: 'radio', - name: `plyr-${type}`, + // Create a settings menu item + createMenuItem({ value, list, type, title, badge = null, checked = false }) { + const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]); + + const menuItem = createElement( + 'button', + extend(attributes, { + type: 'button', + role: 'menuitemradio', + class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(), + 'aria-checked': checked, value, - checked, - class: 'plyr__sr-only', }), ); - const faux = utils.createElement('span', { hidden: '' }); + const flex = createElement('span'); - label.appendChild(radio); - label.appendChild(faux); - label.insertAdjacentHTML('beforeend', title); + // We have to set as HTML incase of special characters + flex.innerHTML = title; - if (utils.is.element(badge)) { - label.appendChild(badge); + if (is.element(badge)) { + flex.appendChild(badge); } - item.appendChild(label); - list.appendChild(item); + menuItem.appendChild(flex); + + // Replicate radio button behaviour + Object.defineProperty(menuItem, 'checked', { + enumerable: true, + get() { + return menuItem.getAttribute('aria-checked') === 'true'; + }, + set(checked) { + // Ensure exclusivity + if (checked) { + Array.from(menuItem.parentNode.children) + .filter(node => matches(node, '[role="menuitemradio"]')) + .forEach(node => node.setAttribute('aria-checked', 'false')); + } + + menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + }, + }); + + this.listeners.bind( + menuItem, + 'click keyup', + event => { + if (is.keyboardEvent(event) && event.which !== 32) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + menuItem.checked = true; + + switch (type) { + case 'language': + this.currentTrack = Number(value); + break; + + case 'quality': + this.quality = value; + break; + + case 'speed': + this.speed = parseFloat(value); + break; + + default: + break; + } + + controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event)); + }, + type, + false, + ); + + controls.bindMenuItemShortcuts.call(this, menuItem, type); + + list.appendChild(menuItem); + }, + + // Format a time for display + formatTime(time = 0, inverted = false) { + // Bail if the value isn't a number + if (!is.number(time)) { + return time; + } + + // Always display hours if duration is over an hour + const forceHours = getHours(this.duration) > 0; + + return formatTime(time, forceHours, inverted); + }, + + // Update the displayed time + updateTimeDisplay(target = null, time = 0, inverted = false) { + // Bail if there's no element to display or the value isn't a number + if (!is.element(target) || !is.number(time)) { + return; + } + + // eslint-disable-next-line no-param-reassign + target.innerText = controls.formatTime(time, inverted); + }, + + // Update volume UI and storage + updateVolume() { + if (!this.supported.ui) { + return; + } + + // Update range + if (is.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } + + // Update mute state + if (is.element(this.elements.buttons.mute)) { + this.elements.buttons.mute.pressed = this.muted || this.volume === 0; + } + }, + + // Update seek value and lower fill + setRange(target, value = 0) { + if (!is.element(target)) { + return; + } + + // eslint-disable-next-line + target.value = value; + + // Webkit range fill + controls.updateRangeFill.call(this, target); + }, + + // Update <progress> elements + updateProgress(event) { + if (!this.supported.ui || !is.event(event)) { + return; + } + + let value = 0; + + const setProgress = (target, input) => { + const value = is.number(input) ? input : 0; + const progress = is.element(target) ? target : this.elements.display.buffer; + + // Update value and label + if (is.element(progress)) { + progress.value = value; + + // Update text label inside + const label = progress.getElementsByTagName('span')[0]; + if (is.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + case 'seeked': + value = getPercentage(this.currentTime, this.duration); + + // Set seek range value only if it's a 'natural' time event + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + + // Check buffer status + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + + break; + + default: + break; + } + } + }, + + // Webkit polyfill for lower fill range + updateRangeFill(target) { + // Get range from event if event passed + const range = is.event(target) ? target.target : target; + + // Needs to be a valid <input type='range'> + if (!is.element(range) || range.getAttribute('type') !== 'range') { + return; + } + + // Set aria values for https://github.com/sampotts/plyr/issues/905 + if (matches(range, this.config.selectors.inputs.seek)) { + range.setAttribute('aria-valuenow', this.currentTime); + const currentTime = controls.formatTime(this.currentTime); + const duration = controls.formatTime(this.duration); + const format = i18n.get('seekLabel', this.config); + range.setAttribute( + 'aria-valuetext', + format.replace('{currentTime}', currentTime).replace('{duration}', duration), + ); + } else if (matches(range, this.config.selectors.inputs.volume)) { + const percent = range.value * 100; + range.setAttribute('aria-valuenow', percent); + range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`); + } else { + range.setAttribute('aria-valuenow', range.value); + } + + // WebKit only + if (!browser.isWebkit) { + return; + } + + // Set CSS custom property + range.style.setProperty('--value', `${(range.value / range.max) * 100}%`); }, // Update hover tooltip for seeking @@ -434,8 +688,8 @@ const controls = { // Bail if setting not true if ( !this.config.tooltips.seek || - !utils.is.element(this.elements.inputs.seek) || - !utils.is.element(this.elements.display.seekTooltip) || + !is.element(this.elements.inputs.seek) || + !is.element(this.elements.display.seekTooltip) || this.duration === 0 ) { return; @@ -443,11 +697,11 @@ const controls = { // Calculate percentage let percent = 0; - const clientRect = this.elements.inputs.seek.getBoundingClientRect(); + const clientRect = this.elements.progress.getBoundingClientRect(); const visible = `${this.config.classNames.tooltip}--visible`; const toggle = toggle => { - utils.toggleClass(this.elements.display.seekTooltip, visible, toggle); + toggleClass(this.elements.display.seekTooltip, visible, toggle); }; // Hide on touch @@ -457,9 +711,9 @@ const controls = { } // Determine percentage, if already visible - if (utils.is.event(event)) { - percent = 100 / clientRect.width * (event.pageX - clientRect.left); - } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { + if (is.event(event)) { + percent = (100 / clientRect.width) * (event.pageX - clientRect.left); + } else if (hasClass(this.elements.display.seekTooltip, visible)) { percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); } else { return; @@ -473,115 +727,153 @@ const controls = { } // Display the time a click would seek to - ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent); // Set position this.elements.display.seekTooltip.style.left = `${percent}%`; // Show/hide the tooltip // If the event is a moues in/out and percentage is inside bounds - if (utils.is.event(event) && [ - 'mouseenter', - 'mouseleave', - ].includes(event.type)) { + if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { toggle(event.type === 'mouseenter'); } }, - // Hide/show a tab - toggleTab(setting, toggle) { - utils.toggleHidden(this.elements.settings.tabs[setting], !toggle); + // Handle time change event + timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + const invert = !is.element(this.elements.display.duration) && this.config.invertTime; + + // Duration + controls.updateTimeDisplay.call( + this, + this.elements.display.currentTime, + invert ? this.duration - this.currentTime : this.currentTime, + invert, + ); + + // Ignore updates while seeking + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } + + // Playing progress + controls.updateProgress.call(this, event); }, - // Set the quality menu - // TODO: Vimeo support - setQualityMenu(options) { - // Menu required - if (!utils.is.element(this.elements.settings.panes.quality)) { + // Show the duration on metadataloaded or durationchange events + durationUpdate() { + // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false + if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) { return; } - const type = 'quality'; - const list = this.elements.settings.panes.quality.querySelector('ul'); + // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar. + // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415 + // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062 + // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338 + if (this.duration >= 2 ** 32) { + toggleHidden(this.elements.display.currentTime, true); + toggleHidden(this.elements.progress, true); + return; + } - // Set options if passed and filter based on config - if (utils.is.array(options)) { - this.options.quality = options.filter(quality => this.config.quality.options.includes(quality)); + // Update ARIA values + if (is.element(this.elements.inputs.seek)) { + this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration); } - // Toggle the pane and tab - const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1; - controls.toggleTab.call(this, type, toggle); + // If there's a spot to display duration + const hasDuration = is.element(this.elements.display.duration); - // Check if we need to toggle the parent - controls.checkMenu.call(this); + // If there's only one time display, display duration there + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } - // If we're hiding, nothing more to do - if (!toggle) { - return; + // If there's a duration element, update content + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); } - // Empty the menu - utils.emptyElement(list); + // Update the tooltip (if visible) + controls.updateSeekTooltip.call(this); + }, - // Get the badge HTML for HD, 4K etc - const getBadge = quality => { - let label = ''; + // Hide/show a tab + toggleMenuButton(setting, toggle) { + toggleHidden(this.elements.settings.buttons[setting], !toggle); + }, - switch (quality) { - case 2160: - label = '4K'; - break; + // Update the selected setting + updateSetting(setting, container, input) { + const pane = this.elements.settings.panels[setting]; + let value = null; + let list = container; - case 1440: - case 1080: - case 720: - label = 'HD'; - break; + if (setting === 'captions') { + value = this.currentTrack; + } else { + value = !is.empty(input) ? input : this[setting]; - case 576: - case 480: - label = 'SD'; - break; + // Get default + if (is.empty(value)) { + value = this.config[setting].default; + } - default: - break; + // Unsupported value + if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) { + this.debug.warn(`Unsupported value of '${value}' for ${setting}`); + return; } - if (!label.length) { - return null; + // Disabled value + if (!this.config[setting].options.includes(value)) { + this.debug.warn(`Disabled value of '${value}' for ${setting}`); + return; } + } - return controls.createBadge.call(this, label); - }; + // Get the list if we need to + if (!is.element(list)) { + list = pane && pane.querySelector('[role="menu"]'); + } - // Sort options by the config and then render options - this.options.quality - .sort((a, b) => { - const sorting = this.config.quality.options; - return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; - }) - .forEach(quality => { - const label = controls.getLabel.call(this, 'quality', quality); - controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality)); - }); + // If there's no list it means it's not been rendered... + if (!is.element(list)) { + return; + } - controls.updateSetting.call(this, type, list); + // Update the label + const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`); + label.innerHTML = controls.getLabel.call(this, setting, value); + + // Find the radio option and check it + const target = list && list.querySelector(`[value="${value}"]`); + + if (is.element(target)) { + target.checked = true; + } }, // Translate a value into a nice label - // TODO: Localisation getLabel(setting, value) { switch (setting) { case 'speed': return value === 1 ? i18n.get('normal', this.config) : `${value}×`; case 'quality': - if (utils.is.number(value)) { - return `${value}p`; + if (is.number(value)) { + const label = i18n.get(`qualityLabel.${value}`, this.config); + + if (!label.length) { + return `${value}p`; + } + + return label; } - return utils.toTitleCase(value); + return toTitleCase(value); case 'captions': return captions.getLabel.call(this); @@ -591,98 +883,93 @@ const controls = { } }, - // Update the selected setting - updateSetting(setting, container, input) { - const pane = this.elements.settings.panes[setting]; - let value = null; - let list = container; - - switch (setting) { - case 'captions': - if (this.captions.active) { - if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) { - value = this.captions.language; - } else { - value = 'enabled'; - } - } else { - value = ''; - } + // Set the quality menu + setQualityMenu(options) { + // Menu required + if (!is.element(this.elements.settings.panels.quality)) { + return; + } - break; + const type = 'quality'; + const list = this.elements.settings.panels.quality.querySelector('[role="menu"]'); - default: - value = !utils.is.empty(input) ? input : this[setting]; + // Set options if passed and filter based on uniqueness and config + if (is.array(options)) { + this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality)); + } - // Get default - if (utils.is.empty(value)) { - value = this.config[setting].default; - } + // Toggle the pane and tab + const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1; + controls.toggleMenuButton.call(this, type, toggle); - // Unsupported value - if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) { - this.debug.warn(`Unsupported value of '${value}' for ${setting}`); - return; - } + // Empty the menu + emptyElement(list); - // Disabled value - if (!this.config[setting].options.includes(value)) { - this.debug.warn(`Disabled value of '${value}' for ${setting}`); - return; - } + // Check if we need to toggle the parent + controls.checkMenu.call(this); - break; + // If we're hiding, nothing more to do + if (!toggle) { + return; } - // Get the list if we need to - if (!utils.is.element(list)) { - list = pane && pane.querySelector('ul'); - } + // Get the badge HTML for HD, 4K etc + const getBadge = quality => { + const label = i18n.get(`qualityBadge.${quality}`, this.config); - // If there's no list it means it's not been rendered... - if (!utils.is.element(list)) { - return; - } + if (!label.length) { + return null; + } - // Update the label - const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`); - label.innerHTML = controls.getLabel.call(this, setting, value); + return controls.createBadge.call(this, label); + }; - // Find the radio option and check it - const target = list && list.querySelector(`input[value="${value}"]`); + // Sort options by the config and then render options + this.options.quality + .sort((a, b) => { + const sorting = this.config.quality.options; + return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; + }) + .forEach(quality => { + controls.createMenuItem.call(this, { + value: quality, + list, + type, + title: controls.getLabel.call(this, 'quality', quality), + badge: getBadge(quality), + }); + }); - if (utils.is.element(target)) { - target.checked = true; - } + controls.updateSetting.call(this, type, list); }, // Set the looping options /* setLoopMenu() { // Menu required - if (!utils.is.element(this.elements.settings.panes.loop)) { + if (!is.element(this.elements.settings.panels.loop)) { return; } const options = ['start', 'end', 'all', 'reset']; - const list = this.elements.settings.panes.loop.querySelector('ul'); + const list = this.elements.settings.panels.loop.querySelector('[role="menu"]'); // Show the pane and tab - utils.toggleHidden(this.elements.settings.tabs.loop, false); - utils.toggleHidden(this.elements.settings.panes.loop, false); + toggleHidden(this.elements.settings.buttons.loop, false); + toggleHidden(this.elements.settings.panels.loop, false); // Toggle the pane and tab - const toggle = !utils.is.empty(this.loop.options); - controls.toggleTab.call(this, 'loop', toggle); + const toggle = !is.empty(this.loop.options); + controls.toggleMenuButton.call(this, 'loop', toggle); // Empty the menu - utils.emptyElement(list); + emptyElement(list); options.forEach(option => { - const item = utils.createElement('li'); + const item = createElement('li'); - const button = utils.createElement( + const button = createElement( 'button', - utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), { + extend(getAttributesFromSelector(this.config.selectors.buttons.loop), { type: 'button', class: this.config.classNames.control, 'data-plyr-loop-action': option, @@ -705,16 +992,22 @@ const controls = { // Set a list of available captions languages setCaptionsMenu() { + // Menu required + if (!is.element(this.elements.settings.panels.captions)) { + return; + } + // TODO: Captions or language? Currently it's mixed const type = 'captions'; - const list = this.elements.settings.panes.captions.querySelector('ul'); + const list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); + const tracks = captions.getTracks.call(this); + const toggle = Boolean(tracks.length); // Toggle the pane and tab - const toggle = captions.getTracks.call(this).length; - controls.toggleTab.call(this, type, toggle); + controls.toggleMenuButton.call(this, type, toggle); // Empty the menu - utils.emptyElement(list); + emptyElement(list); // Check if we need to toggle the parent controls.checkMenu.call(this); @@ -724,72 +1017,57 @@ const controls = { return; } - // Re-map the tracks into just the data we need - const tracks = captions.getTracks.call(this).map(track => ({ - language: !utils.is.empty(track.language) ? track.language : 'enabled', - label: captions.getLabel.call(this, track), + // Generate options data + const options = tracks.map((track, value) => ({ + value, + checked: this.captions.toggled && this.currentTrack === value, + title: captions.getLabel.call(this, track), + badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()), + list, + type: 'language', })); // Add the "Disabled" option to turn off captions - tracks.unshift({ - language: '', - label: i18n.get('disabled', this.config), + options.unshift({ + value: -1, + checked: !this.captions.toggled, + title: i18n.get('disabled', this.config), + list, + type: 'language', }); // Generate options - tracks.forEach(track => { - controls.createMenuItem.call( - this, - track.language, - list, - 'language', - track.label, - track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null, - track.language.toLowerCase() === this.captions.language.toLowerCase(), - ); - }); - - // Store reference - this.options.captions = tracks.map(track => track.language); + options.forEach(controls.createMenuItem.bind(this)); controls.updateSetting.call(this, type, list); }, // Set a list of available captions languages setSpeedMenu(options) { - // Do nothing if not selected - if (!this.config.controls.includes('settings') || !this.config.settings.includes('speed')) { - return; - } - // Menu required - if (!utils.is.element(this.elements.settings.panes.speed)) { + if (!is.element(this.elements.settings.panels.speed)) { return; } const type = 'speed'; + const list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options - if (utils.is.array(options)) { + if (is.array(options)) { this.options.speed = options; } else if (this.isHTML5 || this.isVimeo) { - this.options.speed = [ - 0.5, - 0.75, - 1, - 1.25, - 1.5, - 1.75, - 2, - ]; + this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; } // Set options if passed and filter based on config this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed)); // Toggle the pane and tab - const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1; - controls.toggleTab.call(this, type, toggle); + const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1; + controls.toggleMenuButton.call(this, type, toggle); + + // Empty the menu + emptyElement(list); // Check if we need to toggle the parent controls.checkMenu.call(this); @@ -799,16 +1077,14 @@ const controls = { return; } - // Get the list to populate - const list = this.elements.settings.panes.speed.querySelector('ul'); - - // Empty the menu - utils.emptyElement(list); - // Create items this.options.speed.forEach(speed => { - const label = controls.getLabel.call(this, 'speed', speed); - controls.createMenuItem.call(this, speed, list, type, label); + controls.createMenuItem.call(this, { + value: speed, + list, + type, + title: controls.getLabel.call(this, 'speed', speed), + }); }); controls.updateSetting.call(this, type, list); @@ -816,71 +1092,83 @@ const controls = { // Check if we need to hide/show the settings menu checkMenu() { - const { tabs } = this.elements.settings; - const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden); + const { buttons } = this.elements.settings; + const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden); - utils.toggleHidden(this.elements.settings.menu, !visible); + toggleHidden(this.elements.settings.menu, !visible); + }, + + // Focus the first menu item in a given (or visible) menu + focusFirstMenuItem(pane, tabFocus = false) { + if (this.elements.settings.popup.hidden) { + return; + } + + let target = pane; + + if (!is.element(target)) { + target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden); + } + + const firstItem = target.querySelector('[role^="menuitem"]'); + + setFocus.call(this, firstItem, tabFocus); }, // Show/hide menu - toggleMenu(event) { - const { form } = this.elements.settings; + toggleMenu(input) { + const { popup } = this.elements.settings; const button = this.elements.buttons.settings; // Menu and button are required - if (!utils.is.element(form) || !utils.is.element(button)) { + if (!is.element(popup) || !is.element(button)) { return; } - const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden'); + // True toggle by default + const { hidden } = popup; + let show = hidden; - if (utils.is.event(event)) { - const isMenuItem = utils.is.element(form) && form.contains(event.target); - const isButton = event.target === this.elements.buttons.settings; + if (is.boolean(input)) { + show = input; + } else if (is.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is.event(input)) { + const isMenuItem = popup.contains(input.target); - // If the click was inside the form or if the click + // If the click was inside the menu or if the click // wasn't the button or menu item and we're trying to // show the menu (a doc click shouldn't show the menu) - if (isMenuItem || (!isMenuItem && !isButton && show)) { + if (isMenuItem || (!isMenuItem && input.target !== button && show)) { return; } - - // Prevent the toggle being caught by the doc listener - if (isButton) { - event.stopPropagation(); - } } - // Set form and button attributes - if (utils.is.element(button)) { - button.setAttribute('aria-expanded', show); - } + // Set button attributes + button.setAttribute('aria-expanded', show); - if (utils.is.element(form)) { - utils.toggleHidden(form, !show); - utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); + // Show the actual popup + toggleHidden(popup, !show); - if (show) { - form.removeAttribute('tabindex'); - } else { - form.setAttribute('tabindex', -1); - } + // Add class hook + toggleClass(this.elements.container, this.config.classNames.menu.open, show); + + // Focus the first item if key interaction + if (show && is.keyboardEvent(input)) { + controls.focusFirstMenuItem.call(this, null, true); + } else if (!show && !hidden) { + // If closing, re-focus the button + setFocus.call(this, button, is.keyboardEvent(input)); } }, - // Get the natural size of a tab - getTabSize(tab) { + // Get the natural size of a menu panel + getMenuSize(tab) { const clone = tab.cloneNode(true); clone.style.position = 'absolute'; clone.style.opacity = 0; clone.removeAttribute('hidden'); - // Prevent input's being unchecked due to the name being identical - Array.from(clone.querySelectorAll('input[name]')).forEach(input => { - const name = input.getAttribute('name'); - input.setAttribute('name', `${name}-clone`); - }); - // Append to parent so we get the "real" size tab.parentNode.appendChild(clone); @@ -889,7 +1177,7 @@ const controls = { const height = clone.scrollHeight; // Remove from the DOM - utils.removeElement(clone); + removeElement(clone); return { width, @@ -897,31 +1185,18 @@ const controls = { }; }, - // Toggle Menu - showTab(target = '') { - const { menu } = this.elements.settings; - const pane = document.getElementById(target); + // Show a panel in the menu + showMenuPanel(type = '', tabFocus = false) { + const target = document.getElementById(`plyr-settings-${this.id}-${type}`); // Nothing to show, bail - if (!utils.is.element(pane)) { - return; - } - - // Are we targetting a tab? If not, bail - const isTab = pane.getAttribute('role') === 'tabpanel'; - if (!isTab) { + if (!is.element(target)) { return; } - // Hide all other tabs - // Get other tabs - const current = menu.querySelector('[role="tabpanel"]:not([hidden])'); - const container = current.parentNode; - - // Set other toggles to be expanded false - Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => { - toggle.setAttribute('aria-expanded', false); - }); + // Hide all other panels + const container = target.parentNode; + const current = Array.from(container.children).find(node => !node.hidden); // If we can do fancy animations, we'll animate the height/width if (support.transitions && !support.reducedMotion) { @@ -930,15 +1205,12 @@ const controls = { container.style.height = `${current.scrollHeight}px`; // Get potential sizes - const size = controls.getTabSize.call(this, pane); + const size = controls.getMenuSize.call(this, target); // Restore auto height/width - const restore = e => { + const restore = event => { // We're only bothered about height and width on the container - if (e.target !== container || ![ - 'width', - 'height', - ].includes(e.propertyName)) { + if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { return; } @@ -947,11 +1219,11 @@ const controls = { container.style.height = ''; // Only listen once - utils.off(container, utils.transitionEndEvent, restore); + off.call(this, container, transitionEndEvent, restore); }; // Listen for the transition finishing and restore auto height/width - utils.on(container, utils.transitionEndEvent, restore); + on.call(this, container, transitionEndEvent, restore); // Set dimensions to target container.style.width = `${size.width}px`; @@ -959,32 +1231,33 @@ const controls = { } // Set attributes on current tab - utils.toggleHidden(current, true); - current.setAttribute('tabindex', -1); + toggleHidden(current, true); // Set attributes on target - utils.toggleHidden(pane, false); - - const tabs = utils.getElements.call(this, `[aria-controls="${target}"]`); - Array.from(tabs).forEach(tab => { - tab.setAttribute('aria-expanded', true); - }); - pane.removeAttribute('tabindex'); + toggleHidden(target, false); // Focus the first item - pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus(); + controls.focusFirstMenuItem.call(this, target, tabFocus); + }, + + // Set the download link + setDownloadLink() { + const button = this.elements.buttons.download; + + // Bail if no button + if (!is.element(button)) { + return; + } + + // Set download link + button.setAttribute('href', this.download); }, // Build the default HTML // TODO: Set order based on order in the config.controls array? create(data) { - // Do nothing if we want no controls - if (utils.is.empty(this.config.controls)) { - return null; - } - // Create the container - const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper)); + const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button if (this.config.controls.includes('restart')) { @@ -1008,14 +1281,14 @@ const controls = { // Progress if (this.config.controls.includes('progress')) { - const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress)); + const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider - const seek = controls.createRange.call(this, 'seek', { - id: `plyr-seek-${data.id}`, - }); - progress.appendChild(seek.label); - progress.appendChild(seek.input); + progress.appendChild( + controls.createRange.call(this, 'seek', { + id: `plyr-seek-${data.id}`, + }), + ); // Buffer progress progress.appendChild(controls.createProgress.call(this, 'buffer')); @@ -1024,10 +1297,9 @@ const controls = { // Seek tooltip if (this.config.tooltips.seek) { - const tooltip = utils.createElement( + const tooltip = createElement( 'span', { - role: 'tooltip', class: this.config.classNames.tooltip, }, '00:00', @@ -1051,36 +1323,39 @@ const controls = { container.appendChild(controls.createTime.call(this, 'duration')); } - // Toggle mute button - if (this.config.controls.includes('mute')) { - container.appendChild(controls.createButton.call(this, 'mute')); - } - - // Volume range control - if (this.config.controls.includes('volume')) { - const volume = utils.createElement('div', { + // Volume controls + if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { + const volume = createElement('div', { class: 'plyr__volume', }); - // Set the attributes - const attributes = { - max: 1, - step: 0.05, - value: this.config.volume, - }; + // Toggle mute button + if (this.config.controls.includes('mute')) { + volume.appendChild(controls.createButton.call(this, 'mute')); + } - // Create the volume range slider - const range = controls.createRange.call( - this, - 'volume', - utils.extend(attributes, { - id: `plyr-volume-${data.id}`, - }), - ); - volume.appendChild(range.label); - volume.appendChild(range.input); + // Volume range control + if (this.config.controls.includes('volume')) { + // Set the attributes + const attributes = { + max: 1, + step: 0.05, + value: this.config.volume, + }; + + // Create the volume range slider + volume.appendChild( + controls.createRange.call( + this, + 'volume', + extend(attributes, { + id: `plyr-volume-${data.id}`, + }), + ), + ); - this.elements.volume = volume; + this.elements.volume = volume; + } container.appendChild(volume); } @@ -1091,118 +1366,157 @@ const controls = { } // Settings button / menu - if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { - const menu = utils.createElement('div', { + if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + const control = createElement('div', { class: 'plyr__menu', hidden: '', }); - menu.appendChild( + control.appendChild( controls.createButton.call(this, 'settings', { - id: `plyr-settings-toggle-${data.id}`, 'aria-haspopup': true, 'aria-controls': `plyr-settings-${data.id}`, 'aria-expanded': false, }), ); - const form = utils.createElement('form', { + const popup = createElement('div', { class: 'plyr__menu__container', id: `plyr-settings-${data.id}`, hidden: '', - 'aria-labelled-by': `plyr-settings-toggle-${data.id}`, - role: 'tablist', - tabindex: -1, }); - const inner = utils.createElement('div'); + const inner = createElement('div'); - const home = utils.createElement('div', { + const home = createElement('div', { id: `plyr-settings-${data.id}-home`, - 'aria-labelled-by': `plyr-settings-toggle-${data.id}`, - role: 'tabpanel', }); - // Create the tab list - const tabs = utils.createElement('ul', { - role: 'tablist', + // Create the menu + const menu = createElement('div', { + role: 'menu', }); - // Build the tabs - this.config.settings.forEach(type => { - const tab = utils.createElement('li', { - role: 'tab', - hidden: '', - }); + home.appendChild(menu); + inner.appendChild(home); + this.elements.settings.panels.home = home; - const button = utils.createElement( + // Build the menu items + this.config.settings.forEach(type => { + // TODO: bundle this with the createMenuItem helper and bindings + const menuItem = createElement( 'button', - utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), { + extend(getAttributesFromSelector(this.config.selectors.buttons.settings), { type: 'button', class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`, - id: `plyr-settings-${data.id}-${type}-tab`, + role: 'menuitem', 'aria-haspopup': true, - 'aria-controls': `plyr-settings-${data.id}-${type}`, - 'aria-expanded': false, + hidden: '', }), - i18n.get(type, this.config), ); - const value = utils.createElement('span', { + // Bind menu shortcuts for keyboard users + controls.bindMenuItemShortcuts.call(this, menuItem, type); + + // Show menu on click + on(menuItem, 'click', () => { + controls.showMenuPanel.call(this, type, false); + }); + + const flex = createElement('span', null, i18n.get(type, this.config)); + + const value = createElement('span', { class: this.config.classNames.menu.value, }); // Speed contains HTML entities value.innerHTML = data[type]; - button.appendChild(value); - tab.appendChild(button); - tabs.appendChild(tab); + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); - this.elements.settings.tabs[type] = tab; - }); - - home.appendChild(tabs); - inner.appendChild(home); - - // Build the panes - this.config.settings.forEach(type => { - const pane = utils.createElement('div', { + // Build the panes + const pane = createElement('div', { id: `plyr-settings-${data.id}-${type}`, hidden: '', - 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`, - role: 'tabpanel', - tabindex: -1, }); - const back = utils.createElement( - 'button', - { - type: 'button', - class: `${this.config.classNames.control} ${this.config.classNames.control}--back`, - 'aria-haspopup': true, - 'aria-controls': `plyr-settings-${data.id}-home`, - 'aria-expanded': false, + // Back button + const backButton = createElement('button', { + type: 'button', + class: `${this.config.classNames.control} ${this.config.classNames.control}--back`, + }); + + // Visible label + backButton.appendChild( + createElement( + 'span', + { + 'aria-hidden': true, + }, + i18n.get(type, this.config), + ), + ); + + // Screen reader label + backButton.appendChild( + createElement( + 'span', + { + class: this.config.classNames.hidden, + }, + i18n.get('menuBack', this.config), + ), + ); + + // Go back via keyboard + on( + pane, + 'keydown', + event => { + // We only care about <- + if (event.which !== 37) { + return; + } + + // Prevent seek + event.preventDefault(); + event.stopPropagation(); + + // Show the respective menu + controls.showMenuPanel.call(this, 'home', true); }, - i18n.get(type, this.config), + false, ); - pane.appendChild(back); + // Go back via button click + on(backButton, 'click', () => { + controls.showMenuPanel.call(this, 'home', false); + }); + + // Add to pane + pane.appendChild(backButton); - const options = utils.createElement('ul'); + // Menu + pane.appendChild( + createElement('div', { + role: 'menu', + }), + ); - pane.appendChild(options); inner.appendChild(pane); - this.elements.settings.panes[type] = pane; + this.elements.settings.buttons[type] = menuItem; + this.elements.settings.panels[type] = pane; }); - form.appendChild(inner); - menu.appendChild(form); - container.appendChild(menu); + popup.appendChild(inner); + control.appendChild(popup); + container.appendChild(control); - this.elements.settings.form = form; - this.elements.settings.menu = menu; + this.elements.settings.popup = popup; + this.elements.settings.menu = control; } // Picture in picture button @@ -1215,6 +1529,26 @@ const controls = { container.appendChild(controls.createButton.call(this, 'airplay')); } + // Download button + if (this.config.controls.includes('download')) { + const attributes = { + element: 'a', + href: this.download, + target: '_blank', + }; + + const { download } = this.config.urls; + + if (!is.url(download) && this.isEmbed) { + extend(attributes, { + icon: `logo-${this.provider}`, + label: this.provider, + }); + } + + container.appendChild(controls.createButton.call(this, 'download', attributes)); + } + // Toggle fullscreen button if (this.config.controls.includes('fullscreen')) { container.appendChild(controls.createButton.call(this, 'fullscreen')); @@ -1227,6 +1561,7 @@ const controls = { this.elements.controls = container; + // Set available quality levels if (this.isHTML5) { controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); } @@ -1244,7 +1579,7 @@ const controls = { // Only load external sprite using AJAX if (icon.cors) { - utils.loadSprite(icon.url, 'sprite-plyr'); + loadSprite(icon.url, 'sprite-plyr'); } } @@ -1263,13 +1598,19 @@ const controls = { }; let update = true; - if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { - // String or HTMLElement passed as the option + // If function, run it and use output + if (is.function(this.config.controls)) { + this.config.controls = this.config.controls.call(this, props); + } + + // Convert falsy controls to empty array (primarily for empty strings) + if (!this.config.controls) { + this.config.controls = []; + } + + if (is.element(this.config.controls) || is.string(this.config.controls)) { + // HTMLElement or Non-empty string passed as the option container = this.config.controls; - } else if (utils.is.function(this.config.controls)) { - // A custom function to build controls - // The function can return a HTMLElement or String - container = this.config.controls.call(this, props); } else { // Create controls container = controls.create.call(this, { @@ -1288,11 +1629,8 @@ const controls = { const replace = input => { let result = input; - Object.entries(props).forEach(([ - key, - value, - ]) => { - result = utils.replaceAll(result, `{${key}}`, value); + Object.entries(props).forEach(([key, value]) => { + result = replaceAll(result, `{${key}}`, value); }); return result; @@ -1300,9 +1638,9 @@ const controls = { // Update markup if (update) { - if (utils.is.string(this.config.controls)) { + if (is.string(this.config.controls)) { container = replace(container); - } else if (utils.is.element(container)) { + } else if (is.element(container)) { container.innerHTML = replace(container.innerHTML); } } @@ -1311,49 +1649,67 @@ const controls = { let target; // Inject to custom location - if (utils.is.string(this.config.selectors.controls.container)) { + if (is.string(this.config.selectors.controls.container)) { target = document.querySelector(this.config.selectors.controls.container); } // Inject into the container by default - if (!utils.is.element(target)) { + if (!is.element(target)) { target = this.elements.container; } - // Inject controls HTML - if (utils.is.element(container)) { - target.appendChild(container); - } else if (container) { - target.insertAdjacentHTML('beforeend', container); - } + // Inject controls HTML (needs to be before captions, hence "afterbegin") + const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML'; + target[insertMethod]('afterbegin', container); // Find the elements if need be - if (!utils.is.element(this.elements.controls)) { + if (!is.element(this.elements.controls)) { controls.findElements.call(this); } - // Edge sometimes doesn't finish the paint so force a redraw - if (window.navigator.userAgent.includes('Edge')) { - utils.repaint(target); + // Add pressed property to buttons + if (!is.empty(this.elements.buttons)) { + const addProperty = button => { + const className = this.config.classNames.controlPressed; + Object.defineProperty(button, 'pressed', { + enumerable: true, + get() { + return hasClass(button, className); + }, + set(pressed = false) { + toggleClass(button, className, pressed); + }, + }); + }; + + // Toggle classname when pressed property is set + Object.values(this.elements.buttons) + .filter(Boolean) + .forEach(button => { + if (is.array(button) || is.nodeList(button)) { + Array.from(button) + .filter(Boolean) + .forEach(addProperty); + } else { + addProperty(button); + } + }); + } + + // Edge sometimes doesn't finish the paint so force a repaint + if (browser.isEdge) { + repaint(target); } // Setup tooltips if (this.config.tooltips.controls) { - const labels = utils.getElements.call( - this, - [ - this.config.selectors.controls.wrapper, - ' ', - this.config.selectors.labels, - ' .', - this.config.classNames.hidden, - ].join(''), - ); + const { classNames, selectors } = this.config; + const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`; + const labels = getElements.call(this, selector); Array.from(labels).forEach(label => { - utils.toggleClass(label, this.config.classNames.hidden, false); - utils.toggleClass(label, this.config.classNames.tooltip, true); - label.setAttribute('role', 'tooltip'); + toggleClass(label, this.config.classNames.hidden, false); + toggleClass(label, this.config.classNames.tooltip, true); }); } }, diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js index cd2d8ac6..c86bf877 100644 --- a/src/js/fullscreen.js +++ b/src/js/fullscreen.js @@ -1,11 +1,14 @@ // ========================================================================== // Fullscreen wrapper // https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing +// https://webkit.org/blog/7929/designing-websites-for-iphone-x/ // ========================================================================== -import utils from './utils'; - -const browser = utils.getBrowser(); +import { repaint } from './utils/animation'; +import browser from './utils/browser'; +import { hasClass, toggleClass, trapFocus } from './utils/elements'; +import { on, triggerEvent } from './utils/events'; +import is from './utils/is'; function onChange() { if (!this.enabled) { @@ -14,16 +17,16 @@ function onChange() { // Update toggle button const button = this.player.elements.buttons.fullscreen; - if (utils.is.element(button)) { - utils.toggleState(button, this.active); + if (is.element(button)) { + button.pressed = this.active; } // Trigger an event - utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); + triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container if (!browser.isIos) { - utils.trapFocus.call(this.player, this.target, this.active); + trapFocus.call(this.player, this.target, this.active); } } @@ -42,7 +45,38 @@ function toggleFallback(toggle = false) { document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook - utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); + toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); + + // Force full viewport on iPhone X+ + if (browser.isIos) { + let viewport = document.head.querySelector('meta[name="viewport"]'); + const property = 'viewport-fit=cover'; + + // Inject the viewport meta if required + if (!viewport) { + viewport = document.createElement('meta'); + viewport.setAttribute('name', 'viewport'); + } + + // Check if the property already exists + const hasProperty = is.string(viewport.content) && viewport.content.includes(property); + + if (toggle) { + this.cleanupViewport = !hasProperty; + + if (!hasProperty) { + viewport.content += `,${property}`; + } + } else if (this.cleanupViewport) { + viewport.content = viewport.content + .split(',') + .filter(part => part.trim() !== property) + .join(','); + } + + // Force a repaint as sometimes Safari doesn't want to fill the screen + setTimeout(() => repaint(this.target), 100); + } // Toggle button and fire events onChange.call(this); @@ -60,17 +94,25 @@ class Fullscreen { // Scroll position this.scrollPosition = { x: 0, y: 0 }; + // Force the use of 'full window/browser' rather than fullscreen + this.forceFallback = player.config.fullscreen.fallback === 'force'; + // Register event listeners // Handle event (incase user presses escape etc) - utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => { - // TODO: Filter for target?? - onChange.call(this); - }); + on.call( + this.player, + document, + this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, + () => { + // TODO: Filter for target?? + onChange.call(this); + }, + ); // Fullscreen toggle on double click - utils.on(this.player.elements.container, 'dblclick', event => { + on.call(this.player, this.player.elements.container, 'dblclick', event => { // Ignore double click in controls - if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) { + if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) { return; } @@ -83,26 +125,32 @@ class Fullscreen { // Determine if native supported static get native() { - return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + return !!( + document.fullscreenEnabled || + document.webkitFullscreenEnabled || + document.mozFullScreenEnabled || + document.msFullscreenEnabled + ); + } + + // If we're actually using native + get usingNative() { + return Fullscreen.native && !this.forceFallback; } // Get the prefix for handlers static get prefix() { // No prefix - if (utils.is.function(document.exitFullscreen)) { + if (is.function(document.exitFullscreen)) { return ''; } // Check for fullscreen support by vendor prefix let value = ''; - const prefixes = [ - 'webkit', - 'moz', - 'ms', - ]; + const prefixes = ['webkit', 'moz', 'ms']; prefixes.some(pre => { - if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) { + if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) { value = pre; return true; } @@ -134,8 +182,8 @@ class Fullscreen { } // Fallback using classname - if (!Fullscreen.native) { - return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); + if (!Fullscreen.native || this.forceFallback) { + return hasClass(this.target, this.player.config.classNames.fullscreen.fallback); } const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`]; @@ -145,19 +193,31 @@ class Fullscreen { // Get target element get target() { - return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + return browser.isIos && this.player.config.fullscreen.iosNative + ? this.player.media + : this.player.elements.container; } // Update UI update() { if (this.enabled) { - this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`); + let mode; + + if (this.forceFallback) { + mode = 'Fallback (forced)'; + } else if (Fullscreen.native) { + mode = 'Native'; + } else { + mode = 'Fallback'; + } + + this.player.debug.log(`${mode} fullscreen enabled`); } else { this.player.debug.log('Fullscreen not supported and fallback disabled'); } // Add styling hook to show button - utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); + toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled); } // Make an element fullscreen @@ -168,14 +228,12 @@ class Fullscreen { // iOS native fullscreen doesn't need the request step if (browser.isIos && this.player.config.fullscreen.iosNative) { - if (this.player.playing) { - this.target.webkitEnterFullscreen(); - } - } else if (!Fullscreen.native) { + this.target.webkitEnterFullscreen(); + } else if (!Fullscreen.native || this.forceFallback) { toggleFallback.call(this, true); } else if (!this.prefix) { this.target.requestFullscreen(); - } else if (!utils.is.empty(this.prefix)) { + } else if (!is.empty(this.prefix)) { this.target[`${this.prefix}Request${this.property}`](); } } @@ -190,11 +248,11 @@ class Fullscreen { if (browser.isIos && this.player.config.fullscreen.iosNative) { this.target.webkitExitFullscreen(); this.player.play(); - } else if (!Fullscreen.native) { + } else if (!Fullscreen.native || this.forceFallback) { toggleFallback.call(this, false); } else if (!this.prefix) { (document.cancelFullScreen || document.exitFullscreen).call(document); - } else if (!utils.is.empty(this.prefix)) { + } else if (!is.empty(this.prefix)) { const action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; document[`${this.prefix}${action}${this.property}`](); } diff --git a/src/js/html5.js b/src/js/html5.js index 3818a441..3266a58e 100644 --- a/src/js/html5.js +++ b/src/js/html5.js @@ -3,40 +3,37 @@ // ========================================================================== import support from './support'; -import utils from './utils'; +import { removeElement } from './utils/elements'; +import { triggerEvent } from './utils/events'; +import is from './utils/is'; const html5 = { getSources() { if (!this.isHTML5) { - return null; + return []; } - return this.media.querySelectorAll('source'); - }, - - // Get quality levels - getQualityOptions() { - if (!this.isHTML5) { - return null; - } + const sources = Array.from(this.media.querySelectorAll('source')); - // Get sources - const sources = html5.getSources.call(this); - - if (utils.is.empty(sources)) { - return null; - } + // Filter out unsupported sources (if type is specified) + return sources.filter(source => { + const type = source.getAttribute('type'); - // Get <source> with size attribute - const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size'))); + if (is.empty(type)) { + return true; + } - // If none, bail - if (utils.is.empty(sizes)) { - return null; - } + return support.mime.call(this, type); + }); + }, - // Reduce to unique list - return utils.dedupe(sizes.map(source => Number(source.getAttribute('size')))); + // Get quality levels + getQualityOptions() { + // Get sizes from <source> elements + return html5.getSources + .call(this) + .map(source => Number(source.getAttribute('size'))) + .filter(Boolean); }, extend() { @@ -51,67 +48,47 @@ const html5 = { get() { // Get sources const sources = html5.getSources.call(player); + const source = sources.find(source => source.getAttribute('src') === player.source); - if (utils.is.empty(sources)) { - return null; - } - - const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source); - - if (utils.is.empty(matches)) { - return null; - } - - return Number(matches[0].getAttribute('size')); + // Return size, if match is found + return source && Number(source.getAttribute('size')); }, set(input) { // Get sources const sources = html5.getSources.call(player); - if (utils.is.empty(sources)) { - return; - } - - // Get matches for requested size - const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input); - - // No matches for requested size - if (utils.is.empty(matches)) { - return; - } - - // Get supported sources - const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type'))); + // Get first match for requested size + const source = sources.find(source => Number(source.getAttribute('size')) === input); - // No supported sources - if (utils.is.empty(supported)) { + // No matching source found + if (!source) { return; } - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality: input, - }); - // Get current state - const { currentTime, playing } = player; + const { currentTime, paused, preload, readyState } = player.media; // Set new source - player.media.src = supported[0].getAttribute('src'); - - // Load new source - player.media.load(); - - // Resume playing - if (playing) { - player.play(); + player.media.src = source.getAttribute('src'); + + // Prevent loading if preload="none" and the current source isn't loaded (#1044) + if (preload !== 'none' || readyState) { + // Restore time + player.once('loadedmetadata', () => { + player.currentTime = currentTime; + + // Resume playing + if (!paused) { + player.play(); + } + }); + + // Load new source + player.media.load(); } - // Restore time - player.currentTime = currentTime; - // Trigger change event - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { + triggerEvent.call(player, player.media, 'qualitychange', false, { quality: input, }); }, @@ -126,7 +103,7 @@ const html5 = { } // Remove child sources - utils.removeElement(html5.getSources()); + removeElement(html5.getSources.call(this)); // Set blank video src attribute // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error diff --git a/src/js/i18n.js b/src/js/i18n.js deleted file mode 100644 index 58c3e7cf..00000000 --- a/src/js/i18n.js +++ /dev/null @@ -1,31 +0,0 @@ -// ========================================================================== -// Plyr internationalization -// ========================================================================== - -import utils from './utils'; - -const i18n = { - get(key = '', config = {}) { - if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) { - return ''; - } - - let string = config.i18n[key]; - - const replace = { - '{seektime}': config.seekTime, - '{title}': config.title, - }; - - Object.entries(replace).forEach(([ - key, - value, - ]) => { - string = utils.replaceAll(string, key, value); - }); - - return string; - }, -}; - -export default i18n; diff --git a/src/js/listeners.js b/src/js/listeners.js index f4e9ade3..68a83d0b 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -4,23 +4,30 @@ import controls from './controls'; import ui from './ui'; -import utils from './utils'; - -// Sniff out the browser -const browser = utils.getBrowser(); +import { repaint } from './utils/animation'; +import browser from './utils/browser'; +import { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements'; +import { off, on, once, toggleListener, triggerEvent } from './utils/events'; +import is from './utils/is'; +import { setAspectRatio } from './utils/style'; class Listeners { constructor(player) { this.player = player; this.lastKey = null; + this.focusTimer = null; + this.lastKeyDown = null; this.handleKey = this.handleKey.bind(this); this.toggleMenu = this.toggleMenu.bind(this); + this.setTabFocus = this.setTabFocus.bind(this); this.firstTouch = this.firstTouch.bind(this); } // Handle key presses handleKey(event) { + const { player } = this; + const { elements } = player; const code = event.keyCode ? event.keyCode : event.which; const pressed = event.type === 'keydown'; const repeat = pressed && code === this.lastKey; @@ -32,52 +39,39 @@ class Listeners { // If the event is bubbled from the media element // Firefox doesn't get the keycode for whatever reason - if (!utils.is.number(code)) { + if (!is.number(code)) { return; } // Seek by the number keys const seekByKey = () => { // Divide the max duration into 10th's and times by the number value - this.player.currentTime = this.player.duration / 10 * (code - 48); + player.currentTime = (player.duration / 10) * (code - 48); }; // Handle the key on keydown // Reset on keyup if (pressed) { - // Which keycodes should we prevent default - const preventDefault = [ - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 56, - 57, - 32, - 75, - 38, - 40, - 77, - 39, - 37, - 70, - 67, - 73, - 76, - 79, - ]; - // Check focused element // and if the focused element is not editable (e.g. text input) // and any that accept key input http://webaim.org/techniques/keyboard/ - const focused = utils.getFocusElement(); - if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) { - return; + const focused = document.activeElement; + if (is.element(focused)) { + const { editable } = player.config.selectors; + const { seek } = elements.inputs; + + if (focused !== seek && matches(focused, editable)) { + return; + } + + if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) { + return; + } } + // Which keycodes should we prevent default + const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; + // If the code is found prevent default (e.g. prevent scrolling for arrows) if (preventDefault.includes(code)) { event.preventDefault(); @@ -105,55 +99,55 @@ class Listeners { case 75: // Space and K key if (!repeat) { - this.player.togglePlay(); + player.togglePlay(); } break; case 38: // Arrow up - this.player.increaseVolume(0.1); + player.increaseVolume(0.1); break; case 40: // Arrow down - this.player.decreaseVolume(0.1); + player.decreaseVolume(0.1); break; case 77: // M key if (!repeat) { - this.player.muted = !this.player.muted; + player.muted = !player.muted; } break; case 39: // Arrow forward - this.player.forward(); + player.forward(); break; case 37: // Arrow back - this.player.rewind(); + player.rewind(); break; case 70: // F key - this.player.fullscreen.toggle(); + player.fullscreen.toggle(); break; case 67: // C key if (!repeat) { - this.player.toggleCaptions(); + player.toggleCaptions(); } break; case 76: // L key - this.player.loop = !this.player.loop; + player.loop = !player.loop; break; - /* case 73: + /* case 73: this.setLoop('start'); break; @@ -171,8 +165,8 @@ class Listeners { // Escape is handle natively when in full screen // So we only need to worry about non native - if (!this.player.fullscreen.enabled && this.player.fullscreen.active && code === 27) { - this.player.fullscreen.toggle(); + if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) { + player.fullscreen.toggle(); } // Store last code for next cycle @@ -189,149 +183,289 @@ class Listeners { // Device is touch enabled firstTouch() { - this.player.touch = true; + const { player } = this; + const { elements } = player; + + player.touch = true; // Add touch class - utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true); + toggleClass(elements.container, player.config.classNames.isTouch, true); + } + + setTabFocus(event) { + const { player } = this; + const { elements } = player; + + clearTimeout(this.focusTimer); + + // Ignore any key other than tab + if (event.type === 'keydown' && event.which !== 9) { + return; + } + + // Store reference to event timeStamp + if (event.type === 'keydown') { + this.lastKeyDown = event.timeStamp; + } + + // Remove current classes + const removeCurrent = () => { + const className = player.config.classNames.tabFocus; + const current = getElements.call(player, `.${className}`); + toggleClass(current, className, false); + }; + + // Determine if a key was pressed to trigger this event + const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; + + // Ignore focus events if a key was pressed prior + if (event.type === 'focus' && !wasKeyDown) { + return; + } - // Clean up - utils.off(document.body, 'touchstart', this.firstTouch); + // Remove all current + removeCurrent(); + + // Delay the adding of classname until the focus has changed + // This event fires before the focusin event + this.focusTimer = setTimeout(() => { + const focused = document.activeElement; + + // Ignore if current focus element isn't inside the player + if (!elements.container.contains(focused)) { + return; + } + + toggleClass(document.activeElement, player.config.classNames.tabFocus, true); + }, 10); } // Global window & document listeners global(toggle = true) { + const { player } = this; + // Keyboard shortcuts - if (this.player.config.keyboard.global) { - utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false); + if (player.config.keyboard.global) { + toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false); } // Click anywhere closes menu - utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); + toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events - utils.on(document.body, 'touchstart', this.firstTouch); + once.call(player, document.body, 'touchstart', this.firstTouch); + + // Tab focus detection + toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); } // Container listeners container() { + const { player } = this; + const { config, elements, timers } = player; + // Keyboard shortcuts - if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) { - utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false); + if (!config.keyboard.global && config.keyboard.focused) { + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); } - // Detect tab focus - // Remove class on blur/focusout - utils.on(this.player.elements.container, 'focusout', event => { - utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false); - }); + // Toggle controls on mouse events and entering fullscreen + on.call( + player, + elements.container, + 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', + event => { + const { controls } = elements; + + // Remove button states for fullscreen + if (controls && event.type === 'enterfullscreen') { + controls.pressed = false; + controls.hover = false; + } + + // Show, then hide after a timeout unless another control event occurs + const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); - // Add classname to tabbed elements - utils.on(this.player.elements.container, 'keydown', event => { - if (event.keyCode !== 9) { + let delay = 0; + + if (show) { + ui.toggleControls.call(player, true); + // Use longer timeout for touch devices + delay = player.touch ? 3000 : 2000; + } + + // Clear timer + clearTimeout(timers.controls); + + // Set new timer to prevent flicker when seeking + timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay); + }, + ); + + // Force edge to repaint on exit fullscreen + // TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen + /* if (browser.isEdge) { + on.call(player, elements.container, 'exitfullscreen', () => { + setTimeout(() => repaint(elements.container), 100); + }); + } */ + + // Set a gutter for Vimeo + const setGutter = (ratio, padding, toggle) => { + if (!player.isVimeo) { return; } - // Delay the adding of classname until the focus has changed - // This event fires before the focusin event - setTimeout(() => { - utils.toggleClass(utils.getFocusElement(), this.player.config.classNames.tabFocus, true); - }, 0); - }); + const target = player.elements.wrapper.firstChild; + const [, height] = ratio.split(':').map(Number); + const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number); - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - utils.on(this.player.elements.container, 'mouseenter mouseleave mousemove touchstart touchend touchmove enterfullscreen exitfullscreen', event => { - this.player.toggleControls(event); - }); - } + target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null; + target.style.margin = toggle ? '0 auto' : null; + }; + + // Resize on fullscreen change + const setPlayerSize = measure => { + // If we don't need to measure the viewport + if (!measure) { + return setAspectRatio.call(player); + } + + const rect = elements.container.getBoundingClientRect(); + const { width, height } = rect; + + return setAspectRatio.call(player, `${width}:${height}`); + }; + + const resized = () => { + window.clearTimeout(timers.resized); + timers.resized = window.setTimeout(setPlayerSize, 50); + }; + + on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => { + const { target, usingNative } = player.fullscreen; + + // Ignore for iOS native + if (!player.isEmbed || target !== elements.container) { + return; + } + + const isEnter = event.type === 'enterfullscreen'; + + // Set the player size when entering fullscreen to viewport size + const { padding, ratio } = setPlayerSize(isEnter); + + // Set Vimeo gutter + setGutter(ratio, padding, isEnter); + + // If not using native fullscreen, we need to check for resizes of viewport + if (!usingNative) { + if (isEnter) { + on.call(player, window, 'resize', resized); + } else { + off.call(player, window, 'resize', resized); + } + } + }); } // Listen for media events media() { + const { player } = this; + const { elements } = player; + // Time change on media - utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event)); + on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event)); // Display duration - utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event)); + on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event => + controls.durationUpdate.call(player, event), + ); // Check for audio tracks on load // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point - utils.on(this.player.media, 'loadeddata', () => { - utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio); - utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio); + on.call(player, player.media, 'canplay loadeddata', () => { + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); }); // Handle the media finishing - utils.on(this.player.media, 'ended', () => { + on.call(player, player.media, 'ended', () => { // Show poster on end - if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) { + if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) { // Restart - this.player.restart(); + player.restart(); } }); // Check for buffer progress - utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event)); + on.call(player, player.media, 'progress playing seeking seeked', event => + controls.updateProgress.call(player, event), + ); // Handle volume changes - utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event)); + on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event)); // Handle play/pause - utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event)); + on.call(player, player.media, 'playing play pause ended emptied timeupdate', event => + ui.checkPlaying.call(player, event), + ); // Loading state - utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event)); - - // Check if media failed to load - // utils.on(this.player.media, 'play', event => ui.checkFailed.call(this.player, event)); + on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event)); // If autoplay, then load advertisement if required // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows - utils.on(this.player.media, 'playing', () => { - if (!this.player.ads) { + on.call(player, player.media, 'playing', () => { + if (!player.ads) { return; } // If ads are enabled, wait for them first - if (this.player.ads.enabled && !this.player.ads.initialized) { + if (player.ads.enabled && !player.ads.initialized) { // Wait for manager response - this.player.ads.managerPromise.then(() => this.player.ads.play()).catch(() => this.player.play()); + player.ads.managerPromise.then(() => player.ads.play()).catch(() => player.play()); } }); // Click video - if (this.player.supported.ui && this.player.config.clickToPlay && !this.player.isAudio) { + if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { // Re-fetch the wrapper - const wrapper = utils.getElement.call(this.player, `.${this.player.config.classNames.video}`); + const wrapper = getElement.call(player, `.${player.config.classNames.video}`); // Bail if there's no wrapper (this should never happen) - if (!utils.is.element(wrapper)) { + if (!is.element(wrapper)) { return; } - // On click play, pause ore restart - utils.on(wrapper, 'click', () => { - // Touch devices will just show controls (if we're hiding controls) - if (this.player.config.hideControls && this.player.touch && !this.player.paused) { + // On click play, pause or restart + on.call(player, elements.container, 'click', event => { + const targets = [elements.container, wrapper]; + + // Ignore if click if not container or in video wrapper + if (!targets.includes(event.target) && !wrapper.contains(event.target)) { + return; + } + + // Touch devices will just show controls (if hidden) + if (player.touch && player.config.hideControls) { return; } - if (this.player.paused) { - this.player.play(); - } else if (this.player.ended) { - this.player.restart(); - this.player.play(); + if (player.ended) { + this.proxy(event, player.restart, 'restart'); + this.proxy(event, player.play, 'play'); } else { - this.player.pause(); + this.proxy(event, player.togglePlay, 'play'); } }); } // Disable right click - if (this.player.supported.ui && this.player.config.disableContextMenu) { - utils.on( - this.player.elements.wrapper, + if (player.supported.ui && player.config.disableContextMenu) { + on.call( + player, + elements.wrapper, 'contextmenu', event => { event.preventDefault(); @@ -341,294 +475,395 @@ class Listeners { } // Volume change - utils.on(this.player.media, 'volumechange', () => { + on.call(player, player.media, 'volumechange', () => { // Save to storage - this.player.storage.set({ volume: this.player.volume, muted: this.player.muted }); + player.storage.set({ + volume: player.volume, + muted: player.muted, + }); }); // Speed change - utils.on(this.player.media, 'ratechange', () => { + on.call(player, player.media, 'ratechange', () => { // Update UI - controls.updateSetting.call(this.player, 'speed'); + controls.updateSetting.call(player, 'speed'); // Save to storage - this.player.storage.set({ speed: this.player.speed }); - }); - - // Quality request - utils.on(this.player.media, 'qualityrequested', event => { - // Save to storage - this.player.storage.set({ quality: event.detail.quality }); + player.storage.set({ speed: player.speed }); }); // Quality change - utils.on(this.player.media, 'qualitychange', event => { - // Update UI - controls.updateSetting.call(this.player, 'quality', null, event.detail.quality); - }); - - // Caption language change - utils.on(this.player.media, 'languagechange', () => { + on.call(player, player.media, 'qualitychange', event => { // Update UI - controls.updateSetting.call(this.player, 'captions'); - - // Save to storage - this.player.storage.set({ language: this.player.language }); + controls.updateSetting.call(player, 'quality', null, event.detail.quality); }); - // Captions toggle - utils.on(this.player.media, 'captionsenabled captionsdisabled', () => { - // Update UI - controls.updateSetting.call(this.player, 'captions'); - - // Save to storage - this.player.storage.set({ captions: this.player.captions.active }); + // Update download link when ready and if quality changes + on.call(player, player.media, 'ready qualitychange', () => { + controls.setDownloadLink.call(player); }); // Proxy events to container // Bubble up key events for Edge - utils.on(this.player.media, this.player.config.events.concat([ - 'keyup', - 'keydown', - ]).join(' '), event => { - let detail = {}; + const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); + + on.call(player, player.media, proxyEvents, event => { + let { detail = {} } = event; // Get error details from media if (event.type === 'error') { - detail = this.player.media.error; + detail = player.media.error; } - utils.dispatchEvent.call(this.player, this.player.elements.container, event.type, true, detail); + triggerEvent.call(player, elements.container, event.type, true, detail); }); } - // Listen for control events - controls() { - // IE doesn't support input event, so we fallback to change - const inputEvent = browser.isIE ? 'change' : 'input'; + // Run default and custom handlers + proxy(event, defaultHandler, customHandlerKey) { + const { player } = this; + const customHandler = player.config.listeners[customHandlerKey]; + const hasCustomHandler = is.function(customHandler); + let returned = true; - // Run default and custom handlers - const proxy = (event, defaultHandler, customHandlerKey) => { - const customHandler = this.player.config.listeners[customHandlerKey]; - const hasCustomHandler = utils.is.function(customHandler); - let returned = true; + // Execute custom handler + if (hasCustomHandler) { + returned = customHandler.call(player, event); + } - // Execute custom handler - if (hasCustomHandler) { - returned = customHandler.call(this.player, event); - } + // Only call default handler if not prevented in custom handler + if (returned && is.function(defaultHandler)) { + defaultHandler.call(player, event); + } + } - // Only call default handler if not prevented in custom handler - if (returned && utils.is.function(defaultHandler)) { - defaultHandler.call(this.player, event); - } - }; + // Trigger custom and default handlers + bind(element, type, defaultHandler, customHandlerKey, passive = true) { + const { player } = this; + const customHandler = player.config.listeners[customHandlerKey]; + const hasCustomHandler = is.function(customHandler); + + on.call( + player, + element, + type, + event => this.proxy(event, defaultHandler, customHandlerKey), + passive && !hasCustomHandler, + ); + } - // Trigger custom and default handlers - const on = (element, type, defaultHandler, customHandlerKey, passive = true) => { - const customHandler = this.player.config.listeners[customHandlerKey]; - const hasCustomHandler = utils.is.function(customHandler); + // Listen for control events + controls() { + const { player } = this; + const { elements } = player; - utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler); - }; + // IE doesn't support input event, so we fallback to change + const inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle - on(this.player.elements.buttons.play, 'click', this.player.togglePlay, 'play'); + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(button => { + this.bind(button, 'click', player.togglePlay, 'play'); + }); + } // Pause - on(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart'); + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind - on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind'); + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind - on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward'); + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle - on( - this.player.elements.buttons.mute, + this.bind( + elements.buttons.mute, 'click', () => { - this.player.muted = !this.player.muted; + player.muted = !player.muted; }, 'mute', ); // Captions toggle - on(this.player.elements.buttons.captions, 'click', this.player.toggleCaptions); + this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions()); + + // Download + this.bind( + elements.buttons.download, + 'click', + () => { + triggerEvent.call(player, player.media, 'download'); + }, + 'download', + ); // Fullscreen toggle - on( - this.player.elements.buttons.fullscreen, + this.bind( + elements.buttons.fullscreen, 'click', () => { - this.player.fullscreen.toggle(); + player.fullscreen.toggle(); }, 'fullscreen', ); // Picture-in-Picture - on( - this.player.elements.buttons.pip, + this.bind( + elements.buttons.pip, 'click', () => { - this.player.pip = 'toggle'; + player.pip = 'toggle'; }, 'pip', ); // Airplay - on(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay'); + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); - // Settings menu - on(this.player.elements.buttons.settings, 'click', event => { - controls.toggleMenu.call(this.player, event); + // Settings menu - click toggle + this.bind(elements.buttons.settings, 'click', event => { + // Prevent the document click listener closing the menu + event.stopPropagation(); + + controls.toggleMenu.call(player, event); }); - // Settings menu - on(this.player.elements.settings.form, 'click', event => { - event.stopPropagation(); + // Settings menu - keyboard toggle + // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus + // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 + this.bind( + elements.buttons.settings, + 'keyup', + event => { + const code = event.which; + + // We only care about space and return + if (![13, 32].includes(code)) { + return; + } - // Go back to home tab on click - const showHomeTab = () => { - const id = `plyr-settings-${this.player.id}-home`; - controls.showTab.call(this.player, id); - }; - - // Settings menu items - use event delegation as items are added/removed - if (utils.matches(event.target, this.player.config.selectors.inputs.language)) { - proxy( - event, - () => { - this.player.language = event.target.value; - showHomeTab(); - }, - 'language', - ); - } else if (utils.matches(event.target, this.player.config.selectors.inputs.quality)) { - proxy( - event, - () => { - this.player.quality = event.target.value; - showHomeTab(); - }, - 'quality', - ); - } else if (utils.matches(event.target, this.player.config.selectors.inputs.speed)) { - proxy( - event, - () => { - this.player.speed = parseFloat(event.target.value); - showHomeTab(); - }, - 'speed', - ); - } else { - const tab = event.target; - controls.showTab.call(this.player, tab.getAttribute('aria-controls')); + // Because return triggers a click anyway, all we need to do is set focus + if (code === 13) { + controls.focusFirstMenuItem.call(player, null, true); + return; + } + + // Prevent scroll + event.preventDefault(); + + // Prevent playing video (Firefox) + event.stopPropagation(); + + // Toggle menu + controls.toggleMenu.call(player, event); + }, + null, + false, // Can't be passive as we're preventing default + ); + + // Escape closes menu + this.bind(elements.settings.menu, 'keydown', event => { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); + + // Set range input alternative "value", which matches the tooltip time (#954) + this.bind(elements.inputs.seek, 'mousedown mousemove', event => { + const rect = elements.progress.getBoundingClientRect(); + const percent = (100 / rect.width) * (event.pageX - rect.left); + event.currentTarget.setAttribute('seek-value', percent); + }); + + // Pause while seeking + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => { + const seek = event.currentTarget; + const code = event.keyCode ? event.keyCode : event.which; + const attribute = 'play-on-seeked'; + + if (is.keyboardEvent(event) && (code !== 39 && code !== 37)) { + return; + } + + // Record seek time so we can prevent hiding controls for a few seconds after seek + player.lastSeekTime = Date.now(); + + // Was playing before? + const play = seek.hasAttribute(attribute); + + // Done seeking + const done = ['mouseup', 'touchend', 'keyup'].includes(event.type); + + // If we're done seeking and it was playing, resume playback + if (play && done) { + seek.removeAttribute(attribute); + player.play(); + } else if (!done && player.playing) { + seek.setAttribute(attribute, ''); + player.pause(); } }); + // Fix range inputs on iOS + // Super weird iOS bug where after you interact with an <input type="range">, + // it takes over further interactions on the page. This is a hack + if (browser.isIos) { + const inputs = getElements.call(player, 'input[type="range"]'); + Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target))); + } + // Seek - on( - this.player.elements.inputs.seek, + this.bind( + elements.inputs.seek, inputEvent, event => { - this.player.currentTime = event.target.value / event.target.max * this.player.duration; + const seek = event.currentTarget; + + // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) + let seekTo = seek.getAttribute('seek-value'); + + if (is.empty(seekTo)) { + seekTo = seek.value; + } + + seek.removeAttribute('seek-value'); + + player.currentTime = (seekTo / seek.max) * player.duration; }, 'seek', ); + // Seek tooltip + this.bind(elements.progress, 'mouseenter mouseleave mousemove', event => + controls.updateSeekTooltip.call(player, event), + ); + + // Preview thumbnails plugin + // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this + this.bind(elements.progress, 'mousemove touchmove', event => { + const { previewThumbnails } = player; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startMove(event); + } + }); + + // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering + this.bind(elements.progress, 'mouseleave click', () => { + const { previewThumbnails } = player; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endMove(false, true); + } + }); + + // Show scrubbing preview + this.bind(elements.progress, 'mousedown touchstart', event => { + const { previewThumbnails } = player; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.startScrubbing(event); + } + }); + + this.bind(elements.progress, 'mouseup touchend', event => { + const { previewThumbnails } = player; + + if (previewThumbnails && previewThumbnails.loaded) { + previewThumbnails.endScrubbing(event); + } + }); + + // Polyfill for lower fill in <input type="range"> for webkit + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(element => { + this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target)); + }); + } + // Current time invert // Only if one time element is used for both currentTime and duration - if (this.player.config.toggleInvert && !utils.is.element(this.player.elements.display.duration)) { - on(this.player.elements.display.currentTime, 'click', () => { + if (player.config.toggleInvert && !is.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', () => { // Do nothing if we're at the start - if (this.player.currentTime === 0) { + if (player.currentTime === 0) { return; } - this.player.config.invertTime = !this.player.config.invertTime; - ui.timeUpdate.call(this.player); + player.config.invertTime = !player.config.invertTime; + + controls.timeUpdate.call(player); }); } // Volume - on( - this.player.elements.inputs.volume, + this.bind( + elements.inputs.volume, inputEvent, event => { - this.player.volume = event.target.value; + player.volume = event.target.value; }, 'volume', ); - // Polyfill for lower fill in <input type="range"> for webkit - if (browser.isWebkit) { - on(utils.getElements.call(this.player, 'input[type="range"]'), 'input', event => { - controls.updateRangeFill.call(this.player, event.target); - }); - } + // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) + this.bind(elements.controls, 'mouseenter mouseleave', event => { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; + }); - // Seek tooltip - on(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event)); + // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + }); - // Toggle controls visibility based on mouse movement - if (this.player.config.hideControls) { - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mouseenter mouseleave', event => { - this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter'; - }); + // Show controls when they receive focus (e.g., when using keyboard tab key) + this.bind(elements.controls, 'focusin', () => { + const { config, elements, timers } = player; - // Watch for cursor over controls so they don't hide when trying to interact - on(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => { - this.player.elements.controls.pressed = [ - 'mousedown', - 'touchstart', - ].includes(event.type); - }); + // Skip transition to prevent focus from scrolling the parent element + toggleClass(elements.controls, config.classNames.noTransition, true); - // Focus in/out on controls - on(this.player.elements.controls, 'focusin focusout', event => { - this.player.toggleControls(event); - }); - } + // Toggle + ui.toggleControls.call(player, true); + + // Restore transition + setTimeout(() => { + toggleClass(elements.controls, config.classNames.noTransition, false); + }, 0); + + // Delay a little more for mouse users + const delay = this.touch ? 3000 : 4000; + + // Clear timer + clearTimeout(timers.controls); + + // Hide again after delay + timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay); + }); // Mouse wheel for volume - on( - this.player.elements.inputs.volume, + this.bind( + elements.inputs.volume, 'wheel', event => { // Detect "natural" scroll - suppored on OS X Safari only // Other browsers on OS X will be inverted until support improves const inverted = event.webkitDirectionInvertedFromDevice; - const step = 1 / 50; - let direction = 0; - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - this.player.decreaseVolume(step); - direction = -1; - } else { - this.player.increaseVolume(step); - direction = 1; - } - } - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - this.player.increaseVolume(step); - direction = 1; - } else { - this.player.decreaseVolume(step); - direction = -1; - } - } + // Get delta from event. Invert if `inverted` is true + const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value)); + + // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) + const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); + + // Change the volume by 2% + player.increaseVolume(direction / 50); // Don't break page scrolling at max and min - if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) { + const { volume } = player.media; + if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) { event.preventDefault(); } }, @@ -636,11 +871,6 @@ class Listeners { false, ); } - - // Reset on destroy - clear() { - this.global(false); - } } export default Listeners; diff --git a/src/js/media.js b/src/js/media.js index f10bea1f..eb37d441 100644 --- a/src/js/media.js +++ b/src/js/media.js @@ -5,7 +5,7 @@ import html5 from './html5'; import vimeo from './plugins/vimeo'; import youtube from './plugins/youtube'; -import utils from './utils'; +import { createElement, toggleClass, wrap } from './utils/elements'; const media = { // Setup media @@ -17,50 +17,41 @@ const media = { } // Add type class - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class - utils.toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); + toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds // This will require changes if audio embeds are added if (this.isEmbed) { - utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); + toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true); } // Inject the player wrapper if (this.isVideo) { // Create the wrapper div - this.elements.wrapper = utils.createElement('div', { + this.elements.wrapper = createElement('div', { class: this.config.classNames.video, }); // Wrap the video in a container - utils.wrap(this.media, this.elements.wrapper); + wrap(this.media, this.elements.wrapper); // Faux poster container - this.elements.poster = utils.createElement('div', { + this.elements.poster = createElement('div', { class: this.config.classNames.poster, }); this.elements.wrapper.appendChild(this.elements.poster); } - if (this.isEmbed) { - switch (this.provider) { - case 'youtube': - youtube.setup.call(this); - break; - - case 'vimeo': - vimeo.setup.call(this); - break; - - default: - break; - } - } else if (this.isHTML5) { + if (this.isHTML5) { html5.extend.call(this); + } else if (this.isYouTube) { + youtube.setup.call(this); + } else if (this.isVimeo) { + vimeo.setup.call(this); } }, }; diff --git a/src/js/plugins/ads.js b/src/js/plugins/ads.js index 0246e221..c643c5dd 100644 --- a/src/js/plugins/ads.js +++ b/src/js/plugins/ads.js @@ -6,8 +6,13 @@ /* global google */ -import i18n from '../i18n'; -import utils from '../utils'; +import { createElement } from '../utils/elements'; +import { triggerEvent } from '../utils/events'; +import i18n from '../utils/i18n'; +import is from '../utils/is'; +import loadScript from '../utils/loadScript'; +import { formatTime } from '../utils/time'; +import { buildUrlParams } from '../utils/urls'; class Ads { /** @@ -17,7 +22,7 @@ class Ads { */ constructor(player) { this.player = player; - this.publisherId = player.config.ads.publisherId; + this.config = player.config.ads; this.playing = false; this.initialized = false; this.elements = { @@ -44,7 +49,14 @@ class Ads { } get enabled() { - return this.player.isVideo && this.player.config.ads.enabled && !utils.is.empty(this.publisherId); + const { config } = this; + + return ( + this.player.isHTML5 && + this.player.isVideo && + config.enabled && + (!is.empty(config.publisherId) || is.url(config.tagUrl)) + ); } /** @@ -53,9 +65,8 @@ class Ads { load() { if (this.enabled) { // Check if the Google IMA3 SDK is loaded or load it ourselves - if (!utils.is.object(window.google) || !utils.is.object(window.google.ima)) { - utils - .loadScript(this.player.config.urls.googleIMA.sdk) + if (!is.object(window.google) || !is.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk) .then(() => { this.ready(); }) @@ -89,12 +100,18 @@ class Ads { this.setupIMA(); } - // Build the default tag URL + // Build the tag URL get tagUrl() { + const { config } = this; + + if (is.url(config.tagUrl)) { + return config.tagUrl; + } + const params = { AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', AV_CHANNELID: '5a0458dc28a06145e4519d21', - AV_URL: location.hostname, + AV_URL: window.location.hostname, cb: Date.now(), AV_WIDTH: 640, AV_HEIGHT: 480, @@ -103,7 +120,7 @@ class Ads { const base = 'https://go.aniview.com/api/adserver6/vast/'; - return `${base}?${utils.buildUrlParams(params)}`; + return `${base}?${buildUrlParams(params)}`; } /** @@ -116,7 +133,7 @@ class Ads { */ setupIMA() { // Create the container for our advertisements - this.elements.container = utils.createElement('div', { + this.elements.container = createElement('div', { class: this.player.config.classNames.ads, }); this.player.elements.container.appendChild(this.elements.container); @@ -146,7 +163,11 @@ class Ads { this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events - this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false); + this.loader.addEventListener( + google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, + event => this.onAdsManagerLoaded(event), + false, + ); this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false); // Request video ads @@ -184,7 +205,7 @@ class Ads { } const update = () => { - const time = utils.formatTime(Math.max(this.manager.getRemainingTime(), 0)); + const time = formatTime(Math.max(this.manager.getRemainingTime(), 0)); const label = `${i18n.get('advertisement', this.player.config)} - ${time}`; this.elements.container.setAttribute('data-badge-text', label); }; @@ -197,6 +218,11 @@ class Ads { * @param {Event} adsManagerLoadedEvent */ onAdsManagerLoaded(event) { + // Load could occur after a source change (race condition) + if (!this.enabled) { + return; + } + // Get the ads manager const settings = new google.ima.AdsRenderingSettings(); @@ -212,14 +238,14 @@ class Ads { this.cuePoints = this.manager.getCuePoints(); // Add advertisement cue's within the time line if available - if (!utils.is.empty(this.cuePoints)) { + if (!is.empty(this.cuePoints)) { this.cuePoints.forEach(cuePoint => { if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) { const seekElement = this.player.elements.progress; - if (utils.is.element(seekElement)) { - const cuePercentage = 100 / this.player.duration * cuePoint; - const cue = utils.createElement('span', { + if (is.element(seekElement)) { + const cuePercentage = (100 / this.player.duration) * cuePoint; + const cue = createElement('span', { class: this.player.config.classNames.cues, }); @@ -230,10 +256,6 @@ class Ads { }); } - // Get skippable state - // TODO: Skip button - // this.player.debug.warn(this.manager.getAdSkippableState()); - // Set volume to match player this.manager.setVolume(this.player.volume); @@ -262,11 +284,12 @@ class Ads { // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) // don't have ad object associated const ad = event.getAd(); + const adData = event.getAdData(); // Proxy event const dispatchEvent = type => { const event = `ads${type.replace(/_/g, '').toLowerCase()}`; - utils.dispatchEvent.call(this.player, this.player.media, event); + triggerEvent.call(this.player, this.player.media, event); }; switch (event.type) { @@ -357,6 +380,12 @@ class Ads { dispatchEvent(event.type); break; + case google.ima.AdEvent.Type.LOG: + if (adData.adError) { + this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`); + } + break; + default: break; } @@ -385,15 +414,14 @@ class Ads { this.loader.contentComplete(); }); - this.player.on('seeking', () => { + this.player.on('timeupdate', () => { time = this.player.currentTime; - return time; }); this.player.on('seeked', () => { const seekedTime = this.player.currentTime; - if (utils.is.empty(this.cuePoints)) { + if (is.empty(this.cuePoints)) { return; } @@ -530,9 +558,9 @@ class Ads { trigger(event, ...args) { const handlers = this.events[event]; - if (utils.is.array(handlers)) { + if (is.array(handlers)) { handlers.forEach(handler => { - if (utils.is.function(handler)) { + if (is.function(handler)) { handler.apply(this, args); } }); @@ -546,7 +574,7 @@ class Ads { * @return {Ads} */ on(event, callback) { - if (!utils.is.array(this.events[event])) { + if (!is.array(this.events[event])) { this.events[event] = []; } @@ -577,7 +605,7 @@ class Ads { * @param {string} from */ clearSafetyTimer(from) { - if (!utils.is.nullOrUndefined(this.safetyTimer)) { + if (!is.nullOrUndefined(this.safetyTimer)) { this.player.debug.log(`Safety timer cleared from: ${from}`); clearTimeout(this.safetyTimer); diff --git a/src/js/plugins/previewThumbnails.js b/src/js/plugins/previewThumbnails.js new file mode 100644 index 00000000..6f6b87f5 --- /dev/null +++ b/src/js/plugins/previewThumbnails.js @@ -0,0 +1,636 @@ +import { createElement } from '../utils/elements'; +import { once } from '../utils/events'; +import fetch from '../utils/fetch'; +import is from '../utils/is'; +import { formatTime } from '../utils/time'; + +// Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg" +const parseVtt = vttDataString => { + const processedList = []; + const frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); + + frames.forEach(frame => { + const result = {}; + const lines = frame.split(/\r\n|\n|\r/); + + lines.forEach(line => { + if (!is.number(result.startTime)) { + // The line with start and end times on it is the first line of interest + const matchTimes = line.match( + /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/, + ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT + + if (matchTimes) { + result.startTime = + Number(matchTimes[1]) * 60 * 60 + + Number(matchTimes[2]) * 60 + + Number(matchTimes[3]) + + Number(`0.${matchTimes[4]}`); + result.endTime = + Number(matchTimes[6]) * 60 * 60 + + Number(matchTimes[7]) * 60 + + Number(matchTimes[8]) + + Number(`0.${matchTimes[9]}`); + } + } else if (!is.empty(line.trim()) && is.empty(result.text)) { + // If we already have the startTime, then we're definitely up to the text line(s) + const lineSplit = line.trim().split('#xywh='); + [result.text] = lineSplit; + + // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image + if (lineSplit[1]) { + [result.x, result.y, result.w, result.h] = lineSplit[1].split(','); + } + } + }); + + if (result.text) { + processedList.push(result); + } + }); + + return processedList; +}; + +/** + * Preview thumbnails for seek hover and scrubbing + * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar + * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed + * + * Notes: + * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole + * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails + * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered + */ + +class PreviewThumbnails { + /** + * PreviewThumbnails constructor. + * @param {Plyr} player + * @return {PreviewThumbnails} + */ + constructor(player) { + this.player = player; + this.thumbnails = []; + this.loaded = false; + this.lastMouseMoveTime = Date.now(); + this.mouseDown = false; + this.loadedImages = []; + + this.elements = { + thumb: {}, + scrubbing: {}, + }; + + this.load(); + } + + get enabled() { + return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled; + } + + load() { + // Togglethe regular seek tooltip + if (this.player.elements.display.seekTooltip) { + this.player.elements.display.seekTooltip.hidden = this.enabled; + } + + if (!this.enabled) { + return; + } + + this.getThumbnails().then(() => { + // Render DOM elements + this.render(); + + // Check to see if thumb container size was specified manually in CSS + this.determineContainerAutoSizing(); + + this.loaded = true; + }); + } + + // Download VTT files and parse them + getThumbnails() { + return new Promise(resolve => { + const { src } = this.player.config.previewThumbnails; + + if (is.empty(src)) { + throw new Error('Missing previewThumbnails.src config attribute'); + } + + // If string, convert into single-element list + const urls = is.string(src) ? [src] : src; + + // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails + const promises = urls.map(u => this.getThumbnail(u)); + + Promise.all(promises).then(() => { + // Sort smallest to biggest (e.g., [120p, 480p, 1080p]) + this.thumbnails.sort((x, y) => x.height - y.height); + + this.player.debug.log('Preview thumbnails', this.thumbnails); + + resolve(); + }); + }); + } + + // Process individual VTT file + getThumbnail(url) { + return new Promise(resolve => { + fetch(url).then(response => { + const thumbnail = { + frames: parseVtt(response), + height: null, + urlPrefix: '', + }; + + // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file + // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank + if (!thumbnail.frames[0].text.startsWith('/')) { + thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); + } + + // Download the first frame, so that we can determine/set the height of this thumbnailsDef + const tempImage = new Image(); + + tempImage.onload = () => { + thumbnail.height = tempImage.naturalHeight; + thumbnail.width = tempImage.naturalWidth; + + this.thumbnails.push(thumbnail); + + resolve(); + }; + + tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text; + }); + }); + } + + startMove(event) { + if (!this.loaded) { + return; + } + + if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) { + return; + } + + // Wait until media has a duration + if (!this.player.media.duration) { + return; + } + + if (event.type === 'touchmove') { + // Calculate seek hover position as approx video seconds + this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100); + } else { + // Calculate seek hover position as approx video seconds + const clientRect = this.player.elements.progress.getBoundingClientRect(); + const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left); + this.seekTime = this.player.media.duration * (percentage / 100); + + if (this.seekTime < 0) { + // The mousemove fires for 10+px out to the left + this.seekTime = 0; + } + + if (this.seekTime > this.player.media.duration - 1) { + // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video + this.seekTime = this.player.media.duration - 1; + } + + this.mousePosX = event.pageX; + + // Set time text inside image container + this.elements.thumb.time.innerText = formatTime(this.seekTime); + } + + // Download and show image + this.showImageAtCurrentTime(); + } + + endMove() { + this.toggleThumbContainer(false, true); + } + + startScrubbing(event) { + // Only act on left mouse button (0), or touch device (event.button is false) + if (event.button === false || event.button === 0) { + this.mouseDown = true; + // Wait until media has a duration + if (this.player.media.duration) { + this.toggleScrubbingContainer(true); + this.toggleThumbContainer(false, true); + + // Download and show image + this.showImageAtCurrentTime(); + } + } + } + + finishScrubbing() { + this.mouseDown = false; + + // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview + if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) { + // The video was already seeked/loaded at the chosen time - hide immediately + this.toggleScrubbingContainer(false); + } else { + // The video hasn't seeked yet. Wait for that + once.call(this.player, this.player.media, 'timeupdate', () => { + // Re-check mousedown - we might have already started scrubbing again + if (!this.mouseDown) { + this.toggleScrubbingContainer(false); + } + }); + } + } + + /** + * Setup hooks for Plyr and window events + */ + listeners() { + // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering + this.player.on('play', () => { + this.toggleThumbContainer(false, true); + }); + + this.player.on('seeked', () => { + this.toggleThumbContainer(false); + }); + + this.player.on('timeupdate', () => { + this.lastTime = this.player.media.currentTime; + }); + } + + /** + * Create HTML elements for image containers + */ + render() { + // Create HTML element: plyr__preview-thumbnail-container + this.elements.thumb.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.thumbContainer, + }); + + // Wrapper for the image for styling + this.elements.thumb.imageContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.imageContainer, + }); + this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); + + // Create HTML element, parent+span: time text (e.g., 01:32:00) + const timeContainer = createElement('div', { + class: this.player.config.classNames.previewThumbnails.timeContainer, + }); + + this.elements.thumb.time = createElement('span', {}, '00:00'); + timeContainer.appendChild(this.elements.thumb.time); + + this.elements.thumb.container.appendChild(timeContainer); + + // Inject the whole thumb + this.player.elements.progress.appendChild(this.elements.thumb.container); + + // Create HTML element: plyr__preview-scrubbing-container + this.elements.scrubbing.container = createElement('div', { + class: this.player.config.classNames.previewThumbnails.scrubbingContainer, + }); + + this.player.elements.wrapper.appendChild(this.elements.scrubbing.container); + } + + showImageAtCurrentTime() { + if (this.mouseDown) { + this.setScrubbingContainerSize(); + } else { + this.toggleThumbContainer(true); + this.setThumbContainerSizeAndPos(); + } + + // Find the desired thumbnail index + // TODO: Handle a video longer than the thumbs where thumbNum is null + const thumbNum = this.thumbnails[0].frames.findIndex( + frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime, + ); + const hasThumb = thumbNum >= 0; + let qualityIndex = 0; + + this.toggleThumbContainer(hasThumb); + + // No matching thumb found + if (!hasThumb) { + return; + } + + // Check to see if we've already downloaded higher quality versions of this image + this.thumbnails.forEach((thumbnail, index) => { + if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) { + qualityIndex = index; + } + }); + + // Only proceed if either thumbnum or thumbfilename has changed + if (thumbNum !== this.showingThumb) { + this.showingThumb = thumbNum; + this.loadImage(qualityIndex); + } + } + + // Show the image that's currently specified in this.showingThumb + loadImage(qualityIndex = 0) { + const thumbNum = this.showingThumb; + const thumbnail = this.thumbnails[qualityIndex]; + const { urlPrefix } = thumbnail; + const frame = thumbnail.frames[thumbNum]; + const thumbFilename = thumbnail.frames[thumbNum].text; + const thumbUrl = urlPrefix + thumbFilename; + + if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) { + // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one + // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort + if (this.loadingImage && this.usingSprites) { + this.loadingImage.onload = null; + } + + // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image + // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background + // images causes a flicker. Putting a new image over the top does not + const previewImage = new Image(); + previewImage.src = thumbUrl; + previewImage.dataset.index = thumbNum; + previewImage.dataset.filename = thumbFilename; + this.showingThumbFilename = thumbFilename; + + this.player.debug.log(`Loading image: ${thumbUrl}`); + + // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function... + previewImage.onload = () => + this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true); + this.loadingImage = previewImage; + this.removeOldImages(previewImage); + } else { + // Update the existing image + this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false); + this.currentImageElement.dataset.index = thumbNum; + this.removeOldImages(this.currentImageElement); + } + } + + showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) { + this.player.debug.log( + `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`, + ); + this.setImageSizeAndOffset(previewImage, frame); + + if (newImage) { + this.currentImageContainer.appendChild(previewImage); + this.currentImageElement = previewImage; + + if (!this.loadedImages.includes(thumbFilename)) { + this.loadedImages.push(thumbFilename); + } + } + + // Preload images before and after the current one + // Show higher quality of the same frame + // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading + this.preloadNearby(thumbNum, true) + .then(this.preloadNearby(thumbNum, false)) + .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename)); + } + + // Remove all preview images that aren't the designated current image + removeOldImages(currentImage) { + // Get a list of all images, convert it from a DOM list to an array + Array.from(this.currentImageContainer.children).forEach(image => { + if (image.tagName.toLowerCase() !== 'img') { + return; + } + + const removeDelay = this.usingSprites ? 500 : 1000; + + if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { + // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients + // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function + image.dataset.deleting = true; + // This has to be set before the timeout - to prevent issues switching between hover and scrub + const { currentImageContainer } = this; + + setTimeout(() => { + currentImageContainer.removeChild(image); + this.player.debug.log(`Removing thumb: ${image.dataset.filename}`); + }, removeDelay); + } + }); + } + + // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame + // This will only preload the lowest quality + preloadNearby(thumbNum, forward = true) { + return new Promise(resolve => { + setTimeout(() => { + const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text; + + if (this.showingThumbFilename === oldThumbFilename) { + // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away + let thumbnailsClone; + if (forward) { + thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum); + } else { + thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse(); + } + + let foundOne = false; + + thumbnailsClone.forEach(frame => { + const newThumbFilename = frame.text; + + if (newThumbFilename !== oldThumbFilename) { + // Found one with a different filename. Make sure it hasn't already been loaded on this page visit + if (!this.loadedImages.includes(newThumbFilename)) { + foundOne = true; + this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`); + + const { urlPrefix } = this.thumbnails[0]; + const thumbURL = urlPrefix + newThumbFilename; + + const previewImage = new Image(); + previewImage.src = thumbURL; + previewImage.onload = () => { + this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`); + if (!this.loadedImages.includes(newThumbFilename)) + this.loadedImages.push(newThumbFilename); + + // We don't resolve until the thumb is loaded + resolve(); + }; + } + } + }); + + // If there are none to preload then we want to resolve immediately + if (!foundOne) { + resolve(); + } + } + }, 300); + }); + } + + // If user has been hovering current image for half a second, look for a higher quality one + getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) { + if (currentQualityIndex < this.thumbnails.length - 1) { + // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container + let previewImageHeight = previewImage.naturalHeight; + + if (this.usingSprites) { + previewImageHeight = frame.h; + } + + if (previewImageHeight < this.thumbContainerHeight) { + // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while + setTimeout(() => { + // Make sure the mouse hasn't already moved on and started hovering at another image + if (this.showingThumbFilename === thumbFilename) { + this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`); + this.loadImage(currentQualityIndex + 1); + } + }, 300); + } + } + } + + get currentImageContainer() { + if (this.mouseDown) { + return this.elements.scrubbing.container; + } + + return this.elements.thumb.imageContainer; + } + + get usingSprites() { + return Object.keys(this.thumbnails[0].frames[0]).includes('w'); + } + + get thumbAspectRatio() { + if (this.usingSprites) { + return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h; + } + + return this.thumbnails[0].width / this.thumbnails[0].height; + } + + get thumbContainerHeight() { + if (this.mouseDown) { + // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio); + } + + return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4); + } + + get currentImageElement() { + if (this.mouseDown) { + return this.currentScrubbingImageElement; + } + + return this.currentThumbnailImageElement; + } + + set currentImageElement(element) { + if (this.mouseDown) { + this.currentScrubbingImageElement = element; + } else { + this.currentThumbnailImageElement = element; + } + } + + toggleThumbContainer(toggle = false, clearShowing = false) { + const className = this.player.config.classNames.previewThumbnails.thumbContainerShown; + this.elements.thumb.container.classList.toggle(className, toggle); + + if (!toggle && clearShowing) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + + toggleScrubbingContainer(toggle = false) { + const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown; + this.elements.scrubbing.container.classList.toggle(className, toggle); + + if (!toggle) { + this.showingThumb = null; + this.showingThumbFilename = null; + } + } + + determineContainerAutoSizing() { + if (this.elements.thumb.imageContainer.clientHeight > 20) { + // This will prevent auto sizing in this.setThumbContainerSizeAndPos() + this.sizeSpecifiedInCSS = true; + } + } + + // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS + setThumbContainerSizeAndPos() { + if (!this.sizeSpecifiedInCSS) { + const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio); + this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`; + this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`; + } + + this.setThumbContainerPos(); + } + + setThumbContainerPos() { + const seekbarRect = this.player.elements.progress.getBoundingClientRect(); + const plyrRect = this.player.elements.container.getBoundingClientRect(); + const { container } = this.elements.thumb; + + // Find the lowest and highest desired left-position, so we don't slide out the side of the video container + const minVal = plyrRect.left - seekbarRect.left + 10; + const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; + + // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth + let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; + + if (previewPos < minVal) { + previewPos = minVal; + } + + if (previewPos > maxVal) { + previewPos = maxVal; + } + + container.style.left = `${previewPos}px`; + } + + // Can't use 100% width, in case the video is a different aspect ratio to the video container + setScrubbingContainerSize() { + this.elements.scrubbing.container.style.width = `${this.player.media.clientWidth}px`; + // Can't use media.clientHeight - html5 video goes big and does black bars above and below + this.elements.scrubbing.container.style.height = `${this.player.media.clientWidth / this.thumbAspectRatio}px`; + } + + // Sprites need to be offset to the correct location + setImageSizeAndOffset(previewImage, frame) { + if (!this.usingSprites) { + return; + } + + // Find difference between height and preview container height + const multiplier = this.thumbContainerHeight / frame.h; + + previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`; + previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`; + previewImage.style.left = `-${frame.x * multiplier}px`; + previewImage.style.top = `-${frame.y * multiplier}px`; + } +} + +export default PreviewThumbnails; diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index 0ceb89e5..a7664e73 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -2,23 +2,55 @@ // Vimeo plugin // ========================================================================== -import captions from './../captions'; -import controls from './../controls'; -import ui from './../ui'; -import utils from './../utils'; +import captions from '../captions'; +import controls from '../controls'; +import ui from '../ui'; +import { createElement, replaceElement, toggleClass } from '../utils/elements'; +import { triggerEvent } from '../utils/events'; +import fetch from '../utils/fetch'; +import is from '../utils/is'; +import loadScript from '../utils/loadScript'; +import { extend } from '../utils/objects'; +import { format, stripHTML } from '../utils/strings'; +import { setAspectRatio } from '../utils/style'; +import { buildUrlParams } from '../utils/urls'; + +// Parse Vimeo ID from URL +function parseId(url) { + if (is.empty(url)) { + return null; + } + + if (is.number(Number(url))) { + return url; + } + + const regex = /^.*(vimeo.com\/|video\/)(\d+).*/; + return url.match(regex) ? RegExp.$2 : url; +} + +// Set playback state and trigger change (only on actual change) +function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); + } +} const vimeo = { setup() { // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio - vimeo.setAspectRatio.call(this); + setAspectRatio.call(this); // Load the API if not already - if (!utils.is.object(window.Vimeo)) { - utils - .loadScript(this.config.urls.vimeo.sdk) + if (!is.object(window.Vimeo)) { + loadScript(this.config.urls.vimeo.sdk) .then(() => { vimeo.ready.call(this); }) @@ -30,66 +62,55 @@ const vimeo = { } }, - // Set aspect ratio - // For Vimeo we have an extra 300% height <div> to hide the standard controls and UI - setAspectRatio(input) { - const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':'); - const padding = 100 / ratio[0] * ratio[1]; - this.elements.wrapper.style.paddingBottom = `${padding}%`; - - if (this.supported.ui) { - const height = 240; - const offset = (height - padding) / (height / 50); - - this.media.style.transform = `translateY(-${offset}%)`; - } - }, - // API Ready ready() { const player = this; + const config = player.config.vimeo; // Get Vimeo params for the iframe - const options = { - loop: player.config.loop.active, - autoplay: player.autoplay, - // muted: player.muted, - byline: false, - portrait: false, - title: false, - speed: true, - transparent: 0, - gesture: 'media', - playsinline: !this.config.fullscreen.iosNative, - }; - const params = utils.buildUrlParams(options); + const params = buildUrlParams( + extend( + {}, + { + loop: player.config.loop.active, + autoplay: player.autoplay, + muted: player.muted, + gesture: 'media', + playsinline: !this.config.fullscreen.iosNative, + }, + config, + ), + ); // Get the source URL or ID let source = player.media.getAttribute('src'); // Get from <div> if needed - if (utils.is.empty(source)) { + if (is.empty(source)) { source = player.media.getAttribute(player.config.attributes.embed.id); } - const id = utils.parseVimeoId(source); + const id = parseId(source); // Build an iframe - const iframe = utils.createElement('iframe'); - const src = utils.format(player.config.urls.vimeo.iframe, id, params); + const iframe = createElement('iframe'); + const src = format(player.config.urls.vimeo.iframe, id, params); iframe.setAttribute('src', src); iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('allowtransparency', ''); iframe.setAttribute('allow', 'autoplay'); + // Get poster, if already set + const { poster } = player; + // Inject the package - const wrapper = utils.createElement('div', { class: player.config.classNames.embedContainer }); + const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer }); wrapper.appendChild(iframe); - player.media = utils.replaceElement(wrapper, player.media); + player.media = replaceElement(wrapper, player.media); // Get poster image - utils.fetch(utils.format(player.config.urls.vimeo.api, id), 'json').then(response => { - if (utils.is.empty(response)) { + fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => { + if (is.empty(response)) { return; } @@ -99,11 +120,8 @@ const vimeo = { // Get original image url.pathname = `${url.pathname.split('_')[0]}.jpg`; - // Set attribute - player.media.setAttribute('poster', url.href); - - // Update - ui.setPoster.call(player); + // Set and show poster + ui.setPoster.call(player, url.href).catch(() => {}); }); // Setup instance @@ -123,15 +141,13 @@ const vimeo = { // Create a faux HTML5 API using the Vimeo API player.media.play = () => { - player.embed.play().then(() => { - player.media.paused = false; - }); + assurePlaybackState.call(player, true); + return player.embed.play(); }; player.media.pause = () => { - player.embed.pause().then(() => { - player.media.paused = true; - }); + assurePlaybackState.call(player, false); + return player.embed.pause(); }; player.media.stop = () => { @@ -146,25 +162,27 @@ const vimeo = { return currentTime; }, set(time) { - // Get current paused state - // Vimeo will automatically play on seek - const { paused } = player.media; - - // Set seeking flag - player.media.seeking = true; - - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); - - // Seek after events - player.embed.setCurrentTime(time).catch(() => { - // Do nothing - }); - - // Restore pause state - if (paused) { - player.pause(); - } + // Vimeo will automatically play on seek if the video hasn't been played before + + // Get current paused state and volume etc + const { embed, media, paused, volume } = player; + const restorePause = paused && !embed.hasPlayed; + + // Set seeking state and trigger event + media.seeking = true; + triggerEvent.call(player, media, 'seeking'); + + // If paused, mute until seek is complete + Promise.resolve(restorePause && embed.setVolume(0)) + // Seek + .then(() => embed.setCurrentTime(time)) + // Restore paused + .then(() => restorePause && embed.pause()) + // Restore volume + .then(() => restorePause && embed.setVolume(volume)) + .catch(() => { + // Do nothing + }); }, }); @@ -179,7 +197,7 @@ const vimeo = { .setPlaybackRate(input) .then(() => { speed = input; - utils.dispatchEvent.call(player, player.media, 'ratechange'); + triggerEvent.call(player, player.media, 'ratechange'); }) .catch(error => { // Hide menu item (and menu if empty) @@ -199,7 +217,7 @@ const vimeo = { set(input) { player.embed.setVolume(input).then(() => { volume = input; - utils.dispatchEvent.call(player, player.media, 'volumechange'); + triggerEvent.call(player, player.media, 'volumechange'); }); }, }); @@ -211,11 +229,11 @@ const vimeo = { return muted; }, set(input) { - const toggle = utils.is.boolean(input) ? input : false; + const toggle = is.boolean(input) ? input : false; player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => { muted = toggle; - utils.dispatchEvent.call(player, player.media, 'volumechange'); + triggerEvent.call(player, player.media, 'volumechange'); }); }, }); @@ -227,7 +245,7 @@ const vimeo = { return loop; }, set(input) { - const toggle = utils.is.boolean(input) ? input : player.config.loop.active; + const toggle = is.boolean(input) ? input : player.config.loop.active; player.embed.setLoop(toggle).then(() => { loop = toggle; @@ -241,6 +259,7 @@ const vimeo = { .getVideoUrl() .then(value => { currentSrc = value; + controls.setDownloadLink.call(player); }) .catch(error => { this.debug.warn(error); @@ -260,12 +279,10 @@ const vimeo = { }); // Set aspect ratio based on video size - Promise.all([ - player.embed.getVideoWidth(), - player.embed.getVideoHeight(), - ]).then(dimensions => { - const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]); - vimeo.setAspectRatio.call(this, ratio); + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => { + const [width, height] = dimensions; + player.embed.ratio = `${width}:${height}`; + setAspectRatio.call(this, player.embed.ratio); }); // Set autopause @@ -282,13 +299,13 @@ const vimeo = { // Get current time player.embed.getCurrentTime().then(value => { currentTime = value; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'timeupdate'); }); // Get duration player.embed.getDuration().then(value => { player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); + triggerEvent.call(player, player.media, 'durationchange'); }); // Get captions @@ -297,18 +314,21 @@ const vimeo = { captions.setup.call(player); }); - player.embed.on('cuechange', data => { - let cue = null; - - if (data.cues.length) { - cue = utils.stripHTML(data.cues[0].text); - } - - captions.setText.call(player, cue); + player.embed.on('cuechange', ({ cues = [] }) => { + const strippedCues = cues.map(cue => stripHTML(cue.text)); + captions.updateCues.call(player, strippedCues); }); player.embed.on('loaded', () => { - if (utils.is.element(player.embed.element) && player.supported.ui) { + // Assure state and events are updated on autoplay + player.embed.getPaused().then(paused => { + assurePlaybackState.call(player, !paused); + if (!paused) { + triggerEvent.call(player, player.media, 'playing'); + } + }); + + if (is.element(player.embed.element) && player.supported.ui) { const frame = player.embed.element; // Fix keyboard focus issues @@ -318,32 +338,27 @@ const vimeo = { }); player.embed.on('play', () => { - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - utils.dispatchEvent.call(player, player.media, 'playing'); + assurePlaybackState.call(player, true); + triggerEvent.call(player, player.media, 'playing'); }); player.embed.on('pause', () => { - player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'pause'); + assurePlaybackState.call(player, false); }); player.embed.on('timeupdate', data => { player.media.seeking = false; currentTime = data.seconds; - utils.dispatchEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'timeupdate'); }); player.embed.on('progress', data => { player.media.buffered = data.percent; - utils.dispatchEvent.call(player, player.media, 'progress'); + triggerEvent.call(player, player.media, 'progress'); // Check all loaded if (parseInt(data.percent, 10) === 1) { - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); + triggerEvent.call(player, player.media, 'canplaythrough'); } // Get duration as if we do it before load, it gives an incorrect value @@ -351,25 +366,24 @@ const vimeo = { player.embed.getDuration().then(value => { if (value !== player.media.duration) { player.media.duration = value; - utils.dispatchEvent.call(player, player.media, 'durationchange'); + triggerEvent.call(player, player.media, 'durationchange'); } }); }); player.embed.on('seeked', () => { player.media.seeking = false; - utils.dispatchEvent.call(player, player.media, 'seeked'); - utils.dispatchEvent.call(player, player.media, 'play'); + triggerEvent.call(player, player.media, 'seeked'); }); player.embed.on('ended', () => { player.media.paused = true; - utils.dispatchEvent.call(player, player.media, 'ended'); + triggerEvent.call(player, player.media, 'ended'); }); player.embed.on('error', detail => { player.media.error = detail; - utils.dispatchEvent.call(player, player.media, 'error'); + triggerEvent.call(player, player.media, 'error'); }); // Rebuild UI diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 4fde9319..0bd232e0 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -2,82 +2,52 @@ // YouTube plugin // ========================================================================== -import controls from './../controls'; -import ui from './../ui'; -import utils from './../utils'; - -// Standardise YouTube quality unit -function mapQualityUnit(input) { - switch (input) { - case 'hd2160': - return 2160; - - case 2160: - return 'hd2160'; - - case 'hd1440': - return 1440; - - case 1440: - return 'hd1440'; - - case 'hd1080': - return 1080; - - case 1080: - return 'hd1080'; - - case 'hd720': - return 720; - - case 720: - return 'hd720'; - - case 'large': - return 480; - - case 480: - return 'large'; - - case 'medium': - return 360; - - case 360: - return 'medium'; - - case 'small': - return 240; - - case 240: - return 'small'; - - default: - return 'default'; +import ui from '../ui'; +import { createElement, replaceElement, toggleClass } from '../utils/elements'; +import { triggerEvent } from '../utils/events'; +import fetch from '../utils/fetch'; +import is from '../utils/is'; +import loadImage from '../utils/loadImage'; +import loadScript from '../utils/loadScript'; +import { extend } from '../utils/objects'; +import { format, generateId } from '../utils/strings'; +import { setAspectRatio } from '../utils/style'; + +// Parse YouTube ID from URL +function parseId(url) { + if (is.empty(url)) { + return null; } + + const regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; + return url.match(regex) ? RegExp.$2 : url; } -function mapQualityUnits(levels) { - if (utils.is.empty(levels)) { - return levels; +// Set playback state and trigger change (only on actual change) +function assurePlaybackState(play) { + if (play && !this.embed.hasPlayed) { + this.embed.hasPlayed = true; + } + if (this.media.paused === play) { + this.media.paused = !play; + triggerEvent.call(this, this.media, play ? 'play' : 'pause'); } - - return utils.dedupe(levels.map(level => mapQualityUnit(level))); } const youtube = { setup() { // Add embed class for responsive - utils.toggleClass(this.elements.wrapper, this.config.classNames.embed, true); + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio - youtube.setAspectRatio.call(this); + setAspectRatio.call(this); // Setup API - if (utils.is.object(window.YT) && utils.is.function(window.YT.Player)) { + if (is.object(window.YT) && is.function(window.YT.Player)) { youtube.ready.call(this); } else { // Load the API - utils.loadScript(this.config.urls.youtube.sdk).catch(error => { + loadScript(this.config.urls.youtube.sdk).catch(error => { this.debug.warn('YouTube API failed to load', error); }); @@ -104,10 +74,10 @@ const youtube = { // Try via undocumented API method first // This method disappears now and then though... // https://github.com/sampotts/plyr/issues/709 - if (utils.is.function(this.embed.getVideoData)) { + if (is.function(this.embed.getVideoData)) { const { title } = this.embed.getVideoData(); - if (utils.is.empty(title)) { + if (is.empty(title)) { this.config.title = title; ui.setTitle.call(this); return; @@ -116,13 +86,12 @@ const youtube = { // Or via Google API const key = this.config.keys.google; - if (utils.is.string(key) && !utils.is.empty(key)) { - const url = utils.format(this.config.urls.youtube.api, videoId, key); + if (is.string(key) && !is.empty(key)) { + const url = format(this.config.urls.youtube.api, videoId, key); - utils - .fetch(url) + fetch(url) .then(result => { - if (utils.is.object(result)) { + if (is.object(result)) { this.config.title = result.items[0].snippet.title; ui.setTitle.call(this); } @@ -131,19 +100,13 @@ const youtube = { } }, - // Set aspect ratio - setAspectRatio() { - const ratio = this.config.ratio.split(':'); - this.elements.wrapper.style.paddingBottom = `${100 / ratio[0] * ratio[1]}%`; - }, - // API ready ready() { const player = this; // Ignore already setup (race condition) const currentId = player.media.getAttribute('id'); - if (!utils.is.empty(currentId) && currentId.startsWith('youtube-')) { + if (!is.empty(currentId) && currentId.startsWith('youtube-')) { return; } @@ -151,88 +114,79 @@ const youtube = { let source = player.media.getAttribute('src'); // Get from <div> if needed - if (utils.is.empty(source)) { + if (is.empty(source)) { source = player.media.getAttribute(this.config.attributes.embed.id); } // Replace the <iframe> with a <div> due to YouTube API issues - const videoId = utils.parseYouTubeId(source); - const id = utils.generateId(player.provider); - const container = utils.createElement('div', { id }); - player.media = utils.replaceElement(container, player.media); - - // Set poster image - player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId)); + const videoId = parseId(source); + const id = generateId(player.provider); + + // Get poster, if already set + const { poster } = player; + + // Replace media element + const container = createElement('div', { id, poster }); + player.media = replaceElement(container, player.media); + + // Id to poster wrapper + const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`; + + // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 + .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists + .then(image => ui.setPoster.call(player, image.src)) + .then(posterSrc => { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }) + .catch(() => {}); + + const config = player.config.youtube; // Setup instance // https://developers.google.com/youtube/iframe_api_reference player.embed = new window.YT.Player(id, { videoId, - playerVars: { - autoplay: player.config.autoplay ? 1 : 0, // Autoplay - controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported - rel: 0, // No related vids - showinfo: 0, // Hide info - iv_load_policy: 3, // Hide annotations - modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) - disablekb: 1, // Disable keyboard as we handle it - playsinline: 1, // Allow iOS inline playback - - // Tracking for stats - // origin: window ? `${window.location.protocol}//${window.location.host}` : null, - widget_referrer: window ? window.location.href : null, - - // Captions are flaky on YouTube - cc_load_policy: player.captions.active ? 1 : 0, - cc_lang_pref: player.config.captions.language, - }, + host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + playerVars: extend( + {}, + { + autoplay: player.config.autoplay ? 1 : 0, // Autoplay + hl: player.config.hl, // iframe interface language + controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported + disablekb: 1, // Disable keyboard as we handle it + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback + // Captions are flaky on YouTube + cc_load_policy: player.captions.active ? 1 : 0, + cc_lang_pref: player.config.captions.language, + // Tracking for stats + widget_referrer: window ? window.location.href : null, + }, + config, + ), events: { onError(event) { - // If we've already fired an error, don't do it again - // YouTube fires onError twice - if (utils.is.object(player.media.error)) { - return; - } - - const detail = { - code: event.data, - }; - - // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError - switch (event.data) { - case 2: - detail.message = - 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.'; - break; - - case 5: - detail.message = - 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.'; - break; - - case 100: - detail.message = - 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.'; - break; - - case 101: - case 150: - detail.message = 'The owner of the requested video does not allow it to be played in embedded players.'; - break; - - default: - detail.message = 'An unknown error occured'; - break; + // YouTube may fire onError twice, so only handle it once + if (!player.media.error) { + const code = event.data; + // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError + const message = + { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.', + }[code] || 'An unknown error occured'; + + player.media.error = { code, message }; + + triggerEvent.call(player, player.media, 'error'); } - - player.media.error = detail; - - utils.dispatchEvent.call(player, player.media, 'error'); - }, - onPlaybackQualityChange() { - utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { - quality: player.media.quality, - }); }, onPlaybackRateChange(event) { // Get the instance @@ -241,9 +195,13 @@ const youtube = { // Get current speed player.media.playbackRate = instance.getPlaybackRate(); - utils.dispatchEvent.call(player, player.media, 'ratechange'); + triggerEvent.call(player, player.media, 'ratechange'); }, onReady(event) { + // Bail if onReady has already been called. See issue #1108 + if (is.function(player.media.play)) { + return; + } // Get the instance const instance = event.target; @@ -252,10 +210,12 @@ const youtube = { // Create a faux HTML5 API using the YouTube API player.media.play = () => { + assurePlaybackState.call(player, true); instance.playVideo(); }; player.media.pause = () => { + assurePlaybackState.call(player, false); instance.pauseVideo(); }; @@ -273,22 +233,17 @@ const youtube = { return Number(instance.getCurrentTime()); }, set(time) { - // Vimeo will automatically play on seek - const { paused } = player.media; + // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused && !player.embed.hasPlayed) { + player.embed.mute(); + } - // Set seeking flag + // Set seeking state and trigger event player.media.seeking = true; - - // Trigger seeking - utils.dispatchEvent.call(player, player.media, 'seeking'); + triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent instance.seekTo(time); - - // Restore pause state - if (paused) { - player.pause(); - } }, }); @@ -302,24 +257,6 @@ const youtube = { }, }); - // Quality - Object.defineProperty(player.media, 'quality', { - get() { - return mapQualityUnit(instance.getPlaybackQuality()); - }, - set(input) { - const quality = input; - - // Set via API - instance.setPlaybackQuality(mapQualityUnit(quality)); - - // Trigger request event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality, - }); - }, - }); - // Volume let { volume } = player.config; Object.defineProperty(player.media, 'volume', { @@ -329,7 +266,7 @@ const youtube = { set(input) { volume = input; instance.setVolume(volume * 100); - utils.dispatchEvent.call(player, player.media, 'volumechange'); + triggerEvent.call(player, player.media, 'volumechange'); }, }); @@ -340,10 +277,10 @@ const youtube = { return muted; }, set(input) { - const toggle = utils.is.boolean(input) ? input : muted; + const toggle = is.boolean(input) ? input : muted; muted = toggle; instance[toggle ? 'mute' : 'unMute'](); - utils.dispatchEvent.call(player, player.media, 'volumechange'); + triggerEvent.call(player, player.media, 'volumechange'); }, }); @@ -369,8 +306,8 @@ const youtube = { player.media.setAttribute('tabindex', -1); } - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - utils.dispatchEvent.call(player, player.media, 'durationchange'); + triggerEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'durationchange'); // Reset timer clearInterval(player.timers.buffering); @@ -382,7 +319,7 @@ const youtube = { // Trigger progress only when we actually buffer something if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) { - utils.dispatchEvent.call(player, player.media, 'progress'); + triggerEvent.call(player, player.media, 'progress'); } // Set last buffer point @@ -393,7 +330,7 @@ const youtube = { clearInterval(player.timers.buffering); // Trigger event - utils.dispatchEvent.call(player, player.media, 'canplaythrough'); + triggerEvent.call(player, player.media, 'canplaythrough'); } }, 200); @@ -407,6 +344,14 @@ const youtube = { // Reset timer clearInterval(player.timers.playing); + const seeked = player.media.seeking && [1, 2].includes(event.data); + + if (seeked) { + // Unset seeking and fire seeked event + player.media.seeking = false; + triggerEvent.call(player, player.media, 'seeked'); + } + // Handle events // -1 Unstarted // 0 Ended @@ -417,16 +362,16 @@ const youtube = { switch (event.data) { case -1: // Update scrubber - utils.dispatchEvent.call(player, player.media, 'timeupdate'); + triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube player.media.buffered = instance.getVideoLoadedFraction(); - utils.dispatchEvent.call(player, player.media, 'progress'); + triggerEvent.call(player, player.media, 'progress'); break; case 0: - player.media.paused = true; + assurePlaybackState.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. if (player.media.loop) { @@ -434,48 +379,42 @@ const youtube = { instance.stopVideo(); instance.playVideo(); } else { - utils.dispatchEvent.call(player, player.media, 'ended'); + triggerEvent.call(player, player.media, 'ended'); } break; case 1: - // If we were seeking, fire seeked event - if (player.media.seeking) { - utils.dispatchEvent.call(player, player.media, 'seeked'); - } - player.media.seeking = false; - - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; - - utils.dispatchEvent.call(player, player.media, 'playing'); - - // Poll to get playback progress - player.timers.playing = setInterval(() => { - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }, 50); - - // Check duration again due to YouTube bug - // https://github.com/sampotts/plyr/issues/374 - // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - if (player.media.duration !== instance.getDuration()) { - player.media.duration = instance.getDuration(); - utils.dispatchEvent.call(player, player.media, 'durationchange'); + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused && !player.embed.hasPlayed) { + player.media.pause(); + } else { + assurePlaybackState.call(player, true); + + triggerEvent.call(player, player.media, 'playing'); + + // Poll to get playback progress + player.timers.playing = setInterval(() => { + triggerEvent.call(player, player.media, 'timeupdate'); + }, 50); + + // Check duration again due to YouTube bug + // https://github.com/sampotts/plyr/issues/374 + // https://code.google.com/p/gdata-issues/issues/detail?id=8690 + if (player.media.duration !== instance.getDuration()) { + player.media.duration = instance.getDuration(); + triggerEvent.call(player, player.media, 'durationchange'); + } } - // Get quality - controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels())); - break; case 2: - player.media.paused = true; - - utils.dispatchEvent.call(player, player.media, 'pause'); + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } + assurePlaybackState.call(player, false); break; @@ -483,7 +422,7 @@ const youtube = { break; } - utils.dispatchEvent.call(player, player.elements.container, 'statechange', false, { + triggerEvent.call(player, player.elements.container, 'statechange', false, { code: event.data, }); }, diff --git a/src/js/plyr.js b/src/js/plyr.js index c2a1d6e3..927eb33d 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,24 +1,32 @@ // ========================================================================== // Plyr -// plyr.js v3.3.6 +// plyr.js v3.4.8 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== import captions from './captions'; +import defaults from './config/defaults'; +import { pip } from './config/states'; +import { getProviderByUrl, providers, types } from './config/types'; import Console from './console'; import controls from './controls'; -import defaults from './defaults'; import Fullscreen from './fullscreen'; import Listeners from './listeners'; import media from './media'; import Ads from './plugins/ads'; +import PreviewThumbnails from './plugins/previewThumbnails'; import source from './source'; import Storage from './storage'; import support from './support'; -import { providers, types } from './types'; import ui from './ui'; -import utils from './utils'; +import { closest } from './utils/arrays'; +import { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements'; +import { off, on, once, triggerEvent, unbindListeners } from './utils/events'; +import is from './utils/is'; +import loadSprite from './utils/loadSprite'; +import { cloneDeep, extend } from './utils/objects'; +import { parseUrl } from './utils/urls'; // Private properties // TODO: Use a WeakMap for private globals @@ -41,20 +49,21 @@ class Plyr { this.media = target; // String selector passed - if (utils.is.string(this.media)) { + if (is.string(this.media)) { this.media = document.querySelectorAll(this.media); } // jQuery, NodeList or Array passed, use first element - if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) { + if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) { // eslint-disable-next-line this.media = this.media[0]; } // Set config - this.config = utils.extend( + this.config = extend( {}, defaults, + Plyr.defaults, options || {}, (() => { try { @@ -68,22 +77,24 @@ class Plyr { // Elements cache this.elements = { container: null, + captions: null, buttons: {}, display: {}, progress: {}, inputs: {}, settings: { + popup: null, menu: null, - panes: {}, - tabs: {}, + panels: {}, + buttons: {}, }, - captions: null, }; // Captions this.captions = { active: null, - currentTrack: null, + currentTrack: -1, + meta: new WeakMap(), }; // Fullscreen @@ -95,7 +106,6 @@ class Plyr { this.options = { speed: [], quality: [], - captions: [], }; // Debugging @@ -107,7 +117,7 @@ class Plyr { this.debug.log('Support', support); // We need an element to setup - if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) { + if (is.nullOrUndefined(this.media) || !is.element(this.media)) { this.debug.error('Setup failed: no suitable element passed'); return; } @@ -143,7 +153,6 @@ class Plyr { // Embed properties let iframe = null; let url = null; - let params = null; // Different setup based on type switch (type) { @@ -152,10 +161,10 @@ class Plyr { iframe = this.media.querySelector('iframe'); // <iframe> type - if (utils.is.element(iframe)) { + if (is.element(iframe)) { // Detect provider - url = iframe.getAttribute('src'); - this.provider = utils.getProviderByUrl(url); + url = parseUrl(iframe.getAttribute('src')); + this.provider = getProviderByUrl(url.toString()); // Rework elements this.elements.container = this.media; @@ -165,24 +174,21 @@ class Plyr { this.elements.container.className = ''; // Get attributes from URL and set config - params = utils.getUrlParams(url); - if (!utils.is.empty(params)) { - const truthy = [ - '1', - 'true', - ]; - - if (truthy.includes(params.autoplay)) { + if (url.search.length) { + const truthy = ['1', 'true']; + + if (truthy.includes(url.searchParams.get('autoplay'))) { this.config.autoplay = true; } - if (truthy.includes(params.loop)) { + if (truthy.includes(url.searchParams.get('loop'))) { this.config.loop.active = true; } // TODO: replace fullscreen.iosNative with this playsinline config option // YouTube requires the playsinline in the URL if (this.isYouTube) { - this.config.playsinline = truthy.includes(params.playsinline); + this.config.playsinline = truthy.includes(url.searchParams.get('playsinline')); + this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language? } else { this.config.playsinline = true; } @@ -196,7 +202,7 @@ class Plyr { } // Unsupported or missing provider - if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { + if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) { this.debug.error('Setup failed: Invalid provider'); return; } @@ -218,7 +224,7 @@ class Plyr { if (this.media.hasAttribute('autoplay')) { this.config.autoplay = true; } - if (this.media.hasAttribute('playsinline')) { + if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) { this.config.playsinline = true; } if (this.media.hasAttribute('muted')) { @@ -244,6 +250,8 @@ class Plyr { return; } + this.eventListeners = []; + // Create listeners this.listeners = new Listeners(this); @@ -254,14 +262,11 @@ class Plyr { this.media.plyr = this; // Wrap media - if (!utils.is.element(this.elements.container)) { - this.elements.container = utils.createElement('div'); - utils.wrap(this.media, this.elements.container); + if (!is.element(this.elements.container)) { + this.elements.container = createElement('div', { tabindex: 0 }); + wrap(this.media, this.elements.container); } - // Allow focus to be captured - this.elements.container.setAttribute('tabindex', 0); - // Add style hook ui.addStyleHook.call(this); @@ -270,7 +275,7 @@ class Plyr { // Listen for events if debugging if (this.config.debug) { - utils.on(this.elements.container, this.config.events.join(' '), event => { + on.call(this, this.elements.container, this.config.events.join(' '), event => { this.debug.log(`event: ${event.type}`); }); } @@ -291,12 +296,22 @@ class Plyr { this.fullscreen = new Fullscreen(this); // Setup ads if provided - this.ads = new Ads(this); + if (this.config.ads.enabled) { + this.ads = new Ads(this); + } // Autoplay if required if (this.config.autoplay) { this.play(); } + + // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek + this.lastSeekTime = 0; + + // Setup preview thumbnails if enabled + if (this.config.previewThumbnails.enabled) { + this.previewThumbnails = new PreviewThumbnails(this); + } } // --------------------------------------- @@ -309,18 +324,23 @@ class Plyr { get isHTML5() { return Boolean(this.provider === providers.html5); } + get isEmbed() { return Boolean(this.isYouTube || this.isVimeo); } + get isYouTube() { return Boolean(this.provider === providers.youtube); } + get isVimeo() { return Boolean(this.provider === providers.vimeo); } + get isVideo() { return Boolean(this.type === types.video); } + get isAudio() { return Boolean(this.type === types.audio); } @@ -329,7 +349,7 @@ class Plyr { * Play the media, or play the advertisement (if they are not blocked) */ play() { - if (!utils.is.function(this.media.play)) { + if (!is.function(this.media.play)) { return null; } @@ -341,7 +361,7 @@ class Plyr { * Pause the media */ pause() { - if (!this.playing || !utils.is.function(this.media.pause)) { + if (!this.playing || !is.function(this.media.pause)) { return; } @@ -382,7 +402,7 @@ class Plyr { */ togglePlay(input) { // Toggle based on current state if nothing passed - const toggle = utils.is.boolean(input) ? input : !this.playing; + const toggle = is.boolean(input) ? input : !this.playing; if (toggle) { this.play(); @@ -398,7 +418,7 @@ class Plyr { if (this.isHTML5) { this.pause(); this.restart(); - } else if (utils.is.function(this.media.stop)) { + } else if (is.function(this.media.stop)) { this.media.stop(); } } @@ -415,7 +435,7 @@ class Plyr { * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime */ rewind(seekTime) { - this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime); + this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime); } /** @@ -423,7 +443,7 @@ class Plyr { * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime */ forward(seekTime) { - this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime); + this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime); } /** @@ -431,21 +451,16 @@ class Plyr { * @param {number} input - where to seek to in seconds. Defaults to 0 (the start) */ set currentTime(input) { - let targetTime = 0; - - if (utils.is.number(input)) { - targetTime = input; + // Bail if media duration isn't available yet + if (!this.duration) { + return; } - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > this.duration) { - targetTime = this.duration; - } + // Validate input + const inputIsValid = is.number(input) && input > 0; // Set - this.media.currentTime = targetTime; + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging this.debug.log(`Seeking to ${this.currentTime} seconds`); @@ -465,7 +480,7 @@ class Plyr { const { buffered } = this.media; // YouTube / Vimeo return a float between 0-1 - if (utils.is.number(buffered)) { + if (is.number(buffered)) { return buffered; } @@ -493,11 +508,12 @@ class Plyr { // Faux duration set via config const fauxDuration = parseFloat(this.config.duration); - // True duration - const realDuration = this.media ? Number(this.media.duration) : 0; + // Media duration can be NaN or Infinity before the media has loaded + const realDuration = (this.media || {}).duration; + const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration; - // If custom duration is funky, use regular duration - return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration; + // If config duration is funky, use regular duration + return fauxDuration || duration; } /** @@ -509,17 +525,17 @@ class Plyr { const max = 1; const min = 0; - if (utils.is.string(volume)) { + if (is.string(volume)) { volume = Number(volume); } // Load volume from storage if no value specified - if (!utils.is.number(volume)) { + if (!is.number(volume)) { volume = this.storage.get('volume'); } // Use config if all else fails - if (!utils.is.number(volume)) { + if (!is.number(volume)) { ({ volume } = this.config); } @@ -539,7 +555,7 @@ class Plyr { this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state - if (!utils.is.empty(value) && this.muted && volume > 0) { + if (!is.empty(value) && this.muted && volume > 0) { this.muted = false; } } @@ -557,7 +573,7 @@ class Plyr { */ increaseVolume(step) { const volume = this.media.muted ? 0 : this.volume; - this.volume = volume + (utils.is.number(step) ? step : 1); + this.volume = volume + (is.number(step) ? step : 0); } /** @@ -565,8 +581,7 @@ class Plyr { * @param {boolean} step - How much to decrease by (between 0 and 1) */ decreaseVolume(step) { - const volume = this.media.muted ? 0 : this.volume; - this.volume = volume - (utils.is.number(step) ? step : 1); + this.increaseVolume(-step); } /** @@ -577,12 +592,12 @@ class Plyr { let toggle = mute; // Load muted state from storage - if (!utils.is.boolean(toggle)) { + if (!is.boolean(toggle)) { toggle = this.storage.get('muted'); } // Use config if all else fails - if (!utils.is.boolean(toggle)) { + if (!is.boolean(toggle)) { toggle = this.config.muted; } @@ -628,15 +643,15 @@ class Plyr { set speed(input) { let speed = null; - if (utils.is.number(input)) { + if (is.number(input)) { speed = input; } - if (!utils.is.number(speed)) { + if (!is.number(speed)) { speed = this.storage.get('speed'); } - if (!utils.is.number(speed)) { + if (!is.number(speed)) { speed = this.config.speed.selected; } @@ -673,39 +688,41 @@ class Plyr { * @param {number} input - Quality level */ set quality(input) { - let quality = null; - - if (!utils.is.empty(input)) { - quality = Number(input); - } + const config = this.config.quality; + const options = this.options.quality; - if (!utils.is.number(quality) || quality === 0) { - quality = this.storage.get('quality'); + if (!options.length) { + return; } - if (!utils.is.number(quality)) { - quality = this.config.quality.selected; - } + let quality = [ + !is.empty(input) && Number(input), + this.storage.get('quality'), + config.selected, + config.default, + ].find(is.number); - if (!utils.is.number(quality)) { - quality = this.config.quality.default; - } + let updateStorage = true; - if (!this.options.quality.length) { - return; - } + if (!options.includes(quality)) { + const value = closest(options, quality); + this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`); + quality = value; - if (!this.options.quality.includes(quality)) { - const closest = utils.closest(this.options.quality, quality); - this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`); - quality = closest; + // Don't update storage if quality is not supported + updateStorage = false; } // Update config - this.config.quality.selected = quality; + config.selected = quality; // Set quality this.media.quality = quality; + + // Save to storage + if (updateStorage) { + this.storage.set({ quality }); + } } /** @@ -721,7 +738,7 @@ class Plyr { * @param {boolean} input - Whether to loop or not */ set loop(input) { - const toggle = utils.is.boolean(input) ? input : this.config.loop.active; + const toggle = is.boolean(input) ? input : this.config.loop.active; this.config.loop.active = toggle; this.media.loop = toggle; @@ -792,6 +809,15 @@ class Plyr { } /** + * Get a download URL (either source or custom) + */ + get download() { + const { download } = this.config.urls; + + return is.url(download) ? download : this.source; + } + + /** * Set the poster image for a video * @param {input} - the URL for the new poster image */ @@ -801,10 +827,7 @@ class Plyr { return; } - if (utils.is.string(input)) { - this.media.setAttribute('poster', input); - ui.setPoster.call(this); - } + ui.setPoster.call(this, input, false).catch(() => {}); } /** @@ -823,7 +846,7 @@ class Plyr { * @param {boolean} input - Whether to autoplay or not */ set autoplay(input) { - const toggle = utils.is.boolean(input) ? input : this.config.autoplay; + const toggle = is.boolean(input) ? input : this.config.autoplay; this.config.autoplay = toggle; } @@ -839,88 +862,39 @@ class Plyr { * @param {boolean} input - Whether to enable captions */ toggleCaptions(input) { - // If there's no full support - if (!this.supported.ui) { - return; - } - - // If the method is called without parameter, toggle based on current value - const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active); - - // Nothing to change... - if (this.captions.active === show) { - return; - } - - // Set global - this.captions.active = show; - - // Toggle state - utils.toggleState(this.elements.buttons.captions, this.captions.active); + captions.toggle.call(this, input, false); + } - // Add class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active); + /** + * Set the caption track by index + * @param {number} - Caption index + */ + set currentTrack(input) { + captions.set.call(this, input, false); + } - // Trigger an event - utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); + /** + * Get the current caption track index (-1 if disabled) + */ + get currentTrack() { + const { toggled, currentTrack } = this.captions; + return toggled ? currentTrack : -1; } /** - * Set the captions language + * Set the wanted language for captions + * Since tracks can be added later it won't update the actual caption track until there is a matching track * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc) */ set language(input) { - // Nothing specified - if (!utils.is.string(input)) { - return; - } - - // If empty string is passed, assume disable captions - if (utils.is.empty(input)) { - this.toggleCaptions(false); - return; - } - - // Normalize - const language = input.toLowerCase(); - - // Check for support - if (!this.options.captions.includes(language)) { - this.debug.warn(`Unsupported language option: ${language}`); - return; - } - - // Ensure captions are enabled - this.toggleCaptions(true); - - // Enabled only - if (language === 'enabled') { - return; - } - - // If nothing to change, bail - if (this.language === language) { - return; - } - - // Update config - this.captions.language = language; - - // Clear caption - captions.setText.call(this, null); - - // Update captions - captions.setLanguage.call(this); - - // Trigger an event - utils.dispatchEvent.call(this, this.media, 'languagechange'); + captions.setLanguage.call(this, input, false); } /** - * Get the current captions language + * Get the current track's language */ get language() { - return this.captions.language; + return (captions.getCurrentTrack.call(this) || {}).language; } /** @@ -929,21 +903,28 @@ class Plyr { * TODO: detect outside changes */ set pip(input) { - const states = { - pip: 'picture-in-picture', - inline: 'inline', - }; - // Bail if no support if (!support.pip) { return; } // Toggle based on current state if not passed - const toggle = utils.is.boolean(input) ? input : this.pip === states.inline; + const toggle = is.boolean(input) ? input : !this.pip; // Toggle based on current state - this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline); + // Safari + if (is.function(this.media.webkitSetPresentationMode)) { + this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive); + } + + // Chrome + if (is.function(this.media.requestPictureInPicture)) { + if (!this.pip && toggle) { + this.media.requestPictureInPicture(); + } else if (this.pip && !toggle) { + document.exitPictureInPicture(); + } + } } /** @@ -954,7 +935,13 @@ class Plyr { return null; } - return this.media.webkitPresentationMode; + // Safari + if (!is.empty(this.media.webkitPresentationMode)) { + return this.media.webkitPresentationMode === pip.active; + } + + // Chrome + return this.media === document.pictureInPictureElement; } /** @@ -970,119 +957,35 @@ class Plyr { /** * Toggle the player controls - * @param {boolean} toggle - Whether to show the controls + * @param {boolean} [toggle] - Whether to show the controls */ toggleControls(toggle) { - // We need controls of course... - if (!utils.is.element(this.elements.controls)) { - return; - } - - // Don't hide if no UI support or it's audio - if (!this.supported.ui || this.isAudio) { - return; - } + // Don't toggle if missing UI support or if it's audio + if (this.supported.ui && !this.isAudio) { + // Get state before change + const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); - let delay = 0; - let show = toggle; - let isEnterFullscreen = false; - - // Get toggle state if not set - if (!utils.is.boolean(toggle)) { - if (utils.is.event(toggle)) { - // Is the enter fullscreen event - isEnterFullscreen = toggle.type === 'enterfullscreen'; - - // Events that show the controls - const showEvents = [ - 'touchstart', - 'touchmove', - 'mouseenter', - 'mousemove', - 'focusin', - ]; - - // Events that delay hiding - const delayEvents = [ - 'touchmove', - 'touchend', - 'mousemove', - ]; - - // Whether to show controls - show = showEvents.includes(toggle.type); - - // Delay hiding on move events - if (delayEvents.includes(toggle.type)) { - delay = 2000; - } - - // Delay a little more for keyboard users - if (!this.touch && toggle.type === 'focusin') { - delay = 3000; - utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); - } - } else { - show = utils.hasClass(this.elements.container, this.config.classNames.hideControls); - } - } + // Negate the argument if not undefined since adding the class to hides the controls + const force = typeof toggle === 'undefined' ? undefined : !toggle; - // Clear timer on every call - clearTimeout(this.timers.controls); + // Apply and get updated state + const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); - // If the mouse is not over the controls, set a timeout to hide them - if (show || this.paused || this.loading) { - // Check if controls toggled - const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false); - - // Trigger event - if (toggled) { - utils.dispatchEvent.call(this, this.media, 'controlsshown'); + // Close menu + if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) { + controls.toggleMenu.call(this, false); } - // Always show controls when paused or if touch - if (this.paused || this.loading) { - return; + // Trigger event on change + if (hiding !== isHidden) { + const eventName = hiding ? 'controlshidden' : 'controlsshown'; + triggerEvent.call(this, this.media, eventName); } - // Delay for hiding on touch - if (this.touch) { - delay = 3000; - } + return !hiding; } - // If toggle is false or if we're playing (regardless of toggle), - // then set the timer to hide the controls - if (!show || this.playing) { - this.timers.controls = setTimeout(() => { - // We need controls of course... - if (!utils.is.element(this.elements.controls)) { - return; - } - - // If the mouse is over the controls (and not entering fullscreen), bail - if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) { - return; - } - - // Restore transition behaviour - if (!utils.hasClass(this.elements.container, this.config.classNames.hideControls)) { - utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, false); - } - - // Set hideControls class - const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, this.config.hideControls); - - // Trigger event and close menu - if (toggled) { - utils.dispatchEvent.call(this, this.media, 'controlshidden'); - - if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) { - controls.toggleMenu.call(this, false); - } - } - }, delay); - } + return false; } /** @@ -1091,7 +994,16 @@ class Plyr { * @param {function} callback - Callback for when event occurs */ on(event, callback) { - utils.on(this.elements.container, event, callback); + on.call(this, this.elements.container, event, callback); + } + + /** + * Add event listeners once + * @param {string} event - Event type + * @param {function} callback - Callback for when event occurs + */ + once(event, callback) { + once.call(this, this.elements.container, event, callback); } /** @@ -1100,7 +1012,7 @@ class Plyr { * @param {function} callback - Callback for when event occurs */ off(event, callback) { - utils.off(this.elements.container, event, callback); + off(this.elements.container, event, callback); } /** @@ -1126,10 +1038,10 @@ class Plyr { if (soft) { if (Object.keys(this.elements).length) { // Remove elements - utils.removeElement(this.elements.buttons.play); - utils.removeElement(this.elements.captions); - utils.removeElement(this.elements.controls); - utils.removeElement(this.elements.wrapper); + removeElement(this.elements.buttons.play); + removeElement(this.elements.captions); + removeElement(this.elements.controls); + removeElement(this.elements.wrapper); // Clear for GC this.elements.buttons.play = null; @@ -1139,21 +1051,21 @@ class Plyr { } // Callback - if (utils.is.function(callback)) { + if (is.function(callback)) { callback(); } } else { // Unbind listeners - this.listeners.clear(); + unbindListeners.call(this); // Replace the container with the original element provided - utils.replaceElement(this.elements.original, this.elements.container); + replaceElement(this.elements.original, this.elements.container); // Event - utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true); + triggerEvent.call(this, this.elements.original, 'destroyed', true); // Callback - if (utils.is.function(callback)) { + if (is.function(callback)) { callback.call(this.elements.original); } @@ -1171,50 +1083,37 @@ class Plyr { // Stop playback this.stop(); - // Type specific stuff - switch (`${this.provider}:${this.type}`) { - case 'html5:video': - case 'html5:audio': - // Clear timeout - clearTimeout(this.timers.loading); - - // Restore native video controls - ui.toggleNativeControls.call(this, true); - - // Clean up - done(); - - break; - - case 'youtube:video': - // Clear timers - clearInterval(this.timers.buffering); - clearInterval(this.timers.playing); - - // Destroy YouTube API - if (this.embed !== null && utils.is.function(this.embed.destroy)) { - this.embed.destroy(); - } - - // Clean up - done(); - - break; - - case 'vimeo:video': - // Destroy Vimeo API - // then clean up (wait, to prevent postmessage errors) - if (this.embed !== null) { - this.embed.unload().then(done); - } - - // Vimeo does not always return - setTimeout(done, 200); + // Provider specific stuff + if (this.isHTML5) { + // Clear timeout + clearTimeout(this.timers.loading); + + // Restore native video controls + ui.toggleNativeControls.call(this, true); + + // Clean up + done(); + } else if (this.isYouTube) { + // Clear timers + clearInterval(this.timers.buffering); + clearInterval(this.timers.playing); + + // Destroy YouTube API + if (this.embed !== null && is.function(this.embed.destroy)) { + this.embed.destroy(); + } - break; + // Clean up + done(); + } else if (this.isVimeo) { + // Destroy Vimeo API + // then clean up (wait, to prevent postmessage errors) + if (this.embed !== null) { + this.embed.unload().then(done); + } - default: - break; + // Vimeo does not always return + setTimeout(done, 200); } } @@ -1242,7 +1141,7 @@ class Plyr { * @param {string} [id] - Unique ID */ static loadSprite(url, id) { - return utils.loadSprite(url, id); + return loadSprite(url, id); } /** @@ -1253,15 +1152,15 @@ class Plyr { static setup(selector, options = {}) { let targets = null; - if (utils.is.string(selector)) { + if (is.string(selector)) { targets = Array.from(document.querySelectorAll(selector)); - } else if (utils.is.nodeList(selector)) { + } else if (is.nodeList(selector)) { targets = Array.from(selector); - } else if (utils.is.array(selector)) { - targets = selector.filter(i => utils.is.element(i)); + } else if (is.array(selector)) { + targets = selector.filter(is.element); } - if (utils.is.empty(targets)) { + if (is.empty(targets)) { return null; } @@ -1269,4 +1168,6 @@ class Plyr { } } +Plyr.defaults = cloneDeep(defaults); + export default Plyr; diff --git a/src/js/plyr.polyfilled.js b/src/js/plyr.polyfilled.js index 0cc3c526..42207a1e 100644 --- a/src/js/plyr.polyfilled.js +++ b/src/js/plyr.polyfilled.js @@ -1,12 +1,12 @@ // ========================================================================== // Plyr Polyfilled Build -// plyr.js v3.3.6 +// plyr.js v3.4.8 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== -import 'babel-polyfill'; import 'custom-event-polyfill'; +import 'url-polyfill'; import Plyr from './plyr'; export default Plyr; diff --git a/src/js/source.js b/src/js/source.js index e9a2938e..0173cc9e 100644 --- a/src/js/source.js +++ b/src/js/source.js @@ -2,23 +2,25 @@ // Plyr source update // ========================================================================== +import { providers } from './config/types'; import html5 from './html5'; import media from './media'; import support from './support'; -import { providers } from './types'; import ui from './ui'; -import utils from './utils'; +import { createElement, insertElement, removeElement } from './utils/elements'; +import is from './utils/is'; +import { getDeep } from './utils/objects'; const source = { // Add elements to HTML5 media (source, tracks, etc) insertElements(type, attributes) { - if (utils.is.string(attributes)) { - utils.insertElement(type, this.media, { + if (is.string(attributes)) { + insertElement(type, this.media, { src: attributes, }); - } else if (utils.is.array(attributes)) { + } else if (is.array(attributes)) { attributes.forEach(attribute => { - utils.insertElement(type, this.media, attribute); + insertElement(type, this.media, attribute); }); } }, @@ -26,7 +28,7 @@ const source = { // Update source // Sources are not checked for support so be careful change(input) { - if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) { + if (!getDeep(input, 'sources.length')) { this.debug.warn('Invalid source format'); return; } @@ -42,47 +44,34 @@ const source = { this.options.quality = []; // Remove elements - utils.removeElement(this.media); + removeElement(this.media); this.media = null; // Reset class name - if (utils.is.element(this.elements.container)) { + if (is.element(this.elements.container)) { this.elements.container.removeAttribute('class'); } // Set the type and provider - this.type = input.type; - this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5; - - // Check for support - this.supported = support.check(this.type, this.provider, this.config.playsinline); - - // Create new markup - switch (`${this.provider}:${this.type}`) { - case 'html5:video': - this.media = utils.createElement('video'); - break; - - case 'html5:audio': - this.media = utils.createElement('audio'); - break; - - case 'youtube:video': - case 'vimeo:video': - this.media = utils.createElement('div', { - src: input.sources[0].src, - }); - break; - - default: - break; - } + const { sources, type } = input; + const [{ provider = providers.html5, src }] = sources; + const tagName = provider === 'html5' ? type : 'div'; + const attributes = provider === 'html5' ? {} : { src }; + + Object.assign(this, { + provider, + type, + // Check for support + supported: support.check(type, provider, this.config.playsinline), + // Create new element + media: createElement(tagName, attributes), + }); // Inject the new element this.elements.container.appendChild(this.media); // Autoplay the new source? - if (utils.is.boolean(input.autoplay)) { + if (is.boolean(input.autoplay)) { this.config.autoplay = input.autoplay; } @@ -94,7 +83,7 @@ const source = { if (this.config.autoplay) { this.media.setAttribute('autoplay', ''); } - if (!utils.is.empty(input.poster)) { + if (!is.empty(input.poster)) { this.poster = input.poster; } if (this.config.loop.active) { @@ -113,7 +102,7 @@ const source = { // Set new sources for html5 if (this.isHTML5) { - source.insertElements.call(this, 'source', input.sources); + source.insertElements.call(this, 'source', sources); } // Set video title @@ -125,12 +114,9 @@ const source = { // HTML5 stuff if (this.isHTML5) { // Setup captions - if ('tracks' in input) { + if (Object.keys(input).includes('tracks')) { source.insertElements.call(this, 'track', input.tracks); } - - // Load HTML5 sources - this.media.load(); } // If HTML5 or embed but not fully supported, setupInterface and call ready now @@ -139,6 +125,16 @@ const source = { ui.build.call(this); } + // Load HTML5 sources + if (this.isHTML5) { + this.media.load(); + } + + // Reload thumbnails + if (this.previewThumbnails) { + this.previewThumbnails.load(); + } + // Update the fullscreen support this.fullscreen.update(); }, diff --git a/src/js/storage.js b/src/js/storage.js index 5b914331..27fdad9f 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -2,7 +2,8 @@ // Plyr storage // ========================================================================== -import utils from './utils'; +import is from './utils/is'; +import { extend } from './utils/objects'; class Storage { constructor(player) { @@ -31,19 +32,19 @@ class Storage { } get(key) { - if (!Storage.supported) { + if (!Storage.supported || !this.enabled) { return null; } const store = window.localStorage.getItem(this.key); - if (utils.is.empty(store)) { + if (is.empty(store)) { return null; } const json = JSON.parse(store); - return utils.is.string(key) && key.length ? json[key] : json; + return is.string(key) && key.length ? json[key] : json; } set(object) { @@ -53,7 +54,7 @@ class Storage { } // Can only store objectst - if (!utils.is.object(object)) { + if (!is.object(object)) { return; } @@ -61,12 +62,12 @@ class Storage { let storage = this.get(); // Default to empty object - if (utils.is.empty(storage)) { + if (is.empty(storage)) { storage = {}; } // Update the working copy of the values - utils.extend(storage, object); + extend(storage, object); // Update storage window.localStorage.setItem(this.key, JSON.stringify(storage)); diff --git a/src/js/support.js b/src/js/support.js index 5528e898..81965867 100644 --- a/src/js/support.js +++ b/src/js/support.js @@ -2,7 +2,19 @@ // Plyr support checks // ========================================================================== -import utils from './utils'; +import { transitionEndEvent } from './utils/animation'; +import browser from './utils/browser'; +import { createElement } from './utils/elements'; +import is from './utils/is'; + +// Default codecs for checking mimetype support +const defaultCodecs = { + 'audio/ogg': 'vorbis', + 'audio/wav': '1', + 'video/webm': 'vp8, vorbis', + 'video/mp4': 'avc1.42E01E, mp4a.40.2', + 'video/ogg': 'theora', +}; // Check for feature support const support = { @@ -13,32 +25,9 @@ const support = { // Check for support // Basic functionality vs full UI check(type, provider, playsinline) { - let api = false; - let ui = false; - const browser = utils.getBrowser(); const canPlayInline = browser.isIPhone && playsinline && support.playsinline; - - switch (`${provider}:${type}`) { - case 'html5:video': - api = support.video; - ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline); - break; - - case 'html5:audio': - api = support.audio; - ui = api && support.rangeInput; - break; - - case 'youtube:video': - case 'vimeo:video': - api = true; - ui = support.rangeInput && (!browser.isIPhone || canPlayInline); - break; - - default: - api = support.audio && support.video; - ui = api && support.rangeInput; - } + const api = support[type] || provider !== 'html5'; + const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline); return { api, @@ -47,15 +36,30 @@ const support = { }, // Picture-in-picture support - // Safari only currently + // Safari & Chrome only currently pip: (() => { - const browser = utils.getBrowser(); - return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode); + if (browser.isIPhone) { + return false; + } + + // Safari + // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls + if (is.function(createElement('video').webkitSetPresentationMode)) { + return true; + } + + // Chrome + // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture + if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) { + return true; + } + + return false; })(), // Airplay support // Safari only currently - airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent), + airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent), // Inline playback support // https://webkit.org/blog/6784/new-video-policies-for-ios/ @@ -64,81 +68,33 @@ const support = { // Check for mime type support against a player instance // Credits: http://diveintohtml5.info/everything.html // Related: http://www.leanbackplayer.com/test/h5mt.html - mime(type) { - const { media } = this; - - try { - // Bail if no checking function - if (!this.isHTML5 || !utils.is.function(media.canPlayType)) { - return false; - } - - // Check directly if codecs specified - if (type.includes('codecs=')) { - return media.canPlayType(type).replace(/no/, ''); - } - - // Type specific checks - if (this.isVideo) { - switch (type) { - case 'video/webm': - return media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''); - - case 'video/mp4': - return media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''); - - case 'video/ogg': - return media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''); - - default: - return false; - } - } else if (this.isAudio) { - switch (type) { - case 'audio/mpeg': - return media.canPlayType('audio/mpeg;').replace(/no/, ''); - - case 'audio/ogg': - return media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''); - - case 'audio/wav': - return media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''); - - default: - return false; - } - } - } catch (e) { + mime(input) { + if (is.empty(input)) { return false; } - // If we got this far, we're stuffed - return false; - }, + const [mediaType] = input.split('/'); + let type = input; - // Check for textTracks support - textTracks: 'textTracks' in document.createElement('video'), + // Verify we're using HTML5 and there's no media type mismatch + if (!this.isHTML5 || mediaType !== this.type) { + return false; + } + + // Add codec if required + if (Object.keys(defaultCodecs).includes(type)) { + type += `; codecs="${defaultCodecs[input]}"`; + } - // Check for passive event listener support - // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - // https://www.youtube.com/watch?v=NPM6172J22g - passiveListeners: (() => { - // Test via a getter in the options object to see if the passive property is accessed - let supported = false; try { - const options = Object.defineProperty({}, 'passive', { - get() { - supported = true; - return null; - }, - }); - window.addEventListener('test', null, options); + return Boolean(type && this.media.canPlayType(type).replace(/no/, '')); } catch (e) { - // Do nothing + return false; } + }, - return supported; - })(), + // Check for textTracks support + textTracks: 'textTracks' in document.createElement('video'), // <input type="range"> Sliders rangeInput: (() => { @@ -152,7 +108,7 @@ const support = { touch: 'ontouchstart' in document.documentElement, // Detect transitions support - transitions: utils.transitionEndEvent !== false, + transitions: transitionEndEvent !== false, // Reduced motion iOS & MacOS setting // https://webkit.org/blog/7551/responsive-design-for-motion/ diff --git a/src/js/types.js b/src/js/types.js deleted file mode 100644 index 35716c3c..00000000 --- a/src/js/types.js +++ /dev/null @@ -1,16 +0,0 @@ -// ========================================================================== -// Plyr supported types and providers -// ========================================================================== - -export const providers = { - html5: 'html5', - youtube: 'youtube', - vimeo: 'vimeo', -}; - -export const types = { - audio: 'audio', - video: 'video', -}; - -export default { providers, types }; diff --git a/src/js/ui.js b/src/js/ui.js index 2347b5c8..8e50bb83 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -4,17 +4,18 @@ import captions from './captions'; import controls from './controls'; -import i18n from './i18n'; import support from './support'; -import utils from './utils'; - -// Sniff out the browser -const browser = utils.getBrowser(); +import browser from './utils/browser'; +import { getElement, toggleClass } from './utils/elements'; +import { ready, triggerEvent } from './utils/events'; +import i18n from './utils/i18n'; +import is from './utils/is'; +import loadImage from './utils/loadImage'; const ui = { addStyleHook() { - utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); - utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); + toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); + toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui); }, // Toggle native HTML5 media controls @@ -44,7 +45,7 @@ const ui = { } // Inject custom controls if not present - if (!utils.is.element(this.elements.controls)) { + if (!is.element(this.elements.controls)) { // Inject custom controls controls.inject.call(this); @@ -55,8 +56,10 @@ const ui = { // Remove native controls ui.toggleNativeControls.call(this); - // Captions - captions.setup.call(this); + // Setup captions for HTML5 + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume this.volume = null; @@ -74,39 +77,51 @@ const ui = { this.quality = null; // Reset volume display - ui.updateVolume.call(this); + controls.updateVolume.call(this); // Reset time display - ui.timeUpdate.call(this); + controls.timeUpdate.call(this); // Update the UI ui.checkPlaying.call(this); // Check for picture-in-picture support - utils.toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); + toggleClass( + this.elements.container, + this.config.classNames.pip.supported, + support.pip && this.isHTML5 && this.isVideo, + ); // Check for airplay support - utils.toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); + toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class - utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); + toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class - utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); + toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls this.ready = true; // Ready event at end of execution stack setTimeout(() => { - utils.dispatchEvent.call(this, this.media, 'ready'); + triggerEvent.call(this, this.media, 'ready'); }, 0); // Set the title ui.setTitle.call(this); - // Set the poster image - ui.setPoster.call(this); + // Assure the poster image is set, if the property was added before the element was created + if (this.poster) { + ui.setPoster.call(this, this.poster, false).catch(() => {}); + } + + // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + if (this.config.duration) { + controls.durationUpdate.call(this); + } }, // Setup aria attribute for play and iframe title @@ -115,245 +130,130 @@ const ui = { let label = i18n.get('play', this.config); // If there's a media title set, use that for the label - if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) { + if (is.string(this.config.title) && !is.empty(this.config.title)) { label += `, ${this.config.title}`; - - // Set container label - this.elements.container.setAttribute('aria-label', this.config.title); } // If there's a play button, set label - if (utils.is.nodeList(this.elements.buttons.play)) { - Array.from(this.elements.buttons.play).forEach(button => { - button.setAttribute('aria-label', label); - }); - } + Array.from(this.elements.buttons.play || []).forEach(button => { + button.setAttribute('aria-label', label); + }); // Set iframe title // https://github.com/sampotts/plyr/issues/124 if (this.isEmbed) { - const iframe = utils.getElement.call(this, 'iframe'); + const iframe = getElement.call(this, 'iframe'); - if (!utils.is.element(iframe)) { + if (!is.element(iframe)) { return; } // Default to media type - const title = !utils.is.empty(this.config.title) ? this.config.title : 'video'; + const title = !is.empty(this.config.title) ? this.config.title : 'video'; const format = i18n.get('frameTitle', this.config); iframe.setAttribute('title', format.replace('{title}', title)); } }, - // Set the poster image - setPoster() { - if (!utils.is.element(this.elements.poster) || utils.is.empty(this.poster)) { - return; + // Toggle poster + togglePoster(enable) { + toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable); + }, + + // Set the poster image (async) + // Used internally for the poster setter, with the passive option forced to false + setPoster(poster, passive = true) { + // Don't override if call is passive + if (passive && this.poster) { + return Promise.reject(new Error('Poster already set')); } - // Set the inline style - const posters = this.poster.split(','); - this.elements.poster.style.backgroundImage = posters.map(p => `url('${p}')`).join(','); + // Set property synchronously to respect the call order + this.media.setAttribute('poster', poster); + + // Wait until ui is ready + return ( + ready + .call(this) + // Load image + .then(() => loadImage(poster)) + .catch(err => { + // Hide poster on error unless it's been set by another call + if (poster === this.poster) { + ui.togglePoster.call(this, false); + } + // Rethrow + throw err; + }) + .then(() => { + // Prevent race conditions + if (poster !== this.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }) + .then(() => { + Object.assign(this.elements.poster.style, { + backgroundImage: `url('${poster}')`, + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '', + }); + ui.togglePoster.call(this, true); + return poster; + }) + ); }, // Check playing state checkPlaying(event) { // Class hooks - utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing); - utils.toggleClass(this.elements.container, this.config.classNames.paused, this.paused); - utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); + toggleClass(this.elements.container, this.config.classNames.playing, this.playing); + toggleClass(this.elements.container, this.config.classNames.paused, this.paused); + toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); - // Set ARIA state - utils.toggleState(this.elements.buttons.play, this.playing); + // Set state + Array.from(this.elements.buttons.play || []).forEach(target => { + target.pressed = this.playing; + }); // Only update controls on non timeupdate events - if (utils.is.event(event) && event.type === 'timeupdate') { + if (is.event(event) && event.type === 'timeupdate') { return; } // Toggle controls - this.toggleControls(!this.playing); + ui.toggleControls.call(this); }, // Check if media is loading checkLoading(event) { - this.loading = [ - 'stalled', - 'waiting', - ].includes(event.type); + this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking this.timers.loading = setTimeout(() => { - // Toggle container class hook - utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading); + // Update progress bar loading class state + toggleClass(this.elements.container, this.config.classNames.loading, this.loading); - // Show controls if loading, hide if done - this.toggleControls(this.loading); + // Update controls visibility + ui.toggleControls.call(this); }, this.loading ? 250 : 0); }, - // Check if media failed to load - checkFailed() { - // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState - this.failed = this.media.networkState === 3; - - if (this.failed) { - utils.toggleClass(this.elements.container, this.config.classNames.loading, false); - utils.toggleClass(this.elements.container, this.config.classNames.error, true); - } - - // Clear timer - clearTimeout(this.timers.failed); + // Toggle controls based on state and `force` argument + toggleControls(force) { + const { controls } = this.elements; - // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(() => { - // Toggle container class hook - utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading); + if (controls && this.config.hideControls) { + // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) + const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now()); - // Show controls if loading, hide if done - this.toggleControls(this.loading); - }, this.loading ? 250 : 0); - }, - - // Update volume UI and storage - updateVolume() { - if (!this.supported.ui) { - return; - } - - // Update range - if (utils.is.element(this.elements.inputs.volume)) { - ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); - } - - // Update mute state - if (utils.is.element(this.elements.buttons.mute)) { - utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); - } - }, - - // Update seek value and lower fill - setRange(target, value = 0) { - if (!utils.is.element(target)) { - return; - } - - // eslint-disable-next-line - target.value = value; - - // Webkit range fill - controls.updateRangeFill.call(this, target); - }, - - // Set <progress> value - setProgress(target, input) { - const value = utils.is.number(input) ? input : 0; - const progress = utils.is.element(target) ? target : this.elements.display.buffer; - - // Update value and label - if (utils.is.element(progress)) { - progress.value = value; - - // Update text label inside - const label = progress.getElementsByTagName('span')[0]; - if (utils.is.element(label)) { - label.childNodes[0].nodeValue = value; - } + // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide + this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek)); } }, - - // Update <progress> elements - updateProgress(event) { - if (!this.supported.ui || !utils.is.event(event)) { - return; - } - - let value = 0; - - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - value = utils.getPercentage(this.currentTime, this.duration); - - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate') { - ui.setRange.call(this, this.elements.inputs.seek, value); - } - - break; - - // Check buffer status - case 'playing': - case 'progress': - ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100); - - break; - - default: - break; - } - } - }, - - // Update the displayed time - updateTimeDisplay(target = null, time = 0, inverted = false) { - // Bail if there's no element to display or the value isn't a number - if (!utils.is.element(target) || !utils.is.number(time)) { - return; - } - - // Always display hours if duration is over an hour - const forceHours = utils.getHours(this.duration) > 0; - - // eslint-disable-next-line no-param-reassign - target.textContent = utils.formatTime(time, forceHours, inverted); - }, - - // Handle time change event - timeUpdate(event) { - // Only invert if only one time element is displayed and used for both duration and currentTime - const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime; - - // Duration - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); - - // Ignore updates while seeking - if (event && event.type === 'timeupdate' && this.media.seeking) { - return; - } - - // Playing progress - ui.updateProgress.call(this, event); - }, - - // Show the duration on metadataloaded - durationUpdate() { - if (!this.supported.ui) { - return; - } - - // If there's a spot to display duration - const hasDuration = utils.is.element(this.elements.display.duration); - - // If there's only one time display, display duration there - if (!hasDuration && this.config.displayDuration && this.paused) { - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); - } - - // If there's a duration element, update content - if (hasDuration) { - ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); - } - - // Update the tooltip (if visible) - controls.updateSeekTooltip.call(this); - }, }; export default ui; diff --git a/src/js/utils.js b/src/js/utils.js deleted file mode 100644 index d46a7601..00000000 --- a/src/js/utils.js +++ /dev/null @@ -1,842 +0,0 @@ -// ========================================================================== -// Plyr utils -// ========================================================================== - -import loadjs from 'loadjs'; -import support from './support'; -import { providers } from './types'; - -const utils = { - // Check variable types - is: { - plyr(input) { - return this.instanceof(input, window.Plyr); - }, - object(input) { - return this.getConstructor(input) === Object; - }, - number(input) { - return this.getConstructor(input) === Number && !Number.isNaN(input); - }, - string(input) { - return this.getConstructor(input) === String; - }, - boolean(input) { - return this.getConstructor(input) === Boolean; - }, - function(input) { - return this.getConstructor(input) === Function; - }, - array(input) { - return !this.nullOrUndefined(input) && Array.isArray(input); - }, - weakMap(input) { - return this.instanceof(input, window.WeakMap); - }, - nodeList(input) { - return this.instanceof(input, window.NodeList); - }, - element(input) { - return this.instanceof(input, window.Element); - }, - textNode(input) { - return this.getConstructor(input) === Text; - }, - event(input) { - return this.instanceof(input, window.Event); - }, - cue(input) { - return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); - }, - track(input) { - return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind)); - }, - url(input) { - return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input); - }, - nullOrUndefined(input) { - return input === null || typeof input === 'undefined'; - }, - empty(input) { - return ( - this.nullOrUndefined(input) || - ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) || - (this.object(input) && !Object.keys(input).length) - ); - }, - instanceof(input, constructor) { - return Boolean(input && constructor && input instanceof constructor); - }, - getConstructor(input) { - return !this.nullOrUndefined(input) ? input.constructor : null; - }, - }, - - // Unfortunately, due to mixed support, UA sniffing is required - getBrowser() { - return { - isIE: /* @cc_on!@ */ false || !!document.documentMode, - isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), - isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), - isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), - }; - }, - - // Fetch wrapper - // Using XHR to avoid issues with older browsers - fetch(url, responseType = 'text') { - return new Promise((resolve, reject) => { - try { - const request = new XMLHttpRequest(); - - // Check for CORS support - if (!('withCredentials' in request)) { - return; - } - - request.addEventListener('load', () => { - if (responseType === 'text') { - try { - resolve(JSON.parse(request.responseText)); - } catch (e) { - resolve(request.responseText); - } - } else { - resolve(request.response); - } - }); - - request.addEventListener('error', () => { - throw new Error(request.statusText); - }); - - request.open('GET', url, true); - - // Set the required response type - request.responseType = responseType; - - request.send(); - } catch (e) { - reject(e); - } - }); - }, - - // Load an external script - loadScript(url) { - return new Promise((resolve, reject) => { - loadjs(url, { - success: resolve, - error: reject, - }); - }); - }, - - // Load an external SVG sprite - loadSprite(url, id) { - if (!utils.is.string(url)) { - return; - } - - const prefix = 'cache-'; - const hasId = utils.is.string(id); - let isCached = false; - - const exists = () => document.querySelectorAll(`#${id}`).length; - - function injectSprite(data) { - // Check again incase of race condition - if (hasId && exists()) { - return; - } - - // Inject content - this.innerHTML = data; - - // Inject the SVG to the body - document.body.insertBefore(this, document.body.childNodes[0]); - } - - // Only load once if ID set - if (!hasId || !exists()) { - // Create container - const container = document.createElement('div'); - utils.toggleHidden(container, true); - - if (hasId) { - container.setAttribute('id', id); - } - - // Check in cache - if (support.storage) { - const cached = window.localStorage.getItem(prefix + id); - isCached = cached !== null; - - if (isCached) { - const data = JSON.parse(cached); - injectSprite.call(container, data.content); - return; - } - } - - // Get the sprite - utils - .fetch(url) - .then(result => { - if (utils.is.empty(result)) { - return; - } - - if (support.storage) { - window.localStorage.setItem( - prefix + id, - JSON.stringify({ - content: result, - }), - ); - } - - injectSprite.call(container, result); - }) - .catch(() => {}); - } - }, - - // Generate a random ID - generateId(prefix) { - return `${prefix}-${Math.floor(Math.random() * 10000)}`; - }, - - // Wrap an element - wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - const targets = elements.length ? elements : [elements]; - - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - Array.from(targets) - .reverse() - .forEach((element, index) => { - const child = index > 0 ? wrapper.cloneNode(true) : wrapper; - - // Cache the current parent and sibling. - const parent = element.parentNode; - const sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - }); - }, - - // Create a DocumentFragment - createElement(type, attributes, text) { - // Create a new <element> - const element = document.createElement(type); - - // Set all passed attributes - if (utils.is.object(attributes)) { - utils.setAttributes(element, attributes); - } - - // Add text node - if (utils.is.string(text)) { - element.textContent = text; - } - - // Return built element - return element; - }, - - // Inaert an element after another - insertAfter(element, target) { - target.parentNode.insertBefore(element, target.nextSibling); - }, - - // Insert a DocumentFragment - insertElement(type, parent, attributes, text) { - // Inject the new <element> - parent.appendChild(utils.createElement(type, attributes, text)); - }, - - // Remove element(s) - removeElement(element) { - if (utils.is.nodeList(element) || utils.is.array(element)) { - Array.from(element).forEach(utils.removeElement); - return; - } - - if (!utils.is.element(element) || !utils.is.element(element.parentNode)) { - return; - } - - element.parentNode.removeChild(element); - }, - - // Remove all child elements - emptyElement(element) { - let { length } = element.childNodes; - - while (length > 0) { - element.removeChild(element.lastChild); - length -= 1; - } - }, - - // Replace element - replaceElement(newChild, oldChild) { - if (!utils.is.element(oldChild) || !utils.is.element(oldChild.parentNode) || !utils.is.element(newChild)) { - return null; - } - - oldChild.parentNode.replaceChild(newChild, oldChild); - - return newChild; - }, - - // Set attributes - setAttributes(element, attributes) { - if (!utils.is.element(element) || utils.is.empty(attributes)) { - return; - } - - Object.entries(attributes).forEach(([ - key, - value, - ]) => { - element.setAttribute(key, value); - }); - }, - - // Get an attribute object from a string selector - getAttributesFromSelector(sel, existingAttributes) { - // For example: - // '.test' to { class: 'test' } - // '#test' to { id: 'test' } - // '[data-test="test"]' to { 'data-test': 'test' } - - if (!utils.is.string(sel) || utils.is.empty(sel)) { - return {}; - } - - const attributes = {}; - const existing = existingAttributes; - - sel.split(',').forEach(s => { - // Remove whitespace - const selector = s.trim(); - const className = selector.replace('.', ''); - const stripped = selector.replace(/[[\]]/g, ''); - - // Get the parts and value - const parts = stripped.split('='); - const key = parts[0]; - const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; - - // Get the first character - const start = selector.charAt(0); - - switch (start) { - case '.': - // Add to existing classname - if (utils.is.object(existing) && utils.is.string(existing.class)) { - existing.class += ` ${className}`; - } - - attributes.class = className; - break; - - case '#': - // ID selector - attributes.id = selector.replace('#', ''); - break; - - case '[': - // Attribute selector - attributes[key] = value; - - break; - - default: - break; - } - }); - - return attributes; - }, - - // Toggle hidden - toggleHidden(element, hidden) { - if (!utils.is.element(element)) { - return; - } - - let hide = hidden; - - if (!utils.is.boolean(hide)) { - hide = !element.hasAttribute('hidden'); - } - - if (hide) { - element.setAttribute('hidden', ''); - } else { - element.removeAttribute('hidden'); - } - }, - - // Toggle class on an element - toggleClass(element, className, toggle) { - if (utils.is.element(element)) { - const contains = element.classList.contains(className); - - element.classList[toggle ? 'add' : 'remove'](className); - - return (toggle && !contains) || (!toggle && contains); - } - - return null; - }, - - // Has class name - hasClass(element, className) { - return utils.is.element(element) && element.classList.contains(className); - }, - - // Element matches selector - matches(element, selector) { - const prototype = { Element }; - - function match() { - return Array.from(document.querySelectorAll(selector)).includes(this); - } - - const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; - - return matches.call(element, selector); - }, - - // Find all elements - getElements(selector) { - return this.elements.container.querySelectorAll(selector); - }, - - // Find a single element - getElement(selector) { - return this.elements.container.querySelector(selector); - }, - - // Get the focused element - getFocusElement() { - let focused = document.activeElement; - - if (!focused || focused === document.body) { - focused = null; - } else { - focused = document.querySelector(':focus'); - } - - return focused; - }, - - // Trap focus inside container - trapFocus(element = null, toggle = false) { - if (!utils.is.element(element)) { - return; - } - - const focusable = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); - const first = focusable[0]; - const last = focusable[focusable.length - 1]; - - const trap = event => { - // Bail if not tab key or not fullscreen - if (event.key !== 'Tab' || event.keyCode !== 9) { - return; - } - - // Get the current focused element - const focused = utils.getFocusElement(); - - if (focused === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - first.focus(); - event.preventDefault(); - } else if (focused === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - last.focus(); - event.preventDefault(); - } - }; - - if (toggle) { - utils.on(this.elements.container, 'keydown', trap, false); - } else { - utils.off(this.elements.container, 'keydown', trap, false); - } - }, - - // Toggle event listener - toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) { - // Bail if no elemetns, event, or callback - if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) { - return; - } - - // If a nodelist is passed, call itself on each node - if (utils.is.nodeList(elements) || utils.is.array(elements)) { - // Create listener for each node - Array.from(elements).forEach(element => { - if (element instanceof Node) { - utils.toggleListener.call(null, element, event, callback, toggle, passive, capture); - } - }); - - return; - } - - // Allow multiple events - const events = event.split(' '); - - // Build options - // Default to just the capture boolean for browsers with no passive listener support - let options = capture; - - // If passive events listeners are supported - if (support.passiveListeners) { - options = { - // Whether the listener can be passive (i.e. default never prevented) - passive, - // Whether the listener is a capturing listener or not - capture, - }; - } - - // If a single node is passed, bind the event listener - events.forEach(type => { - elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); - }); - }, - - // Bind event handler - on(element, events = '', callback, passive = true, capture = false) { - utils.toggleListener(element, events, callback, true, passive, capture); - }, - - // Unbind event handler - off(element, events = '', callback, passive = true, capture = false) { - utils.toggleListener(element, events, callback, false, passive, capture); - }, - - // Trigger event - dispatchEvent(element, type = '', bubbles = false, detail = {}) { - // Bail if no element - if (!utils.is.element(element) || utils.is.empty(type)) { - return; - } - - // Create and dispatch the event - const event = new CustomEvent(type, { - bubbles, - detail: Object.assign({}, detail, { - plyr: utils.is.plyr(this) ? this : null, - }), - }); - - // Dispatch the event - element.dispatchEvent(event); - }, - - // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - toggleState(element, input) { - // If multiple elements passed - if (utils.is.array(element) || utils.is.nodeList(element)) { - Array.from(element).forEach(target => utils.toggleState(target, input)); - return; - } - - // Bail if no target - if (!utils.is.element(element)) { - return; - } - - // Get state - const pressed = element.getAttribute('aria-pressed') === 'true'; - const state = utils.is.boolean(input) ? input : !pressed; - - // Set the attribute on target - element.setAttribute('aria-pressed', state); - }, - - // Format string - format(input, ...args) { - if (utils.is.empty(input)) { - return input; - } - - return input.toString().replace(/{(\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : ''); - }, - - // Get percentage - getPercentage(current, max) { - if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { - return 0; - } - - return (current / max * 100).toFixed(2); - }, - - // Time helpers - getHours(value) { - return parseInt((value / 60 / 60) % 60, 10); - }, - getMinutes(value) { - return parseInt((value / 60) % 60, 10); - }, - getSeconds(value) { - return parseInt(value % 60, 10); - }, - - // Format time to UI friendly string - formatTime(time = 0, displayHours = false, inverted = false) { - // Bail if the value isn't a number - if (!utils.is.number(time)) { - return this.formatTime(null, displayHours, inverted); - } - - // Format time component to add leading zero - const format = value => `0${value}`.slice(-2); - - // Breakdown to hours, mins, secs - let hours = this.getHours(time); - const mins = this.getMinutes(time); - const secs = this.getSeconds(time); - - // Do we need to display hours? - if (displayHours || hours > 0) { - hours = `${hours}:`; - } else { - hours = ''; - } - - // Render - return `${inverted ? '-' : ''}${hours}${format(mins)}:${format(secs)}`; - }, - - // Replace all occurances of a string in a string - replaceAll(input = '', find = '', replace = '') { - return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); - }, - - // Convert to title case - toTitleCase(input = '') { - return input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); - }, - - // Convert string to pascalCase - toPascalCase(input = '') { - let string = input.toString(); - - // Convert kebab case - string = utils.replaceAll(string, '-', ' '); - - // Convert snake case - string = utils.replaceAll(string, '_', ' '); - - // Convert to title case - string = utils.toTitleCase(string); - - // Convert to pascal case - return utils.replaceAll(string, ' ', ''); - }, - - // Convert string to pascalCase - toCamelCase(input = '') { - let string = input.toString(); - - // Convert to pascal case - string = utils.toPascalCase(string); - - // Convert first character to lowercase - return string.charAt(0).toLowerCase() + string.slice(1); - }, - - // Deep extend destination object with N more objects - extend(target = {}, ...sources) { - if (!sources.length) { - return target; - } - - const source = sources.shift(); - - if (!utils.is.object(source)) { - return target; - } - - Object.keys(source).forEach(key => { - if (utils.is.object(source[key])) { - if (!Object.keys(target).includes(key)) { - Object.assign(target, { [key]: {} }); - } - - utils.extend(target[key], source[key]); - } else { - Object.assign(target, { [key]: source[key] }); - } - }); - - return utils.extend(target, ...sources); - }, - - // Remove duplicates in an array - dedupe(array) { - if (!utils.is.array(array)) { - return array; - } - - return array.filter((item, index) => array.indexOf(item) === index); - }, - - // Get the closest value in an array - closest(array, value) { - if (!utils.is.array(array) || !array.length) { - return null; - } - - return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); - }, - - // Get the provider for a given URL - getProviderByUrl(url) { - // YouTube - if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/.test(url)) { - return providers.youtube; - } - - // Vimeo - if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) { - return providers.vimeo; - } - - return null; - }, - - // Parse YouTube ID from URL - parseYouTubeId(url) { - if (utils.is.empty(url)) { - return null; - } - - const regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; - return url.match(regex) ? RegExp.$2 : url; - }, - - // Parse Vimeo ID from URL - parseVimeoId(url) { - if (utils.is.empty(url)) { - return null; - } - - if (utils.is.number(Number(url))) { - return url; - } - - const regex = /^.*(vimeo.com\/|video\/)(\d+).*/; - return url.match(regex) ? RegExp.$2 : url; - }, - - // Convert a URL to a location object - parseUrl(url) { - const parser = document.createElement('a'); - parser.href = url; - return parser; - }, - - // Get URL query parameters - getUrlParams(input) { - let search = input; - - // Parse URL if needed - if (input.startsWith('http://') || input.startsWith('https://')) { - ({ search } = this.parseUrl(input)); - } - - if (this.is.empty(search)) { - return null; - } - - const hashes = search.slice(search.indexOf('?') + 1).split('&'); - - return hashes.reduce((params, hash) => { - const [ - key, - val, - ] = hash.split('='); - - return Object.assign(params, { [key]: decodeURIComponent(val) }); - }, {}); - }, - - // Convert object to URL parameters - buildUrlParams(input) { - if (!utils.is.object(input)) { - return ''; - } - - return Object.keys(input) - .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`) - .join('&'); - }, - - // Remove HTML from a string - stripHTML(source) { - const fragment = document.createDocumentFragment(); - const element = document.createElement('div'); - fragment.appendChild(element); - element.innerHTML = source; - return fragment.firstChild.innerText; - }, - - // Get aspect ratio for dimensions - getAspectRatio(width, height) { - const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); - const ratio = getRatio(width, height); - return `${width / ratio}:${height / ratio}`; - }, - - // Get the transition end event - get transitionEndEvent() { - const element = document.createElement('span'); - - const events = { - WebkitTransition: 'webkitTransitionEnd', - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd otransitionend', - transition: 'transitionend', - }; - - const type = Object.keys(events).find(event => element.style[event] !== undefined); - - return utils.is.string(type) ? events[type] : false; - }, - - // Force repaint of element - repaint(element) { - setTimeout(() => { - utils.toggleHidden(element, true); - element.offsetHeight; // eslint-disable-line - utils.toggleHidden(element, false); - }, 0); - }, -}; - -export default utils; diff --git a/src/js/utils/animation.js b/src/js/utils/animation.js new file mode 100644 index 00000000..6b950b61 --- /dev/null +++ b/src/js/utils/animation.js @@ -0,0 +1,34 @@ +// ========================================================================== +// Animation utils +// ========================================================================== + +import { toggleHidden } from './elements'; +import is from './is'; + +export const transitionEndEvent = (() => { + const element = document.createElement('span'); + + const events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend', + }; + + const type = Object.keys(events).find(event => element.style[event] !== undefined); + + return is.string(type) ? events[type] : false; +})(); + +// Force repaint of element +export function repaint(element) { + setTimeout(() => { + try { + toggleHidden(element, true); + element.offsetHeight; // eslint-disable-line + toggleHidden(element, false); + } catch (e) { + // Do nothing + } + }, 0); +} diff --git a/src/js/utils/arrays.js b/src/js/utils/arrays.js new file mode 100644 index 00000000..69ef242c --- /dev/null +++ b/src/js/utils/arrays.js @@ -0,0 +1,23 @@ +// ========================================================================== +// Array utils +// ========================================================================== + +import is from './is'; + +// Remove duplicates in an array +export function dedupe(array) { + if (!is.array(array)) { + return array; + } + + return array.filter((item, index) => array.indexOf(item) === index); +} + +// Get the closest value in an array +export function closest(array, value) { + if (!is.array(array) || !array.length) { + return null; + } + + return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); +} diff --git a/src/js/utils/browser.js b/src/js/utils/browser.js new file mode 100644 index 00000000..11705074 --- /dev/null +++ b/src/js/utils/browser.js @@ -0,0 +1,14 @@ +// ========================================================================== +// Browser sniffing +// Unfortunately, due to mixed support, UA sniffing is required +// ========================================================================== + +const browser = { + isIE: /* @cc_on!@ */ false || !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), +}; + +export default browser; diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js new file mode 100644 index 00000000..6be634e5 --- /dev/null +++ b/src/js/utils/elements.js @@ -0,0 +1,302 @@ +// ========================================================================== +// Element utils +// ========================================================================== + +import { toggleListener } from './events'; +import is from './is'; + +// Wrap an element +export function wrap(elements, wrapper) { + // Convert `elements` to an array, if necessary. + const targets = elements.length ? elements : [elements]; + + // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + Array.from(targets) + .reverse() + .forEach((element, index) => { + const child = index > 0 ? wrapper.cloneNode(true) : wrapper; + + // Cache the current parent and sibling. + const parent = element.parentNode; + const sibling = element.nextSibling; + + // Wrap the element (is automatically removed from its current + // parent). + child.appendChild(element); + + // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); +} + +// Set attributes +export function setAttributes(element, attributes) { + if (!is.element(element) || is.empty(attributes)) { + return; + } + + // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" + Object.entries(attributes) + .filter(([, value]) => !is.nullOrUndefined(value)) + .forEach(([key, value]) => element.setAttribute(key, value)); +} + +// Create a DocumentFragment +export function createElement(type, attributes, text) { + // Create a new <element> + const element = document.createElement(type); + + // Set all passed attributes + if (is.object(attributes)) { + setAttributes(element, attributes); + } + + // Add text node + if (is.string(text)) { + element.innerText = text; + } + + // Return built element + return element; +} + +// Inaert an element after another +export function insertAfter(element, target) { + if (!is.element(element) || !is.element(target)) { + return; + } + + target.parentNode.insertBefore(element, target.nextSibling); +} + +// Insert a DocumentFragment +export function insertElement(type, parent, attributes, text) { + if (!is.element(parent)) { + return; + } + + parent.appendChild(createElement(type, attributes, text)); +} + +// Remove element(s) +export function removeElement(element) { + if (is.nodeList(element) || is.array(element)) { + Array.from(element).forEach(removeElement); + return; + } + + if (!is.element(element) || !is.element(element.parentNode)) { + return; + } + + element.parentNode.removeChild(element); +} + +// Remove all child elements +export function emptyElement(element) { + if (!is.element(element)) { + return; + } + + let { length } = element.childNodes; + + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } +} + +// Replace element +export function replaceElement(newChild, oldChild) { + if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { + return null; + } + + oldChild.parentNode.replaceChild(newChild, oldChild); + + return newChild; +} + +// Get an attribute object from a string selector +export function getAttributesFromSelector(sel, existingAttributes) { + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + + if (!is.string(sel) || is.empty(sel)) { + return {}; + } + + const attributes = {}; + const existing = existingAttributes; + + sel.split(',').forEach(s => { + // Remove whitespace + const selector = s.trim(); + const className = selector.replace('.', ''); + const stripped = selector.replace(/[[\]]/g, ''); + + // Get the parts and value + const parts = stripped.split('='); + const key = parts[0]; + const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; + + // Get the first character + const start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is.object(existing) && is.string(existing.class)) { + existing.class += ` ${className}`; + } + + attributes.class = className; + break; + + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; + + case '[': + // Attribute selector + attributes[key] = value; + + break; + + default: + break; + } + }); + + return attributes; +} + +// Toggle hidden +export function toggleHidden(element, hidden) { + if (!is.element(element)) { + return; + } + + let hide = hidden; + + if (!is.boolean(hide)) { + hide = !element.hidden; + } + + if (hide) { + element.setAttribute('hidden', ''); + } else { + element.removeAttribute('hidden'); + } +} + +// Mirror Element.classList.toggle, with IE compatibility for "force" argument +export function toggleClass(element, className, force) { + if (is.nodeList(element)) { + return Array.from(element).map(e => toggleClass(e, className, force)); + } + + if (is.element(element)) { + let method = 'toggle'; + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; + } + + element.classList[method](className); + return element.classList.contains(className); + } + + return false; +} + +// Has class name +export function hasClass(element, className) { + return is.element(element) && element.classList.contains(className); +} + +// Element matches selector +export function matches(element, selector) { + const prototype = { Element }; + + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } + + const matches = + prototype.matches || + prototype.webkitMatchesSelector || + prototype.mozMatchesSelector || + prototype.msMatchesSelector || + match; + + return matches.call(element, selector); +} + +// Find all elements +export function getElements(selector) { + return this.elements.container.querySelectorAll(selector); +} + +// Find a single element +export function getElement(selector) { + return this.elements.container.querySelector(selector); +} + +// Trap focus inside container +export function trapFocus(element = null, toggle = false) { + if (!is.element(element)) { + return; + } + + const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); + const first = focusable[0]; + const last = focusable[focusable.length - 1]; + + const trap = event => { + // Bail if not tab key or not fullscreen + if (event.key !== 'Tab' || event.keyCode !== 9) { + return; + } + + // Get the current focused element + const focused = document.activeElement; + + if (focused === last && !event.shiftKey) { + // Move focus to first element that can be tabbed if Shift isn't used + first.focus(); + event.preventDefault(); + } else if (focused === first && event.shiftKey) { + // Move focus to last element that can be tabbed if Shift is used + last.focus(); + event.preventDefault(); + } + }; + + toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); +} + +// Set focus and tab focus class +export function setFocus(element = null, tabFocus = false) { + if (!is.element(element)) { + return; + } + + // Set regular focus + element.focus({ preventScroll: true }); + + // If we want to mimic keyboard focus via tab + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } +} diff --git a/src/js/utils/events.js b/src/js/utils/events.js new file mode 100644 index 00000000..d304c312 --- /dev/null +++ b/src/js/utils/events.js @@ -0,0 +1,120 @@ +// ========================================================================== +// Event utils +// ========================================================================== + +import is from './is'; + +// Check for passive event listener support +// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md +// https://www.youtube.com/watch?v=NPM6172J22g +const supportsPassiveListeners = (() => { + // Test via a getter in the options object to see if the passive property is accessed + let supported = false; + try { + const options = Object.defineProperty({}, 'passive', { + get() { + supported = true; + return null; + }, + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) { + // Do nothing + } + + return supported; +})(); + +// Toggle event listener +export function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) { + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { + return; + } + + // Allow multiple events + const events = event.split(' '); + + // Build options + // Default to just the capture boolean for browsers with no passive listener support + let options = capture; + + // If passive events listeners are supported + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive, + // Whether the listener is a capturing listener or not + capture, + }; + } + + // If a single node is passed, bind the event listener + events.forEach(type => { + if (this && this.eventListeners && toggle) { + // Cache event listener + this.eventListeners.push({ element, type, callback, options }); + } + + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); +} + +// Bind event handler +export function on(element, events = '', callback, passive = true, capture = false) { + toggleListener.call(this, element, events, callback, true, passive, capture); +} + +// Unbind event handler +export function off(element, events = '', callback, passive = true, capture = false) { + toggleListener.call(this, element, events, callback, false, passive, capture); +} + +// Bind once-only event handler +export function once(element, events = '', callback, passive = true, capture = false) { + const onceCallback = (...args) => { + off(element, events, onceCallback, passive, capture); + callback.apply(this, args); + }; + + toggleListener.call(this, element, events, onceCallback, true, passive, capture); +} + +// Trigger event +export function triggerEvent(element, type = '', bubbles = false, detail = {}) { + // Bail if no element + if (!is.element(element) || is.empty(type)) { + return; + } + + // Create and dispatch the event + const event = new CustomEvent(type, { + bubbles, + detail: Object.assign({}, detail, { + plyr: this, + }), + }); + + // Dispatch the event + element.dispatchEvent(event); +} + +// Unbind all cached event listeners +export function unbindListeners() { + if (this && this.eventListeners) { + this.eventListeners.forEach(item => { + const { element, type, callback, options } = item; + element.removeEventListener(type, callback, options); + }); + + this.eventListeners = []; + } +} + +// Run method when / if player is ready +export function ready() { + return new Promise(resolve => + this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve), + ).then(() => {}); +} diff --git a/src/js/utils/fetch.js b/src/js/utils/fetch.js new file mode 100644 index 00000000..ee33ea7c --- /dev/null +++ b/src/js/utils/fetch.js @@ -0,0 +1,42 @@ +// ========================================================================== +// Fetch wrapper +// Using XHR to avoid issues with older browsers +// ========================================================================== + +export default function fetch(url, responseType = 'text') { + return new Promise((resolve, reject) => { + try { + const request = new XMLHttpRequest(); + + // Check for CORS support + if (!('withCredentials' in request)) { + return; + } + + request.addEventListener('load', () => { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); + + request.addEventListener('error', () => { + throw new Error(request.status); + }); + + request.open('GET', url, true); + + // Set the required response type + request.responseType = responseType; + + request.send(); + } catch (e) { + reject(e); + } + }); +} diff --git a/src/js/utils/i18n.js b/src/js/utils/i18n.js new file mode 100644 index 00000000..758ed695 --- /dev/null +++ b/src/js/utils/i18n.js @@ -0,0 +1,47 @@ +// ========================================================================== +// Plyr internationalization +// ========================================================================== + +import is from './is'; +import { getDeep } from './objects'; +import { replaceAll } from './strings'; + +// Skip i18n for abbreviations and brand names +const resources = { + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube', +}; + +const i18n = { + get(key = '', config = {}) { + if (is.empty(key) || is.empty(config)) { + return ''; + } + + let string = getDeep(config.i18n, key); + + if (is.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; + } + + return ''; + } + + const replace = { + '{seektime}': config.seekTime, + '{title}': config.title, + }; + + Object.entries(replace).forEach(([key, value]) => { + string = replaceAll(string, key, value); + }); + + return string; + }, +}; + +export default i18n; diff --git a/src/js/utils/is.js b/src/js/utils/is.js new file mode 100644 index 00000000..ab28f2ab --- /dev/null +++ b/src/js/utils/is.js @@ -0,0 +1,70 @@ +// ========================================================================== +// Type checking utils +// ========================================================================== + +const getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null); +const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor); +const isNullOrUndefined = input => input === null || typeof input === 'undefined'; +const isObject = input => getConstructor(input) === Object; +const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input); +const isString = input => getConstructor(input) === String; +const isBoolean = input => getConstructor(input) === Boolean; +const isFunction = input => getConstructor(input) === Function; +const isArray = input => Array.isArray(input); +const isWeakMap = input => instanceOf(input, WeakMap); +const isNodeList = input => instanceOf(input, NodeList); +const isElement = input => instanceOf(input, Element); +const isTextNode = input => getConstructor(input) === Text; +const isEvent = input => instanceOf(input, Event); +const isKeyboardEvent = input => instanceOf(input, KeyboardEvent); +const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); +const isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind)); + +const isEmpty = input => + isNullOrUndefined(input) || + ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) || + (isObject(input) && !Object.keys(input).length); + +const isUrl = input => { + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } + + // Must be string from here + if (!isString(input)) { + return false; + } + + // Add the protocol if required + let string = input; + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = `http://${input}`; + } + + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } +}; + +export default { + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + url: isUrl, + empty: isEmpty, +}; diff --git a/src/js/utils/loadImage.js b/src/js/utils/loadImage.js new file mode 100644 index 00000000..8acd2496 --- /dev/null +++ b/src/js/utils/loadImage.js @@ -0,0 +1,19 @@ +// ========================================================================== +// Load image avoiding xhr/fetch CORS issues +// Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded +// By default it checks if it is at least 1px, but you can add a second argument to change this +// ========================================================================== + +export default function loadImage(src, minWidth = 1) { + return new Promise((resolve, reject) => { + const image = new Image(); + + const handler = () => { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { onload: handler, onerror: handler, src }); + }); +} diff --git a/src/js/utils/loadScript.js b/src/js/utils/loadScript.js new file mode 100644 index 00000000..81ae36f4 --- /dev/null +++ b/src/js/utils/loadScript.js @@ -0,0 +1,14 @@ +// ========================================================================== +// Load an external script +// ========================================================================== + +import loadjs from 'loadjs'; + +export default function loadScript(url) { + return new Promise((resolve, reject) => { + loadjs(url, { + success: resolve, + error: reject, + }); + }); +} diff --git a/src/js/utils/loadSprite.js b/src/js/utils/loadSprite.js new file mode 100644 index 00000000..917bd6ac --- /dev/null +++ b/src/js/utils/loadSprite.js @@ -0,0 +1,76 @@ +// ========================================================================== +// Sprite loader +// ========================================================================== + +import Storage from '../storage'; +import fetch from './fetch'; +import is from './is'; + +// Load an external SVG sprite +export default function loadSprite(url, id) { + if (!is.string(url)) { + return; + } + + const prefix = 'cache'; + const hasId = is.string(id); + let isCached = false; + + const exists = () => document.getElementById(id) !== null; + + const update = (container, data) => { + container.innerHTML = data; + + // Check again incase of race condition + if (hasId && exists()) { + return; + } + + // Inject the SVG to the body + document.body.insertAdjacentElement('afterbegin', container); + }; + + // Only load once if ID set + if (!hasId || !exists()) { + const useStorage = Storage.supported; + + // Create container + const container = document.createElement('div'); + container.setAttribute('hidden', ''); + + if (hasId) { + container.setAttribute('id', id); + } + + // Check in cache + if (useStorage) { + const cached = window.localStorage.getItem(`${prefix}-${id}`); + isCached = cached !== null; + + if (isCached) { + const data = JSON.parse(cached); + update(container, data.content); + } + } + + // Get the sprite + fetch(url) + .then(result => { + if (is.empty(result)) { + return; + } + + if (useStorage) { + window.localStorage.setItem( + `${prefix}-${id}`, + JSON.stringify({ + content: result, + }), + ); + } + + update(container, result); + }) + .catch(() => {}); + } +} diff --git a/src/js/utils/objects.js b/src/js/utils/objects.js new file mode 100644 index 00000000..225bb459 --- /dev/null +++ b/src/js/utils/objects.js @@ -0,0 +1,42 @@ +// ========================================================================== +// Object utils +// ========================================================================== + +import is from './is'; + +// Clone nested objects +export function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); +} + +// Get a nested value in an object +export function getDeep(object, path) { + return path.split('.').reduce((obj, key) => obj && obj[key], object); +} + +// Deep extend destination object with N more objects +export function extend(target = {}, ...sources) { + if (!sources.length) { + return target; + } + + const source = sources.shift(); + + if (!is.object(source)) { + return target; + } + + Object.keys(source).forEach(key => { + if (is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, { [key]: {} }); + } + + extend(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); + } + }); + + return extend(target, ...sources); +} diff --git a/src/js/utils/strings.js b/src/js/utils/strings.js new file mode 100644 index 00000000..6b9a65a2 --- /dev/null +++ b/src/js/utils/strings.js @@ -0,0 +1,85 @@ +// ========================================================================== +// String utils +// ========================================================================== + +import is from './is'; + +// Generate a random ID +export function generateId(prefix) { + return `${prefix}-${Math.floor(Math.random() * 10000)}`; +} + +// Format string +export function format(input, ...args) { + if (is.empty(input)) { + return input; + } + + return input.toString().replace(/{(\d+)}/g, (match, i) => args[i].toString()); +} + +// Get percentage +export function getPercentage(current, max) { + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } + + return ((current / max) * 100).toFixed(2); +} + +// Replace all occurances of a string in a string +export function replaceAll(input = '', find = '', replace = '') { + return input.replace( + new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), + replace.toString(), + ); +} + +// Convert to title case +export function toTitleCase(input = '') { + return input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); +} + +// Convert string to pascalCase +export function toPascalCase(input = '') { + let string = input.toString(); + + // Convert kebab case + string = replaceAll(string, '-', ' '); + + // Convert snake case + string = replaceAll(string, '_', ' '); + + // Convert to title case + string = toTitleCase(string); + + // Convert to pascal case + return replaceAll(string, ' ', ''); +} + +// Convert string to pascalCase +export function toCamelCase(input = '') { + let string = input.toString(); + + // Convert to pascal case + string = toPascalCase(string); + + // Convert first character to lowercase + return string.charAt(0).toLowerCase() + string.slice(1); +} + +// Remove HTML from a string +export function stripHTML(source) { + const fragment = document.createDocumentFragment(); + const element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; +} + +// Like outerHTML, but also works for DocumentFragment +export function getHTML(element) { + const wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; +} diff --git a/src/js/utils/style.js b/src/js/utils/style.js new file mode 100644 index 00000000..a8eb393b --- /dev/null +++ b/src/js/utils/style.js @@ -0,0 +1,40 @@ +// ========================================================================== +// Style utils +// ========================================================================== + +import is from './is'; + +/* function reduceAspectRatio(width, height) { + const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); + const ratio = getRatio(width, height); + return `${width / ratio}:${height / ratio}`; +} */ + +// Set aspect ratio for responsive container +export function setAspectRatio(input) { + let ratio = input; + + if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { + ({ ratio } = this.embed); + } + + if (!is.string(ratio)) { + ({ ratio } = this.config); + } + + const [x, y] = ratio.split(':').map(Number); + const padding = (100 / x) * y; + + this.elements.wrapper.style.paddingBottom = `${padding}%`; + + // For Vimeo we have an extra <div> to hide the standard controls and UI + if (this.isVimeo && this.supported.ui) { + const height = 240; + const offset = (height - padding) / (height / 50); + this.media.style.transform = `translateY(-${offset}%)`; + } + + return { padding, ratio }; +} + +export default { setAspectRatio }; diff --git a/src/js/utils/time.js b/src/js/utils/time.js new file mode 100644 index 00000000..2deccf65 --- /dev/null +++ b/src/js/utils/time.js @@ -0,0 +1,36 @@ +// ========================================================================== +// Time utils +// ========================================================================== + +import is from './is'; + +// Time helpers +export const getHours = value => Math.trunc((value / 60 / 60) % 60, 10); +export const getMinutes = value => Math.trunc((value / 60) % 60, 10); +export const getSeconds = value => Math.trunc(value % 60, 10); + +// Format time to UI friendly string +export function formatTime(time = 0, displayHours = false, inverted = false) { + // Bail if the value isn't a number + if (!is.number(time)) { + return formatTime(null, displayHours, inverted); + } + + // Format time component to add leading zero + const format = value => `0${value}`.slice(-2); + + // Breakdown to hours, mins, secs + let hours = getHours(time); + const mins = getMinutes(time); + const secs = getSeconds(time); + + // Do we need to display hours? + if (displayHours || hours > 0) { + hours = `${hours}:`; + } else { + hours = ''; + } + + // Render + return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`; +} diff --git a/src/js/utils/urls.js b/src/js/utils/urls.js new file mode 100644 index 00000000..3ebe622e --- /dev/null +++ b/src/js/utils/urls.js @@ -0,0 +1,39 @@ +// ========================================================================== +// URL utils +// ========================================================================== + +import is from './is'; + +/** + * Parse a string to a URL object + * @param {string} input - the URL to be parsed + * @param {boolean} safe - failsafe parsing + */ +export function parseUrl(input, safe = true) { + let url = input; + + if (safe) { + const parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } + + try { + return new URL(url); + } catch (e) { + return null; + } +} + +// Convert object to URLSearchParams +export function buildUrlParams(input) { + const params = new URLSearchParams(); + + if (is.object(input)) { + Object.entries(input).forEach(([key, value]) => { + params.set(key, value); + }); + } + + return params; +} diff --git a/src/sass/components/captions.scss b/src/sass/components/captions.scss index 9dfc2be8..1cfca92e 100644 --- a/src/sass/components/captions.scss +++ b/src/sass/components/captions.scss @@ -17,11 +17,10 @@ padding: $plyr-control-spacing; position: absolute; text-align: center; - transform: translateY(-($plyr-control-spacing * 4)); transition: transform 0.4s ease-in-out; width: 100%; - span { + .plyr__caption { background: $plyr-captions-bg; border-radius: 2px; box-decoration-break: clone; @@ -53,6 +52,8 @@ display: block; } -.plyr--hide-controls .plyr__captions { - transform: translateY(-($plyr-control-spacing * 1.5)); +// If the lower controls are shown and not empty +.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty) ~ .plyr__captions { + transform: translateY(-($plyr-control-spacing * 4)); } + diff --git a/src/sass/components/control.scss b/src/sass/components/control.scss index 52716805..1c9aab2b 100644 --- a/src/sass/components/control.scss +++ b/src/sass/components/control.scss @@ -33,15 +33,25 @@ } } +// Remove any link styling +a.plyr__control { + text-decoration: none; + + &::after, + &::before { + display: none; + } +} + // Change icons on state change -.plyr__control[aria-pressed='false'] .icon--pressed, -.plyr__control[aria-pressed='true'] .icon--not-pressed, -.plyr__control[aria-pressed='false'] .label--pressed, -.plyr__control[aria-pressed='true'] .label--not-pressed { +.plyr__control:not(.plyr__control--pressed) .icon--pressed, +.plyr__control.plyr__control--pressed .icon--not-pressed, +.plyr__control:not(.plyr__control--pressed) .label--pressed, +.plyr__control.plyr__control--pressed .label--not-pressed { display: none; } -// Audio styles +// Audio control .plyr--audio .plyr__control { &.plyr__tab-focus, &:hover, @@ -51,6 +61,21 @@ } } +// Video control +.plyr--video .plyr__control { + svg { + filter: drop-shadow(0 1px 1px rgba(#000, 0.15)); + } + + // Hover and tab focus + &.plyr__tab-focus, + &:hover, + &[aria-expanded='true'] { + background: $plyr-video-control-bg-hover; + color: $plyr-video-control-color-hover; + } +} + // Large play button (video only) .plyr__control--overlaid { background: rgba($plyr-video-control-bg-hover, 0.8); @@ -66,11 +91,10 @@ transform: translate(-50%, -50%); z-index: 2; + // Offset icon to make the play button look right svg { - height: $plyr-control-icon-size-large; - left: 2px; // Offset to make the play button look right + left: 2px; position: relative; - width: $plyr-control-icon-size-large; } &:hover, diff --git a/src/sass/components/controls.scss b/src/sass/components/controls.scss index 91db1b20..41426e8b 100644 --- a/src/sass/components/controls.scss +++ b/src/sass/components/controls.scss @@ -11,79 +11,78 @@ .plyr__controls { align-items: center; display: flex; + justify-content: flex-end; text-align: center; // Spacing > .plyr__control, .plyr__progress, .plyr__time, - .plyr__menu { + .plyr__menu, + .plyr__volume { margin-left: ($plyr-control-spacing / 2); + } - &:first-child, - &:first-child + [data-plyr='pause'] { - margin-left: 0; - } + .plyr__menu + .plyr__control, + > .plyr__control + .plyr__menu, + > .plyr__control + .plyr__control, + .plyr__progress + .plyr__control { + margin-left: floor($plyr-control-spacing / 4); } - .plyr__volume { - margin-left: ($plyr-control-spacing / 2); + > .plyr__control:first-child, + > .plyr__control:first-child + [data-plyr='pause'] { + margin-left: 0; + margin-right: auto; + } + + // Hide empty controls + &:empty { + display: none; } @media (min-width: $plyr-bp-sm) { > .plyr__control, + .plyr__menu, .plyr__progress, .plyr__time, - .plyr__menu { + .plyr__volume { margin-left: $plyr-control-spacing; } - - > .plyr__control + .plyr__control, - .plyr__menu + .plyr__control, - > .plyr__control + .plyr__menu { - margin-left: ($plyr-control-spacing / 2); - } } } +// Audio controls +.plyr--audio .plyr__controls { + background: $plyr-audio-controls-bg; + border-radius: inherit; + color: $plyr-audio-control-color; + padding: $plyr-control-spacing; +} + // Video controls .plyr--video .plyr__controls { - background: linear-gradient(rgba($plyr-video-controls-bg, 0), rgba($plyr-video-controls-bg, 0.7)); + background: linear-gradient( + rgba($plyr-video-controls-bg, 0), + rgba($plyr-video-controls-bg, 0.7) + ); border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; bottom: 0; color: $plyr-video-control-color; left: 0; - padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing $plyr-control-spacing; + padding: ($plyr-control-spacing * 2) ($plyr-control-spacing / 2) ($plyr-control-spacing / 2); position: absolute; right: 0; transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out; - z-index: 2; - - .plyr__control { - svg { - filter: drop-shadow(0 1px 1px rgba(#000, 0.15)); - } + z-index: 3; - // Hover and tab focus - &.plyr__tab-focus, - &:hover, - &[aria-expanded='true'] { - background: $plyr-video-control-bg-hover; - color: $plyr-video-control-color-hover; - } + @media (min-width: $plyr-bp-sm) { + padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing $plyr-control-spacing; } } -// Audio controls -.plyr--audio .plyr__controls { - background: $plyr-audio-controls-bg; - border-radius: inherit; - color: $plyr-audio-control-color; - padding: $plyr-control-spacing; -} - -// Hide controls +// Hide video controls .plyr--video.plyr--hide-controls .plyr__controls { opacity: 0; pointer-events: none; diff --git a/src/sass/components/embed.scss b/src/sass/components/embed.scss index be807739..25431caf 100644 --- a/src/sass/components/embed.scss +++ b/src/sass/components/embed.scss @@ -27,11 +27,6 @@ $embed-padding: ((100 / 16) * 9); $height: 240; $offset: to-percentage(($height - $embed-padding) / ($height / 50)); - // To allow mouse events to be captured if full support - iframe { - pointer-events: none; - } - // Only used for Vimeo > .plyr__video-embed__container { padding-bottom: to-percentage($height); diff --git a/src/sass/components/menus.scss b/src/sass/components/menus.scss index 3ad4039a..b8c85284 100644 --- a/src/sass/components/menus.scss +++ b/src/sass/components/menus.scss @@ -39,7 +39,8 @@ > div { overflow: hidden; - transition: height 0.35s cubic-bezier(0.4, 0, 0.2, 1), width 0.35s cubic-bezier(0.4, 0, 0.2, 1); + transition: height 0.35s cubic-bezier(0.4, 0, 0.2, 1), + width 0.35s cubic-bezier(0.4, 0, 0.2, 1); } // Arrow @@ -54,18 +55,16 @@ width: 0; } - ul { - list-style: none; - margin: 0; - overflow: hidden; + [role='menu'] { padding: $plyr-control-padding; + } - li { - margin-top: 2px; + [role='menuitem'], + [role='menuitemradio'] { + margin-top: 2px; - &:first-child { - margin-top: 0; - } + &:first-child { + margin-top: 0; } } @@ -75,10 +74,17 @@ color: $plyr-menu-color; display: flex; font-size: $plyr-font-size-menu; - padding: ceil($plyr-control-padding / 2) ($plyr-control-padding * 2); + padding: ceil($plyr-control-padding / 2) + ceil($plyr-control-padding * 1.5); user-select: none; width: 100%; + > span { + align-items: inherit; + display: flex; + width: 100%; + } + &::after { border: 4px solid transparent; content: ''; @@ -135,50 +141,49 @@ } } - label.plyr__control { + .plyr__control[role='menuitemradio'] { padding-left: $plyr-control-padding; - input[type='radio'] + span { - background: rgba(#000, 0.1); + &::before, + &::after { border-radius: 100%; + } + + &::before { + background: rgba(#000, 0.1); + content: ''; display: block; flex-shrink: 0; height: 16px; margin-right: $plyr-control-spacing; - position: relative; transition: all 0.3s ease; width: 16px; - - &::after { - background: #fff; - border-radius: 100%; - content: ''; - height: 6px; - left: 5px; - opacity: 0; - position: absolute; - top: 5px; - transform: scale(0); - transition: transform 0.3s ease, opacity 0.3s ease; - width: 6px; - } } - input[type='radio']:checked + span { - background: $plyr-color-main; + &::after { + background: #fff; + border: 0; + height: 6px; + left: 12px; + opacity: 0; + top: 50%; + transform: translateY(-50%) scale(0); + transition: transform 0.3s ease, opacity 0.3s ease; + width: 6px; + } + &[aria-checked='true'] { + &::before { + background: $plyr-color-main; + } &::after { opacity: 1; - transform: scale(1); + transform: translateY(-50%) scale(1); } } - input[type='radio']:focus + span { - @include plyr-tab-focus(); - } - - &.plyr__tab-focus input[type='radio'] + span, - &:hover input[type='radio'] + span { + &.plyr__tab-focus::before, + &:hover::before { background: rgba(#000, 0.1); } } @@ -188,7 +193,7 @@ align-items: center; display: flex; margin-left: auto; - margin-right: -$plyr-control-padding; + margin-right: -($plyr-control-padding - 2); overflow: hidden; padding-left: ceil($plyr-control-padding * 3.5); pointer-events: none; diff --git a/src/sass/components/poster.scss b/src/sass/components/poster.scss index b2518a78..9b239d4f 100644 --- a/src/sass/components/poster.scss +++ b/src/sass/components/poster.scss @@ -6,17 +6,17 @@ background-color: #000; background-position: 50% 50%; background-repeat: no-repeat; - background-size: 100% 100%; + background-size: contain; height: 100%; left: 0; opacity: 0; position: absolute; top: 0; - transition: opacity 0.3s ease; + transition: opacity 0.2s ease; width: 100%; z-index: 1; } -.plyr--stopped .plyr__poster { +.plyr--stopped.plyr__poster-enabled .plyr__poster { opacity: 1; } diff --git a/src/sass/components/progress.scss b/src/sass/components/progress.scss index 7490ee17..f28a19ca 100644 --- a/src/sass/components/progress.scss +++ b/src/sass/components/progress.scss @@ -3,10 +3,19 @@ // -------------------------------------------------------------- .plyr__progress { - display: flex; flex: 1; + left: $plyr-range-thumb-height / 2; + margin-right: $plyr-range-thumb-height; position: relative; + input[type='range'], + &__buffer { + margin-left: -($plyr-range-thumb-height / 2); + margin-right: -($plyr-range-thumb-height / 2); + // Offset the range thumb in order to be able to calculate the relative progress (#954) + width: calc(100% + #{$plyr-range-thumb-height}); + } + input[type='range'] { position: relative; z-index: 2; @@ -19,28 +28,27 @@ } } -.plyr__progress--buffer { +.plyr__progress__buffer { -webkit-appearance: none; /* stylelint-disable-line */ background: transparent; border: 0; border-radius: 100px; height: $plyr-range-track-height; left: 0; - margin: -($plyr-range-track-height / 2) 0 0; + margin-top: -($plyr-range-track-height / 2); padding: 0; position: absolute; top: 50%; - width: 100%; &::-webkit-progress-bar { background: transparent; - transition: width 0.2s ease; } &::-webkit-progress-value { background: currentColor; border-radius: 100px; min-width: $plyr-range-track-height; + transition: width 0.2s ease; } // Mozilla @@ -58,17 +66,17 @@ } } -.plyr--video .plyr__progress--buffer { +.plyr--video .plyr__progress__buffer { box-shadow: 0 1px 1px rgba(#000, 0.15); color: $plyr-video-progress-buffered-bg; } -.plyr--audio .plyr__progress--buffer { +.plyr--audio .plyr__progress__buffer { color: $plyr-audio-progress-buffered-bg; } // Loading state -.plyr--loading .plyr__progress--buffer { +.plyr--loading .plyr__progress__buffer { animation: plyr-progress 1s linear infinite; background-image: linear-gradient( -45deg, @@ -85,10 +93,10 @@ color: transparent; } -.plyr--video.plyr--loading .plyr__progress--buffer { +.plyr--video.plyr--loading .plyr__progress__buffer { background-color: $plyr-video-progress-buffered-bg; } -.plyr--audio.plyr--loading .plyr__progress--buffer { +.plyr--audio.plyr--loading .plyr__progress__buffer { background-color: $plyr-audio-progress-buffered-bg; } diff --git a/src/sass/components/sliders.scss b/src/sass/components/sliders.scss index b9264b05..ee64271b 100644 --- a/src/sass/components/sliders.scss +++ b/src/sass/components/sliders.scss @@ -19,7 +19,11 @@ &::-webkit-slider-runnable-track { @include plyr-range-track(); - background-image: linear-gradient(to right, currentColor var(--value, 0%), transparent var(--value, 0%)); + background-image: linear-gradient( + to right, + currentColor var(--value, 0%), + transparent var(--value, 0%) + ); } &::-webkit-slider-thumb { @@ -140,15 +144,21 @@ // Pressed styles &:active { &::-webkit-slider-thumb { - @include plyr-range-thumb-active($plyr-audio-range-thumb-shadow-color); + @include plyr-range-thumb-active( + $plyr-audio-range-thumb-shadow-color + ); } &::-moz-range-thumb { - @include plyr-range-thumb-active($plyr-audio-range-thumb-shadow-color); + @include plyr-range-thumb-active( + $plyr-audio-range-thumb-shadow-color + ); } &::-ms-thumb { - @include plyr-range-thumb-active($plyr-audio-range-thumb-shadow-color); + @include plyr-range-thumb-active( + $plyr-audio-range-thumb-shadow-color + ); } } } diff --git a/src/sass/components/tooltips.scss b/src/sass/components/tooltips.scss index 537e2444..80603bb5 100644 --- a/src/sass/components/tooltips.scss +++ b/src/sass/components/tooltips.scss @@ -10,6 +10,7 @@ color: $plyr-tooltip-color; font-size: $plyr-font-size-small; font-weight: $plyr-font-weight-regular; + left: 50%; line-height: 1.3; margin-bottom: ($plyr-tooltip-padding * 2); opacity: 0; @@ -64,6 +65,7 @@ // Last tooltip .plyr__controls > .plyr__control:last-child .plyr__tooltip { + left: auto; right: 0; transform: translate(0, 10px) scale(0.8); transform-origin: 100% 100%; diff --git a/src/sass/components/video.scss b/src/sass/components/video.scss index 3caf866d..c3dc4152 100644 --- a/src/sass/components/video.scss +++ b/src/sass/components/video.scss @@ -3,6 +3,7 @@ // -------------------------------------------------------------- .plyr--video { + background: #000; overflow: hidden; // Menu open diff --git a/src/sass/components/volume.scss b/src/sass/components/volume.scss index d22b7cba..82a6dd36 100644 --- a/src/sass/components/volume.scss +++ b/src/sass/components/volume.scss @@ -3,20 +3,23 @@ // -------------------------------------------------------------- .plyr__volume { + align-items: center; + display: flex; flex: 1; position: relative; input[type='range'] { + margin-left: ($plyr-control-spacing / 2); position: relative; z-index: 2; } @media (min-width: $plyr-bp-sm) { - max-width: 50px; + max-width: 90px; } @media (min-width: $plyr-bp-md) { - max-width: 80px; + max-width: 110px; } } diff --git a/src/sass/lib/mixins.scss b/src/sass/lib/mixins.scss index 8b333f65..554c66a5 100644 --- a/src/sass/lib/mixins.scss +++ b/src/sass/lib/mixins.scss @@ -5,7 +5,7 @@ // Nicer focus styles // --------------------------------------- @mixin plyr-tab-focus($color: $plyr-tab-focus-default-color) { - box-shadow: 0 0 0 3px rgba($color, 0.35); + box-shadow: 0 0 0 5px rgba($color, 0.5); outline: 0; } @@ -28,7 +28,7 @@ border: 0; border-radius: ($plyr-range-track-height / 2); height: $plyr-range-track-height; - transition: all 0.3s ease; + transition: box-shadow 0.3s ease; user-select: none; } @@ -37,7 +37,6 @@ border: 0; border-radius: 100%; box-shadow: $plyr-range-thumb-shadow; - box-sizing: border-box; height: $plyr-range-thumb-height; position: relative; transition: all 0.2s ease; @@ -66,11 +65,6 @@ width: 100%; } - .plyr__video-embed { - // Revert overflow change - overflow: visible; - } - // Vimeo requires some different styling &.plyr--vimeo .plyr__video-wrapper { height: 0; diff --git a/src/sass/plugins/previewThumbnails.scss b/src/sass/plugins/previewThumbnails.scss new file mode 100644 index 00000000..02a2f619 --- /dev/null +++ b/src/sass/plugins/previewThumbnails.scss @@ -0,0 +1,118 @@ +// -------------------------------------------------------------- +// Preview Thumbnails +// -------------------------------------------------------------- + +$plyr-preview-padding: $plyr-tooltip-padding !default; +$plyr-preview-bg: $plyr-tooltip-bg !default; +$plyr-preview-radius: $plyr-tooltip-radius !default; +$plyr-preview-shadow: $plyr-tooltip-shadow !default; +$plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default; +$plyr-preview-image-bg: $plyr-color-heather !default; +$plyr-preview-time-font-size: $plyr-font-size-time !default; +$plyr-preview-time-padding: 3px 6px !default; +$plyr-preview-time-bg: rgba(0, 0, 0, 0.55); +$plyr-preview-time-color: #fff; +$plyr-preview-time-bottom-offset: 6px; + +.plyr__preview-thumb { + background-color: $plyr-preview-bg; + border-radius: 3px; + bottom: 100%; + box-shadow: $plyr-preview-shadow; + margin-bottom: $plyr-preview-padding * 2; + opacity: 0; + padding: $plyr-preview-radius; + pointer-events: none; + position: absolute; + transform: translate(0, 10px) scale(0.8); + transform-origin: 50% 100%; + transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease; + z-index: 2; + + &--is-shown { + opacity: 1; + transform: translate(0, 0) scale(1); + } + + // The background triangle + &::before { + border-left: $plyr-preview-arrow-size solid transparent; + border-right: $plyr-preview-arrow-size solid transparent; + border-top: $plyr-preview-arrow-size solid $plyr-preview-bg; + bottom: -$plyr-preview-arrow-size; + content: ''; + height: 0; + left: 50%; + position: absolute; + transform: translateX(-50%); + width: 0; + z-index: 2; + } + + &__image-container { + background: $plyr-preview-image-bg; + border-radius: ($plyr-preview-radius - 1px); + overflow: hidden; + position: relative; + z-index: 0; + + img { + height: 100%; // Non sprite images are 100%. Sprites will have their size applied by JavaScript + left: 0; + max-height: none; + max-width: none; + position: absolute; + top: 0; + width: 100%; + } + } + + // Seek time text + &__time-container { + bottom: $plyr-preview-time-bottom-offset; + left: 0; + position: absolute; + right: 0; + white-space: nowrap; + z-index: 3; + + span { + background-color: $plyr-preview-time-bg; + border-radius: ($plyr-preview-radius - 1px); + color: $plyr-preview-time-color; + font-size: $plyr-preview-time-font-size; + padding: $plyr-preview-time-padding; + } + } +} + +.plyr__preview-scrubbing { + bottom: 0; + filter: blur(1px); + height: 100%; + left: 0; + margin: auto; // Required when video is different dimensions to container (e.g. fullscreen) + opacity: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + transition: opacity 0.3s ease; + width: 100%; + z-index: 1; + + &--is-shown { + opacity: 1; + } + + img { + height: 100%; + left: 0; + max-height: none; + max-width: none; + object-fit: contain; + position: absolute; + top: 0; + width: 100%; + } +} diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss index 65134331..468c534c 100644 --- a/src/sass/plyr.scss +++ b/src/sass/plyr.scss @@ -31,18 +31,18 @@ @import 'components/controls'; @import 'components/embed'; @import 'components/menus'; -@import 'components/progress'; -@import 'components/poster'; @import 'components/sliders'; +@import 'components/poster'; @import 'components/times'; @import 'components/tooltips'; @import 'components/video'; +@import 'components/progress'; @import 'components/volume'; -@import 'states/error'; @import 'states/fullscreen'; @import 'plugins/ads'; +@import 'plugins/previewThumbnails'; @import 'utils/animation'; @import 'utils/hidden'; diff --git a/src/sass/settings/controls.scss b/src/sass/settings/controls.scss index 64f05cec..d6d2c153 100644 --- a/src/sass/settings/controls.scss +++ b/src/sass/settings/controls.scss @@ -3,7 +3,6 @@ // ========================================================================== $plyr-control-icon-size: 18px !default; -$plyr-control-icon-size-large: 20px !default; $plyr-control-spacing: 10px !default; $plyr-control-padding: ($plyr-control-spacing * 0.7) !default; $plyr-control-radius: 3px !default; diff --git a/src/sass/settings/sliders.scss b/src/sass/settings/sliders.scss index 3c75b797..6ac053b0 100644 --- a/src/sass/settings/sliders.scss +++ b/src/sass/settings/sliders.scss @@ -6,13 +6,13 @@ $plyr-range-thumb-active-shadow-width: 3px !default; // Thumb -$plyr-range-thumb-height: 14px !default; +$plyr-range-thumb-height: 13px !default; $plyr-range-thumb-bg: #fff !default; $plyr-range-thumb-border: 2px solid transparent !default; $plyr-range-thumb-shadow: 0 1px 1px rgba(#000, 0.15), 0 0 0 1px rgba($plyr-color-gunmetal, 0.2) !default; // Track -$plyr-range-track-height: 6px !default; +$plyr-range-track-height: 5px !default; $plyr-range-max-height: ($plyr-range-thumb-active-shadow-width * 2) + $plyr-range-thumb-height !default; // Fill diff --git a/src/sass/settings/type.scss b/src/sass/settings/type.scss index 351ebd18..79cb57de 100644 --- a/src/sass/settings/type.scss +++ b/src/sass/settings/type.scss @@ -17,4 +17,4 @@ $plyr-font-weight-bold: 600 !default; $plyr-line-height: 1.7 !default; -$plyr-font-smoothing: true !default; +$plyr-font-smoothing: false !default; diff --git a/src/sass/states/error.scss b/src/sass/states/error.scss deleted file mode 100644 index 64d05c7b..00000000 --- a/src/sass/states/error.scss +++ /dev/null @@ -1,25 +0,0 @@ -// -------------------------------------------------------------- -// Error state -// -------------------------------------------------------------- - -.plyr--has-error { - pointer-events: none; - - &::after { - align-items: center; - background: rgba(#000, 90%); - color: #fff; - content: attr(data-plyr-error); - display: flex; - font-size: $plyr-font-size-base; - height: 100%; - justify-content: center; - left: 0; - position: absolute; - text-align: center; - text-shadow: 0 1px 1px rgba(#000, 10%); - top: 0; - width: 100%; - z-index: 10; - } -} diff --git a/src/sass/utils/hidden.scss b/src/sass/utils/hidden.scss index e4fa0aec..a42c3be8 100644 --- a/src/sass/utils/hidden.scss +++ b/src/sass/utils/hidden.scss @@ -22,3 +22,7 @@ width: 1px; } } + +.plyr [hidden] { + display: none !important; +} diff --git a/src/sprite/plyr-airplay.svg b/src/sprite/plyr-airplay.svg index 45c55414..3ef6ec61 100644 --- a/src/sprite/plyr-airplay.svg +++ b/src/sprite/plyr-airplay.svg @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> <g> <path d="M16,1 L2,1 C1.447,1 1,1.447 1,2 L1,12 C1,12.553 1.447,13 2,13 L5,13 L5,11 L3,11 L3,3 L15,3 L15,11 L13,11 L13,13 L16,13 C16.553,13 17,12.553 17,12 L17,2 C17,1.447 16.553,1 16,1 L16,1 Z"></path> <polygon points="4 17 14 17 9 11"></polygon> diff --git a/src/sprite/plyr-captions-off.svg b/src/sprite/plyr-captions-off.svg index 48503285..e0fd0e16 100644 --- a/src/sprite/plyr-captions-off.svg +++ b/src/sprite/plyr-captions-off.svg @@ -1,6 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch --> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> <g fill-rule="evenodd" fill-opacity="0.5"> <path d="M1,1 C0.4,1 0,1.4 0,2 L0,13 C0,13.6 0.4,14 1,14 L5.6,14 L8.3,16.7 C8.5,16.9 8.7,17 9,17 C9.3,17 9.5,16.9 9.7,16.7 L12.4,14 L17,14 C17.6,14 18,13.6 18,13 L18,2 C18,1.4 17.6,1 17,1 L1,1 Z M5.52,11.15 C7.51,11.15 8.53,9.83 8.8,8.74 L7.51,8.35 C7.32,9.01 6.73,9.8 5.52,9.8 C4.38,9.8 3.32,8.97 3.32,7.46 C3.32,5.85 4.44,5.09 5.5,5.09 C6.73,5.09 7.28,5.84 7.45,6.52 L8.75,6.11 C8.47,4.96 7.46,3.76 5.5,3.76 C3.6,3.76 1.89,5.2 1.89,7.46 C1.89,9.72 3.54,11.15 5.52,11.15 Z M13.09,11.15 C15.08,11.15 16.1,9.83 16.37,8.74 L15.08,8.35 C14.89,9.01 14.3,9.8 13.09,9.8 C11.95,9.8 10.89,8.97 10.89,7.46 C10.89,5.85 12.01,5.09 13.07,5.09 C14.3,5.09 14.85,5.84 15.02,6.52 L16.32,6.11 C16.04,4.96 15.03,3.76 13.07,3.76 C11.17,3.76 9.46,5.2 9.46,7.46 C9.46,9.72 11.11,11.15 13.09,11.15 Z"></path> </g> diff --git a/src/sprite/plyr-captions-on.svg b/src/sprite/plyr-captions-on.svg index b524abcb..26947448 100644 --- a/src/sprite/plyr-captions-on.svg +++ b/src/sprite/plyr-captions-on.svg @@ -1,6 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch --> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> <g fill-rule="evenodd"> <path d="M1,1 C0.4,1 0,1.4 0,2 L0,13 C0,13.6 0.4,14 1,14 L5.6,14 L8.3,16.7 C8.5,16.9 8.7,17 9,17 C9.3,17 9.5,16.9 9.7,16.7 L12.4,14 L17,14 C17.6,14 18,13.6 18,13 L18,2 C18,1.4 17.6,1 17,1 L1,1 Z M5.52,11.15 C7.51,11.15 8.53,9.83 8.8,8.74 L7.51,8.35 C7.32,9.01 6.73,9.8 5.52,9.8 C4.38,9.8 3.32,8.97 3.32,7.46 C3.32,5.85 4.44,5.09 5.5,5.09 C6.73,5.09 7.28,5.84 7.45,6.52 L8.75,6.11 C8.47,4.96 7.46,3.76 5.5,3.76 C3.6,3.76 1.89,5.2 1.89,7.46 C1.89,9.72 3.54,11.15 5.52,11.15 Z M13.09,11.15 C15.08,11.15 16.1,9.83 16.37,8.74 L15.08,8.35 C14.89,9.01 14.3,9.8 13.09,9.8 C11.95,9.8 10.89,8.97 10.89,7.46 C10.89,5.85 12.01,5.09 13.07,5.09 C14.3,5.09 14.85,5.84 15.02,6.52 L16.32,6.11 C16.04,4.96 15.03,3.76 13.07,3.76 C11.17,3.76 9.46,5.2 9.46,7.46 C9.46,9.72 11.11,11.15 13.09,11.15 Z"></path> </g> diff --git a/src/sprite/plyr-download.svg b/src/sprite/plyr-download.svg new file mode 100644 index 00000000..1d971a40 --- /dev/null +++ b/src/sprite/plyr-download.svg @@ -0,0 +1,6 @@ +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(2 1)"> + <path d="M7,12 C7.3,12 7.5,11.9 7.7,11.7 L13.4,6 L12,4.6 L8,8.6 L8,0 L6,0 L6,8.6 L2,4.6 L0.6,6 L6.3,11.7 C6.5,11.9 6.7,12 7,12 Z" /> + <rect width="14" height="2" y="14" /> + </g> +</svg>
\ No newline at end of file diff --git a/src/sprite/plyr-enter-fullscreen.svg b/src/sprite/plyr-enter-fullscreen.svg index 4c4aba9b..9607b143 100644 --- a/src/sprite/plyr-enter-fullscreen.svg +++ b/src/sprite/plyr-enter-fullscreen.svg @@ -1,7 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="10 3 13.6 3 9.6 7 11 8.4 15 4.4 15 8 17 8 17 1 10 1"></polygon> - <polygon points="7 9.6 3 13.6 3 10 1 10 1 17 8 17 8 15 4.4 15 8.4 11"></polygon> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="10 3 13.6 3 9.6 7 11 8.4 15 4.4 15 8 17 8 17 1 10 1"></polygon> + <polygon points="7 9.6 3 13.6 3 10 1 10 1 17 8 17 8 15 4.4 15 8.4 11"></polygon> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-exit-fullscreen.svg b/src/sprite/plyr-exit-fullscreen.svg index bd08d775..bb314e32 100644 --- a/src/sprite/plyr-exit-fullscreen.svg +++ b/src/sprite/plyr-exit-fullscreen.svg @@ -1,7 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="1 12 4.6 12 0.6 16 2 17.4 6 13.4 6 17 8 17 8 10 1 10"></polygon> - <polygon points="16 0.6 12 4.6 12 1 10 1 10 8 17 8 17 6 13.4 6 17.4 2"></polygon> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="1 12 4.6 12 0.6 16 2 17.4 6 13.4 6 17 8 17 8 10 1 10"></polygon> + <polygon points="16 0.6 12 4.6 12 1 10 1 10 8 17 8 17 6 13.4 6 17.4 2"></polygon> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-fast-forward.svg b/src/sprite/plyr-fast-forward.svg index a441bd27..5398b94f 100644 --- a/src/sprite/plyr-fast-forward.svg +++ b/src/sprite/plyr-fast-forward.svg @@ -1,6 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="7.875 7.17142857 0 1 0 17 7.875 10.8285714 7.875 17 18 9 7.875 1"></polygon> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="7.875 7.17142857 0 1 0 17 7.875 10.8285714 7.875 17 18 9 7.875 1"></polygon> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-logo-vimeo.svg b/src/sprite/plyr-logo-vimeo.svg new file mode 100644 index 00000000..de2f9ee6 --- /dev/null +++ b/src/sprite/plyr-logo-vimeo.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"> + <path d="M16,3.3 C15.9,4.9 14.8,7 12.7,9.7 C10.5,12.5 8.7,13.9 7.2,13.9 C6.3,13.9 5.5,13 4.8,11.3 C4,8.9 3.4,4 2,4 C1.9,4 1.5,4.3 0.8,4.8 L0,3.8 C0.8,3.1 3.5,0.4 4.7,0.3 C5.9,0.2 6.7,1 7,2.8 C7.3,4.8 7.8,8.9 8.8,8.9 C9.7,8.9 11.3,5.5 11.4,4.9 C11.5,4 11.1,3 9.1,3.8 C9.9,1.2 11.4,-8.8817842e-16 13.6,-8.8817842e-16 C15.3,0.1 16.1,1.2 16,3.3 Z" + transform="translate(1 2)" /> +</svg>
\ No newline at end of file diff --git a/src/sprite/plyr-logo-youtube.svg b/src/sprite/plyr-logo-youtube.svg new file mode 100644 index 00000000..3bec1531 --- /dev/null +++ b/src/sprite/plyr-logo-youtube.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"> + <path d="M15.8,2.8 C15.6,1.5 15,0.6 13.6,0.4 C11.4,0 8,0 8,0 C8,0 4.6,0 2.4,0.4 C1,0.6 0.3,1.5 0.2,2.8 C0,4.1 0,6 0,6 C0,6 0,7.9 0.2,9.2 C0.4,10.5 1,11.4 2.4,11.6 C4.6,12 8,12 8,12 C8,12 11.4,12 13.6,11.6 C15,11.3 15.6,10.5 15.8,9.2 C16,7.9 16,6 16,6 C16,6 16,4.1 15.8,2.8 Z M6,9 L6,3 L11,6 L6,9 Z" + transform="translate(1 3)" /> +</svg>
\ No newline at end of file diff --git a/src/sprite/plyr-muted.svg b/src/sprite/plyr-muted.svg index 41c66821..095d9a7a 100644 --- a/src/sprite/plyr-muted.svg +++ b/src/sprite/plyr-muted.svg @@ -1,7 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="12.4 12.5 14.5 10.4 16.6 12.5 18 11.1 15.9 9 18 6.9 16.6 5.5 14.5 7.6 12.4 5.5 11 6.9 13.1 9 11 11.1"></polygon> - <path d="M3.78571429,6.00820648 L0.714285714,6.00820648 C0.285714286,6.00820648 0,6.30901277 0,6.76022222 L0,11.2723167 C0,11.7235261 0.285714286,12.0243324 0.714285714,12.0243324 L3.78571429,12.0243324 L7.85714286,15.8819922 C8.35714286,16.1827985 9,15.8819922 9,15.2803796 L9,2.75215925 C9,2.15054666 8.35714286,1.77453879 7.85714286,2.15054666 L3.78571429,6.00820648 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="12.4 12.5 14.5 10.4 16.6 12.5 18 11.1 15.9 9 18 6.9 16.6 5.5 14.5 7.6 12.4 5.5 11 6.9 13.1 9 11 11.1"></polygon> + <path d="M3.78571429,6.00820648 L0.714285714,6.00820648 C0.285714286,6.00820648 0,6.30901277 0,6.76022222 L0,11.2723167 C0,11.7235261 0.285714286,12.0243324 0.714285714,12.0243324 L3.78571429,12.0243324 L7.85714286,15.8819922 C8.35714286,16.1827985 9,15.8819922 9,15.2803796 L9,2.75215925 C9,2.15054666 8.35714286,1.77453879 7.85714286,2.15054666 L3.78571429,6.00820648 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-pause.svg b/src/sprite/plyr-pause.svg index a4dae883..5910f595 100644 --- a/src/sprite/plyr-pause.svg +++ b/src/sprite/plyr-pause.svg @@ -1,7 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <path d="M6,1 L3,1 C2.4,1 2,1.4 2,2 L2,16 C2,16.6 2.4,17 3,17 L6,17 C6.6,17 7,16.6 7,16 L7,2 C7,1.4 6.6,1 6,1 L6,1 Z"></path> - <path d="M12,1 C11.4,1 11,1.4 11,2 L11,16 C11,16.6 11.4,17 12,17 L15,17 C15.6,17 16,16.6 16,16 L16,2 C16,1.4 15.6,1 15,1 L12,1 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <path d="M6,1 L3,1 C2.4,1 2,1.4 2,2 L2,16 C2,16.6 2.4,17 3,17 L6,17 C6.6,17 7,16.6 7,16 L7,2 C7,1.4 6.6,1 6,1 L6,1 Z"></path> + <path d="M12,1 C11.4,1 11,1.4 11,2 L11,16 C11,16.6 11.4,17 12,17 L15,17 C15.6,17 16,16.6 16,16 L16,2 C16,1.4 15.6,1 15,1 L12,1 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-pip.svg b/src/sprite/plyr-pip.svg index d841fce5..c465f482 100644 --- a/src/sprite/plyr-pip.svg +++ b/src/sprite/plyr-pip.svg @@ -1,7 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="13.293 3.293 7.022 9.564 8.436 10.978 14.707 4.707 17 7 17 1 11 1"></polygon> - <path d="M13,15 L3,15 L3,5 L8,5 L8,3 L2,3 C1.448,3 1,3.448 1,4 L1,16 C1,16.552 1.448,17 2,17 L14,17 C14.552,17 15,16.552 15,16 L15,10 L13,10 L13,15 L13,15 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="13.293 3.293 7.022 9.564 8.436 10.978 14.707 4.707 17 7 17 1 11 1"></polygon> + <path d="M13,15 L3,15 L3,5 L8,5 L8,3 L2,3 C1.448,3 1,3.448 1,4 L1,16 C1,16.552 1.448,17 2,17 L14,17 C14.552,17 15,16.552 15,16 L15,10 L13,10 L13,15 L13,15 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-play.svg b/src/sprite/plyr-play.svg index cc551902..96a45244 100644 --- a/src/sprite/plyr-play.svg +++ b/src/sprite/plyr-play.svg @@ -1,6 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <path d="M15.5615866,8.10002147 L3.87056367,0.225209313 C3.05219207,-0.33727727 2,0.225209313 2,1.12518784 L2,16.8748122 C2,17.7747907 3.05219207,18.3372773 3.87056367,17.7747907 L15.5615866,9.89997853 C16.1461378,9.44998927 16.1461378,8.55001073 15.5615866,8.10002147 L15.5615866,8.10002147 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <path d="M15.5615866,8.10002147 L3.87056367,0.225209313 C3.05219207,-0.33727727 2,0.225209313 2,1.12518784 L2,16.8748122 C2,17.7747907 3.05219207,18.3372773 3.87056367,17.7747907 L15.5615866,9.89997853 C16.1461378,9.44998927 16.1461378,8.55001073 15.5615866,8.10002147 L15.5615866,8.10002147 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-restart.svg b/src/sprite/plyr-restart.svg index efb99cce..5730141e 100755 --- a/src/sprite/plyr-restart.svg +++ b/src/sprite/plyr-restart.svg @@ -1,6 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <path d="M9.7,1.2 L10.4,7.6 L12.5,5.5 C14.4,7.4 14.4,10.6 12.5,12.5 C11.6,13.5 10.3,14 9,14 C7.7,14 6.4,13.5 5.5,12.5 C3.6,10.6 3.6,7.4 5.5,5.5 C6.1,4.9 6.9,4.4 7.8,4.2 L7.2,2.3 C6,2.6 4.9,3.2 4,4.1 C1.3,6.8 1.3,11.2 4,14 C5.3,15.3 7.1,16 8.9,16 C10.8,16 12.5,15.3 13.8,14 C16.5,11.3 16.5,6.9 13.8,4.1 L16,1.9 L9.7,1.2 L9.7,1.2 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <path d="M9.7,1.2 L10.4,7.6 L12.5,5.5 C14.4,7.4 14.4,10.6 12.5,12.5 C11.6,13.5 10.3,14 9,14 C7.7,14 6.4,13.5 5.5,12.5 C3.6,10.6 3.6,7.4 5.5,5.5 C6.1,4.9 6.9,4.4 7.8,4.2 L7.2,2.3 C6,2.6 4.9,3.2 4,4.1 C1.3,6.8 1.3,11.2 4,14 C5.3,15.3 7.1,16 8.9,16 C10.8,16 12.5,15.3 13.8,14 C16.5,11.3 16.5,6.9 13.8,4.1 L16,1.9 L9.7,1.2 L9.7,1.2 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-rewind.svg b/src/sprite/plyr-rewind.svg index dec85456..99fd5992 100644 --- a/src/sprite/plyr-rewind.svg +++ b/src/sprite/plyr-rewind.svg @@ -1,6 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <polygon points="10.125 1 0 9 10.125 17 10.125 10.8285714 18 17 18 1 10.125 7.17142857"></polygon> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <polygon points="10.125 1 0 9 10.125 17 10.125 10.8285714 18 17 18 1 10.125 7.17142857"></polygon> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-settings.svg b/src/sprite/plyr-settings.svg index fbf8ecd1..d9254f4b 100644 --- a/src/sprite/plyr-settings.svg +++ b/src/sprite/plyr-settings.svg @@ -1,6 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <path d="M16.135,7.784 C14.832,7.458 14.214,5.966 14.905,4.815 C15.227,4.279 15.13,3.817 14.811,3.499 L14.501,3.189 C14.183,2.871 13.721,2.774 13.185,3.095 C12.033,3.786 10.541,3.168 10.216,1.865 C10.065,1.258 9.669,1 9.219,1 L8.781,1 C8.331,1 7.936,1.258 7.784,1.865 C7.458,3.168 5.966,3.786 4.815,3.095 C4.279,2.773 3.816,2.87 3.498,3.188 L3.188,3.498 C2.87,3.816 2.773,4.279 3.095,4.815 C3.786,5.967 3.168,7.459 1.865,7.784 C1.26,7.935 1,8.33 1,8.781 L1,9.219 C1,9.669 1.258,10.064 1.865,10.216 C3.168,10.542 3.786,12.034 3.095,13.185 C2.773,13.721 2.87,14.183 3.189,14.501 L3.499,14.811 C3.818,15.13 4.281,15.226 4.815,14.905 C5.967,14.214 7.459,14.832 7.784,16.135 C7.935,16.742 8.331,17 8.781,17 L9.219,17 C9.669,17 10.064,16.742 10.216,16.135 C10.542,14.832 12.034,14.214 13.185,14.905 C13.72,15.226 14.182,15.13 14.501,14.811 L14.811,14.501 C15.129,14.183 15.226,13.72 14.905,13.185 C14.214,12.033 14.832,10.541 16.135,10.216 C16.742,10.065 17,9.669 17,9.219 L17,8.781 C17,8.33 16.74,7.935 16.135,7.784 L16.135,7.784 Z M9,12 C7.343,12 6,10.657 6,9 C6,7.343 7.343,6 9,6 C10.657,6 12,7.343 12,9 C12,10.657 10.657,12 9,12 L9,12 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <path d="M16.135,7.784 C14.832,7.458 14.214,5.966 14.905,4.815 C15.227,4.279 15.13,3.817 14.811,3.499 L14.501,3.189 C14.183,2.871 13.721,2.774 13.185,3.095 C12.033,3.786 10.541,3.168 10.216,1.865 C10.065,1.258 9.669,1 9.219,1 L8.781,1 C8.331,1 7.936,1.258 7.784,1.865 C7.458,3.168 5.966,3.786 4.815,3.095 C4.279,2.773 3.816,2.87 3.498,3.188 L3.188,3.498 C2.87,3.816 2.773,4.279 3.095,4.815 C3.786,5.967 3.168,7.459 1.865,7.784 C1.26,7.935 1,8.33 1,8.781 L1,9.219 C1,9.669 1.258,10.064 1.865,10.216 C3.168,10.542 3.786,12.034 3.095,13.185 C2.773,13.721 2.87,14.183 3.189,14.501 L3.499,14.811 C3.818,15.13 4.281,15.226 4.815,14.905 C5.967,14.214 7.459,14.832 7.784,16.135 C7.935,16.742 8.331,17 8.781,17 L9.219,17 C9.669,17 10.064,16.742 10.216,16.135 C10.542,14.832 12.034,14.214 13.185,14.905 C13.72,15.226 14.182,15.13 14.501,14.811 L14.811,14.501 C15.129,14.183 15.226,13.72 14.905,13.185 C14.214,12.033 14.832,10.541 16.135,10.216 C16.742,10.065 17,9.669 17,9.219 L17,8.781 C17,8.33 16.74,7.935 16.135,7.784 L16.135,7.784 Z M9,12 C7.343,12 6,10.657 6,9 C6,7.343 7.343,6 9,6 C10.657,6 12,7.343 12,9 C12,10.657 10.657,12 9,12 L9,12 Z"></path> </svg>
\ No newline at end of file diff --git a/src/sprite/plyr-volume.svg b/src/sprite/plyr-volume.svg index bc533f40..7d0dd32e 100755 --- a/src/sprite/plyr-volume.svg +++ b/src/sprite/plyr-volume.svg @@ -1,8 +1,5 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <g> - <path d="M15.5999996,3.3 C15.1999996,2.9 14.5999996,2.9 14.1999996,3.3 C13.7999996,3.7 13.7999996,4.3 14.1999996,4.7 C15.3999996,5.9 15.9999996,7.4 15.9999996,9 C15.9999996,10.6 15.3999996,12.1 14.1999996,13.3 C13.7999996,13.7 13.7999996,14.3 14.1999996,14.7 C14.3999996,14.9 14.6999996,15 14.8999996,15 C15.1999996,15 15.3999996,14.9 15.5999996,14.7 C17.0999996,13.2 17.9999996,11.2 17.9999996,9 C17.9999996,6.8 17.0999996,4.8 15.5999996,3.3 L15.5999996,3.3 Z"></path> - <path d="M11.2819745,5.28197449 C10.9060085,5.65794047 10.9060085,6.22188944 11.2819745,6.59785542 C12.0171538,7.33303477 12.2772954,8.05605449 12.2772954,9.00000021 C12.2772954,9.93588462 11.851678,10.9172014 11.2819745,11.4869049 C10.9060085,11.8628709 10.9060085,12.4268199 11.2819745,12.8027859 C11.4271642,12.9479755 11.9176724,13.0649528 12.2998149,12.9592565 C12.4124479,12.9281035 12.5156669,12.8776063 12.5978555,12.8027859 C13.773371,11.732654 14.1311161,10.1597914 14.1312523,9.00000021 C14.1312723,8.8299555 14.1286311,8.66015647 14.119665,8.4897429 C14.0674781,7.49784946 13.8010171,6.48513613 12.5978554,5.28197449 C12.2218894,4.9060085 11.6579405,4.9060085 11.2819745,5.28197449 Z"></path> - <path d="M3.78571429,6.00820648 L0.714285714,6.00820648 C0.285714286,6.00820648 0,6.30901277 0,6.76022222 L0,11.2723167 C0,11.7235261 0.285714286,12.0243324 0.714285714,12.0243324 L3.78571429,12.0243324 L7.85714286,15.8819922 C8.35714286,16.1827985 9,15.8819922 9,15.2803796 L9,2.75215925 C9,2.15054666 8.35714286,1.77453879 7.85714286,2.15054666 L3.78571429,6.00820648 Z"></path> - </g> +<svg width="18px" height="18px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> + <path d="M15.5999996,3.3 C15.1999996,2.9 14.5999996,2.9 14.1999996,3.3 C13.7999996,3.7 13.7999996,4.3 14.1999996,4.7 C15.3999996,5.9 15.9999996,7.4 15.9999996,9 C15.9999996,10.6 15.3999996,12.1 14.1999996,13.3 C13.7999996,13.7 13.7999996,14.3 14.1999996,14.7 C14.3999996,14.9 14.6999996,15 14.8999996,15 C15.1999996,15 15.3999996,14.9 15.5999996,14.7 C17.0999996,13.2 17.9999996,11.2 17.9999996,9 C17.9999996,6.8 17.0999996,4.8 15.5999996,3.3 L15.5999996,3.3 Z"></path> + <path d="M11.2819745,5.28197449 C10.9060085,5.65794047 10.9060085,6.22188944 11.2819745,6.59785542 C12.0171538,7.33303477 12.2772954,8.05605449 12.2772954,9.00000021 C12.2772954,9.93588462 11.851678,10.9172014 11.2819745,11.4869049 C10.9060085,11.8628709 10.9060085,12.4268199 11.2819745,12.8027859 C11.4271642,12.9479755 11.9176724,13.0649528 12.2998149,12.9592565 C12.4124479,12.9281035 12.5156669,12.8776063 12.5978555,12.8027859 C13.773371,11.732654 14.1311161,10.1597914 14.1312523,9.00000021 C14.1312723,8.8299555 14.1286311,8.66015647 14.119665,8.4897429 C14.0674781,7.49784946 13.8010171,6.48513613 12.5978554,5.28197449 C12.2218894,4.9060085 11.6579405,4.9060085 11.2819745,5.28197449 Z"></path> + <path d="M3.78571429,6.00820648 L0.714285714,6.00820648 C0.285714286,6.00820648 0,6.30901277 0,6.76022222 L0,11.2723167 C0,11.7235261 0.285714286,12.0243324 0.714285714,12.0243324 L3.78571429,12.0243324 L7.85714286,15.8819922 C8.35714286,16.1827985 9,15.8819922 9,15.2803796 L9,2.75215925 C9,2.15054666 8.35714286,1.77453879 7.85714286,2.15054666 L3.78571429,6.00820648 Z"></path> </svg>
\ No newline at end of file @@ -2,199 +2,611 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz#a9c83233fa7cd06b39dc77adbb908616ff4f1962" - dependencies: - "@babel/highlight" "7.0.0-beta.42" - -"@babel/code-frame@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" - dependencies: - "@babel/highlight" "7.0.0-beta.44" - -"@babel/core@^7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0-beta.42.tgz#b3a838fddbd19663369a0b4892189fd8d3f82001" - dependencies: - "@babel/code-frame" "7.0.0-beta.42" - "@babel/generator" "7.0.0-beta.42" - "@babel/helpers" "7.0.0-beta.42" - "@babel/template" "7.0.0-beta.42" - "@babel/traverse" "7.0.0-beta.42" - "@babel/types" "7.0.0-beta.42" - babylon "7.0.0-beta.42" +"@babel/code-frame@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" + integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/core@>=7.1.0", "@babel/core@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.2.2.tgz#07adba6dde27bb5ad8d8672f15fde3e08184a687" + integrity sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.2.2" + "@babel/helpers" "^7.2.0" + "@babel/parser" "^7.2.2" + "@babel/template" "^7.2.2" + "@babel/traverse" "^7.2.2" + "@babel/types" "^7.2.2" convert-source-map "^1.1.0" - debug "^3.1.0" - json5 "^0.5.0" - lodash "^4.2.0" - micromatch "^2.3.11" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.10" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.42.tgz#777bb50f39c94a7e57f73202d833141f8159af33" +"@babel/generator@^7.2.2": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.0.tgz#f663838cd7b542366de3aa608a657b8ccb2a99eb" + integrity sha512-dZTwMvTgWfhmibq4V9X+LMf6Bgl7zAodRn9PvcPdhlzFMbvUutx74dbEv7Atz3ToeEpevYEJtAwfxq/bDCzHWg== dependencies: - "@babel/types" "7.0.0-beta.42" + "@babel/types" "^7.3.0" jsesc "^2.5.1" - lodash "^4.2.0" + lodash "^4.17.10" source-map "^0.5.0" trim-right "^1.0.1" -"@babel/generator@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" +"@babel/helper-annotate-as-pure@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" + integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== dependencies: - "@babel/types" "7.0.0-beta.44" - jsesc "^2.5.1" - lodash "^4.2.0" - source-map "^0.5.0" - trim-right "^1.0.1" + "@babel/types" "^7.0.0" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" + integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-call-delegate@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" + integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ== + dependencies: + "@babel/helper-hoist-variables" "^7.0.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" -"@babel/helper-function-name@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz#b38b8f4f85168d1812c543dd700b5d549b0c4658" +"@babel/helper-define-map@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c" + integrity sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg== dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.42" - "@babel/template" "7.0.0-beta.42" - "@babel/types" "7.0.0-beta.42" + "@babel/helper-function-name" "^7.1.0" + "@babel/types" "^7.0.0" + lodash "^4.17.10" -"@babel/helper-function-name@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" +"@babel/helper-explode-assignable-expression@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" + integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.44" - "@babel/template" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" -"@babel/helper-get-function-arity@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz#ad072e32f912c033053fc80478169aeadc22191e" +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== dependencies: - "@babel/types" "7.0.0-beta.42" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" -"@babel/helper-get-function-arity@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" +"@babel/helper-get-function-arity@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== dependencies: - "@babel/types" "7.0.0-beta.44" + "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz#0d0d5254220a9cc4e7e226240306b939dc210ee7" +"@babel/helper-hoist-variables@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88" + integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w== dependencies: - "@babel/types" "7.0.0-beta.42" + "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" +"@babel/helper-member-expression-to-functions@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" + integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== dependencies: - "@babel/types" "7.0.0-beta.44" + "@babel/types" "^7.0.0" -"@babel/helpers@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0-beta.42.tgz#151c1c4e9da1b6ce83d54c1be5fb8c9c57aa5044" +"@babel/helper-module-imports@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" + integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== dependencies: - "@babel/template" "7.0.0-beta.42" - "@babel/traverse" "7.0.0-beta.42" - "@babel/types" "7.0.0-beta.42" + "@babel/types" "^7.0.0" -"@babel/highlight@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.42.tgz#a502a1c0d6f99b2b0e81d468a1b0c0e81e3f3623" +"@babel/helper-module-transforms@^7.1.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz#ab2f8e8d231409f8370c883d20c335190284b963" + integrity sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA== dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.0.0" + "@babel/template" "^7.2.2" + "@babel/types" "^7.2.2" + lodash "^4.17.10" -"@babel/highlight@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" +"@babel/helper-optimise-call-expression@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" + integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-plugin-utils@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27" + integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg== + dependencies: + lodash "^4.17.10" + +"@babel/helper-remap-async-to-generator@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" + integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-wrap-function" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-replace-supers@^7.1.0": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz#19970020cf22677d62b3a689561dbd9644d8c5e5" + integrity sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.0.0" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/traverse" "^7.2.3" + "@babel/types" "^7.0.0" + +"@babel/helper-simple-access@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" + integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== + dependencies: + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-split-export-declaration@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" + integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-wrap-function@^7.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" + integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.2.0" + +"@babel/helpers@^7.2.0": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.3.1.tgz#949eec9ea4b45d3210feb7dc1c22db664c9e44b9" + integrity sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA== + dependencies: + "@babel/template" "^7.1.2" + "@babel/traverse" "^7.1.5" + "@babel/types" "^7.3.0" + +"@babel/highlight@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" + integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== dependencies: chalk "^2.0.0" esutils "^2.0.2" - js-tokens "^3.0.0" - -"@babel/template@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.42.tgz#7186d4e70d44cdec975049ba0a73bdaf5cdee052" - dependencies: - "@babel/code-frame" "7.0.0-beta.42" - "@babel/types" "7.0.0-beta.42" - babylon "7.0.0-beta.42" - lodash "^4.2.0" - -"@babel/template@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" - dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - lodash "^4.2.0" - -"@babel/traverse@7.0.0-beta.42", "@babel/traverse@^7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.42.tgz#f4bf4d1e33d41baf45205e2d0463591d57326285" - dependencies: - "@babel/code-frame" "7.0.0-beta.42" - "@babel/generator" "7.0.0-beta.42" - "@babel/helper-function-name" "7.0.0-beta.42" - "@babel/helper-split-export-declaration" "7.0.0-beta.42" - "@babel/types" "7.0.0-beta.42" - babylon "7.0.0-beta.42" - debug "^3.1.0" - globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.2.0" - -"@babel/traverse@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" - dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/generator" "7.0.0-beta.44" - "@babel/helper-function-name" "7.0.0-beta.44" - "@babel/helper-split-export-declaration" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - debug "^3.1.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.1.tgz#8f4ffd45f779e6132780835ffa7a215fa0b2d181" + integrity sha512-ATz6yX/L8LEnC3dtLQnIx4ydcPxhLcoy9Vl6re00zb2w5lG6itY6Vhnr1KFRPq/FHNsgl/gh2mjNN20f9iJTTA== + +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + +"@babel/plugin-proposal-object-rest-spread@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz#f69fb6a1ea6a4e1c503994a91d9cf76f3c4b36e8" + integrity sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520" + integrity sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + regexpu-core "^4.2.0" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-async-to-generator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff" + integrity sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoping@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4" + integrity sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.10" + +"@babel/plugin-transform-classes@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz#6c90542f210ee975aa2aa8c8b5af7fa73a126953" + integrity sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-define-map" "^7.1.0" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.0.0" globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.2.0" -"@babel/types@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.42.tgz#1e2118767684880f6963801b272fd2b3348efacc" +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== dependencies: - esutils "^2.0.2" - lodash "^4.2.0" - to-fast-properties "^2.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz#e75269b4b7889ec3a332cd0d0c8cff8fed0dc6f3" + integrity sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49" + integrity sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + regexpu-core "^4.1.3" + +"@babel/plugin-transform-duplicate-keys@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" + integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-for-of@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9" + integrity sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a" + integrity sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-amd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" + integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-commonjs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404" + integrity sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + +"@babel/plugin-transform-modules-systemjs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068" + integrity sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ== + dependencies: + "@babel/helper-hoist-variables" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" + integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50" + integrity sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw== + dependencies: + regexp-tree "^0.1.0" + +"@babel/plugin-transform-new-target@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" + integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-object-super@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" + integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.1.0" + +"@babel/plugin-transform-parameters@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz#0d5ad15dc805e2ea866df4dd6682bfe76d1408c2" + integrity sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA== + dependencies: + "@babel/helper-call-delegate" "^7.1.0" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" -"@babel/types@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" +"@babel/plugin-transform-regenerator@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1" + integrity sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw== + dependencies: + regenerator-transform "^0.13.3" + +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" + integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b" + integrity sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-unicode-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b" + integrity sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + regexpu-core "^4.1.3" + +"@babel/preset-env@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db" + integrity sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.3.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.2.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.2.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.2.0" + "@babel/plugin-transform-classes" "^7.2.0" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.2.0" + "@babel/plugin-transform-dotall-regex" "^7.2.0" + "@babel/plugin-transform-duplicate-keys" "^7.2.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.2.0" + "@babel/plugin-transform-function-name" "^7.2.0" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.2.0" + "@babel/plugin-transform-modules-commonjs" "^7.2.0" + "@babel/plugin-transform-modules-systemjs" "^7.2.0" + "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0" + "@babel/plugin-transform-new-target" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.2.0" + "@babel/plugin-transform-parameters" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.2.0" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.2.0" + browserslist "^4.3.4" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.3.0" + +"@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" + integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.2.2" + "@babel/types" "^7.2.2" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2", "@babel/traverse@^7.2.3": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8" + integrity sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.2.2" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.0.0" + "@babel/parser" "^7.2.3" + "@babel/types" "^7.2.2" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.10" + +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.0.tgz#61dc0b336a93badc02bf5f69c4cd8e1353f2ffc0" + integrity sha512-QkFPw68QqWU1/RVPyBe8SO7lXbPfjtqAxRYQKpFpaB8yMq7X2qAqfwK5LKoQufEkSmO5NQ70O6Kc3Afk03RwXw== dependencies: esutils "^2.0.2" - lodash "^4.2.0" + lodash "^4.17.10" to-fast-properties "^2.0.0" "@gulp-sourcemaps/identity-map@1.X": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1" + version "1.0.2" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz#1e6fe5d8027b1f285dc0d31762f566bccd73d5a9" + integrity sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ== dependencies: acorn "^5.0.3" css "^2.2.1" normalize-path "^2.1.1" - source-map "^0.5.6" + source-map "^0.6.0" through2 "^2.0.3" "@gulp-sourcemaps/map-sources@1.X": version "1.0.0" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" + integrity sha1-iQrnxdjId/bThIYCFazp1+yUW9o= dependencies: normalize-path "^2.0.1" through2 "^2.0.3" @@ -202,159 +614,231 @@ "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== dependencies: call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -JSONStream@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/node@*": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + +"@types/q@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" + integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== + +"@types/unist@*", "@types/unist@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.2.tgz#5dc0a7f76809b7518c0df58689cd16a19bd751c6" + integrity sha512-iHI60IbyfQilNubmxsq4zqSjdynlmc2Q/QvH9kjzg9+CCYVVzq1O6tc7VBzSygIwnmOt07w80IG6HDQvjv3Liw== + +"@types/vfile-message@*": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" + integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA== + dependencies: + "@types/node" "*" + "@types/unist" "*" + +"@types/vfile@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9" + integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw== dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" + "@types/node" "*" + "@types/unist" "*" + "@types/vfile-message" "*" -abbrev@1, abbrev@~1.1.1: +abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" + integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== + acorn@5.X, acorn@^5.0.3, acorn@^5.5.0: - version "5.5.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" - dependencies: - es6-promisify "^5.0.0" - -agentkeepalive@^3.3.0, agentkeepalive@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.4.1.tgz#aa95aebc3a749bca5ed53e3880a09f5235b48f0c" - dependencies: - humanize-ms "^1.2.1" +acorn@^6.0.2: + version "6.0.5" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a" + integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg== ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" + version "3.2.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" + integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= -ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: +ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.0.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.1.tgz#28a6abc493a2abe0fb4c8507acaedb43fa550671" +ajv@^6.0.1, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: + version "6.7.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96" + integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg== dependencies: - fast-deep-equal "^1.0.0" + fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= dependencies: string-width "^2.0.0" ansi-colors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== dependencies: ansi-wrap "^0.1.0" ansi-cyan@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= dependencies: ansi-wrap "0.1.0" ansi-escapes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= dependencies: ansi-wrap "0.1.0" ansi-red@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= dependencies: ansi-wrap "0.1.0" ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" + integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-regex@^3.0.0, ansi-regex@~3.0.0: +ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" + integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" + integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -ansicolors@^0.3.2, ansicolors@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" -ansistyles@^0.1.3, ansistyles@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" +append-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" -aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2, aproba@~1.2.0: +aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -archy@^1.0.0, archy@~1.0.0: +archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -362,12 +846,14 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" arr-diff@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= dependencies: arr-flatten "^1.0.1" array-slice "^0.2.3" @@ -375,116 +861,190 @@ arr-diff@^1.0.1: arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-filter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" + integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= + dependencies: + make-iterator "^1.0.0" arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-map@^2.0.0, arr-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" + integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= + dependencies: + make-iterator "^1.0.0" arr-union@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= -array-each@^1.0.1: +array-each@^1.0.0, array-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= -array-iterate@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.1.tgz#865bf7f8af39d6b0982c60902914ac76bc0108f6" +array-initial@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" + integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= + dependencies: + array-slice "^1.0.0" + is-number "^4.0.0" + +array-last@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" + integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== + dependencies: + is-number "^4.0.0" array-slice@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= array-slice@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== -array-union@^1.0.1: +array-sort@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" + integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== + dependencies: + default-compare "^1.0.0" + get-value "^2.0.6" + kind-of "^5.0.2" + +array-union@^1.0.1, array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1, array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-done@^1.2.0, async-done@^1.2.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.1.tgz#14b7b73667b864c8f02b5b253fc9c6eddb777f3e" + integrity sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.2" + process-nextick-args "^1.0.7" + stream-exhaust "^1.0.1" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= + +async-settle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" + integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= + dependencies: + async-done "^1.2.2" async@: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: - lodash "^4.14.0" + lodash "^4.17.10" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^7.1.2: version "7.2.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" + integrity sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ== dependencies: browserslist "^2.11.3" caniuse-lite "^1.0.30000805" @@ -493,555 +1053,86 @@ autoprefixer@^7.1.2: postcss "^6.0.17" postcss-value-parser "^3.2.3" -autoprefixer@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.1.0.tgz#374cf35be1c0e8fce97408d876f95f66f5cb4641" +autoprefixer@^9.0.0, autoprefixer@^9.1.3: + version "9.4.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.4.6.tgz#0ace275e33b37de16b09a5547dbfe73a98c1d446" + integrity sha512-Yp51mevbOEdxDUy5WjiKtpQaecqYq9OqZSL04rSoCiry7Tc5I9FEyo3bfxiTJc1DfHeKwSFCUYbBAiOQ2VGfiw== dependencies: - browserslist "^3.1.1" - caniuse-lite "^1.0.30000810" + browserslist "^4.4.1" + caniuse-lite "^1.0.30000929" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^6.0.19" - postcss-value-parser "^3.2.3" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + postcss "^7.0.13" + postcss-value-parser "^3.3.1" aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - -babel-core@^6.26.3: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-eslint@^8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf" +babel-eslint@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" + integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/traverse" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - eslint-scope "~3.7.1" + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-external-helpers@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-polyfill@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - dependencies: - babel-runtime "^6.26.0" - core-js "^2.5.0" - regenerator-runtime "^0.10.5" - -babel-preset-env@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^2.1.2" - invariant "^2.2.2" - semver "^5.3.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: +babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" +bach@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" + integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@7.0.0-beta.42, babylon@^7.0.0-beta.42: - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.42.tgz#67cfabcd4f3ec82999d29031ccdea89d0ba99657" - -babylon@7.0.0-beta.44: - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + arr-filter "^1.1.1" + arr-flatten "^1.0.1" + arr-map "^2.0.0" + array-each "^1.0.0" + array-initial "^1.0.0" + array-last "^1.1.1" + async-done "^1.2.2" + async-settle "^1.0.0" + now-and-later "^2.0.0" bail@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" + version "1.0.3" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" + integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1052,64 +1143,43 @@ base@^0.11.1: pascalcase "^0.1.1" bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" beeper@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= -bin-links@^1.1.0, bin-links@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" - dependencies: - bluebird "^3.5.0" - cmd-shim "^2.0.2" - gentle-fs "^2.0.0" - graceful-fs "^4.1.11" - write-file-atomic "^2.3.0" +binary-extensions@^1.0.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== -binaryextensions@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755" +binaryextensions@2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.2.tgz#c83c3d74233ba7674e4f313cb2a2b70f54e94b7c" + integrity sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg== block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" -bluebird@^3.5.0, bluebird@^3.5.1, bluebird@~3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - -boolbase@~1.0.0: +boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== dependencies: ansi-align "^2.0.0" camelcase "^4.0.0" @@ -1119,9 +1189,10 @@ boxen@^1.2.1: term-size "^1.2.0" widest-line "^2.0.0" -brace-expansion@^1.0.0, brace-expansion@^1.1.7: +brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1129,106 +1200,69 @@ brace-expansion@^1.0.0, brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" - define-property "^1.0.0" extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" - kind-of "^6.0.2" repeat-element "^1.1.2" snapdragon "^0.8.1" snapdragon-node "^2.0.1" split-string "^3.0.2" to-regex "^3.0.1" -browserslist@^2.1.2, browserslist@^2.11.3: +browserslist@^2.11.3: version "2.11.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" + integrity sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA== dependencies: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" -browserslist@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.1.2.tgz#893f29399d640ed35fe06bacd7eb1d78609a47e5" +browserslist@^4.3.4, browserslist@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.1.tgz#42e828954b6b29a7a53e352277be429478a69062" + integrity sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A== dependencies: - caniuse-lite "^1.0.30000813" - electron-to-chromium "^1.3.36" + caniuse-lite "^1.0.30000929" + electron-to-chromium "^1.3.103" + node-releases "^1.1.3" -buffer-from@^1.0.0: +buffer-equal@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= -builtin-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" - -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - -byline@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" - -byte-size@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.2.tgz#e8ddbf7161913965c6af5b236a4bed8896bdc83e" - -cacache@^10.0.0, cacache@^10.0.4: - version "10.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" - dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.1" - mississippi "^2.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.2" - ssri "^5.2.4" - unique-filename "^1.1.0" - y18n "^4.0.0" - -cacache@^11.0.1: - version "11.0.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.0.1.tgz#63cde88b51aa5f50741e34833c9d0048a138d1dd" - dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - figgy-pudding "^3.1.0" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.2" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.2" - ssri "^6.0.0" - unique-filename "^1.1.0" - y18n "^4.0.0" +builtin-modules@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.0.0.tgz#1e587d44b006620d90286cc7a9238bbc6129cab1" + integrity sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg== cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1240,27 +1274,51 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -call-limit@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" - call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" + integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= dependencies: camelcase "^2.0.0" map-obj "^1.0.0" @@ -1268,6 +1326,7 @@ camelcase-keys@^2.0.0: camelcase-keys@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= dependencies: camelcase "^4.1.0" map-obj "^2.0.0" @@ -1276,38 +1335,47 @@ camelcase-keys@^4.0.0: camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= -caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000810, caniuse-lite@^1.0.30000813: - version "1.0.30000815" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000815.tgz#3a4258e6850362185adb11b0d754a48402d35bf6" +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== -capture-stack-trace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" +caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000929: + version "1.0.30000932" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000932.tgz#d01763e9ce77810962ca7391ff827b5949ce4272" + integrity sha512-4bghJFItvzz8m0T3lLZbacmEY9X1Z2AtIzTr7s7byqZIOumASfr4ynDx7rtm0J85nDmx8vsgR6vnaSoeU8Oh0A== -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" +capture-stack-trace@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" + integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= ccount@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.2.tgz#53b6a2f815bb77b9c2871f7b9a72c3a25f1d8e89" + version "1.0.3" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff" + integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw== chalk@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" + integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= dependencies: ansi-styles "^1.1.0" escape-string-regexp "^1.0.0" @@ -1318,6 +1386,7 @@ chalk@^0.5.0: chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1325,37 +1394,49 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" character-entities-html4@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.1.tgz#359a2a4a0f7e29d3dc2ac99bdbe21ee39438ea50" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" + integrity sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw== character-entities-legacy@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz#f40779df1a101872bb510a3d295e1fccf147202f" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" + integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA== character-entities@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.1.tgz#f76871be5ef66ddb7f8f8e3478ecc374c27d6dca" + version "1.2.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" + integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ== character-reference-invalid@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz#942835f750e4ec61a308e60c2ef8cc1011202efc" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" + integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ== chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== cheerio@0.*: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" @@ -1374,78 +1455,89 @@ cheerio@0.*: lodash.reject "^4.4.0" lodash.some "^4.4.0" -chownr@^1.0.1, chownr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" +chokidar@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + lodash.debounce "^4.0.8" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.5" + optionalDependencies: + fsevents "^1.2.2" -ci-info@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== -cidr-regex@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.8.tgz#c79bae6223d241c0860d93bfde1fb1c1c4fdcab6" - dependencies: - ip-regex "^2.1.0" +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - dependencies: - chalk "^1.1.3" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" static-extend "^0.1.1" -clean-css@4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a" +clean-css@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" + integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== dependencies: - source-map "0.5.x" + source-map "~0.6.0" cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - -cli-columns@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" - dependencies: - string-width "^2.0.0" - strip-ansi "^3.0.1" + integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" -cli-table2@^0.2.0, cli-table2@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/cli-table2/-/cli-table2-0.2.0.tgz#2d1ef7f218a0e786e214540562d4bd177fe32d97" +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== dependencies: - lodash "^3.10.1" - string-width "^1.0.1" + object-assign "^4.1.0" + string-width "^2.1.1" optionalDependencies: colors "^1.1.2" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1454,6 +1546,7 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1462,10 +1555,12 @@ cliui@^4.0.0: clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= clone-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c" + version "1.0.1" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f" + integrity sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw== dependencies: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" @@ -1473,153 +1568,148 @@ clone-regexp@^1.0.0: clone-stats@^0.0.1, clone-stats@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= clone-stats@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - -clone@^1.0.0, clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" +clone@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= cloneable-readable@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== dependencies: inherits "^2.0.1" process-nextick-args "^2.0.0" readable-stream "^2.3.5" -cmd-shim@^2.0.2, cmd-shim@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" - dependencies: - graceful-fs "^4.1.2" - mkdirp "~0.5.0" - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" +coa@~2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" q "^1.1.2" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= collapse-white-space@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" + version "1.0.4" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" + integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw== + +collection-map@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" + integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= + dependencies: + arr-map "^2.0.2" + for-own "^1.0.0" + make-iterator "^1.0.0" collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: - color-name "^1.1.1" + color-name "1.1.3" -color-name@^1.1.1: +color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colors@^1.1.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.1.tgz#f4a3d302976aaf042356ba1ade3b1a2c62d9d794" + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= -columnify@~1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" - dependencies: - strip-ansi "^3.0.0" - wcwidth "^1.0.0" - -combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" -commander@^2.9.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322" - -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" +commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== common-tags@^1.4.0: - version "1.7.2" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.7.2.tgz#24d9768c63d253a56ecff93845b44b4df1d52771" - dependencies: - babel-runtime "^6.26.0" + version "1.8.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" + integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.5.2: +concat-stream@^1.5.1, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" -concat-stream@^1.6.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -concat-with-sourcemaps@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz#8964bc2347d05819b63798104d87d6e001bed8d0" +concat-with-sourcemaps@^1.0.0, concat-with-sourcemaps@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== dependencies: source-map "^0.6.1" -config-chain@~1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - configstore@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== dependencies: dot-prop "^4.1.0" graceful-fs "^4.1.2" @@ -1631,41 +1721,47 @@ configstore@^3.0.0: console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" +convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" + safe-buffer "~5.1.1" copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +copy-props@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" + integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== + dependencies: + each-props "^1.3.0" + is-plain-object "^2.0.1" -core-js@^2.4.0, core-js@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" +core-js@^2.4.0, core-js@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.3.tgz#4b70938bdffdaf64931e66e2db158f0892289c49" + integrity sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cosmiconfig@^3.0.1, cosmiconfig@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397" + integrity sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" @@ -1675,21 +1771,34 @@ cosmiconfig@^3.0.1, cosmiconfig@^3.1.0: cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" + integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" parse-json "^4.0.0" require-from-string "^2.0.1" +cosmiconfig@^5.0.0: + version "5.0.7" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04" + integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= dependencies: capture-stack-trace "^1.0.0" cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= dependencies: lru-cache "^4.0.1" which "^1.2.9" @@ -1697,89 +1806,131 @@ cross-spawn@^3.0.0: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" which "^1.2.9" -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: - boom "5.x.x" + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + +css-select-base-adapter@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== + dependencies: + boolbase "^1.0.0" + css-what "^2.1.2" + domutils "^1.7.0" + nth-check "^1.0.2" css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= dependencies: boolbase "~1.0.0" css-what "2.1" domutils "1.5.1" nth-check "~1.0.1" -css-what@2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" +css-tree@1.0.0-alpha.28: + version "1.0.0-alpha.28" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" + integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-url-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" + integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= + +css-what@2.1, css-what@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" + integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== css@2.X, css@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.3.0" + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" urix "^0.1.0" -cssesc@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-1.0.1.tgz#ef7bd8d0229ed6a3a7051ff7771265fe7330e0a8" +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" +csso@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== dependencies: - clap "^1.0.9" - source-map "^0.5.3" + css-tree "1.0.0-alpha.29" currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= dependencies: array-find-index "^1.0.1" -custom-event-polyfill@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/custom-event-polyfill/-/custom-event-polyfill-0.3.0.tgz#99807839be62edb446b645832e0d80ead6fa1888" - -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" +custom-event-polyfill@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/custom-event-polyfill/-/custom-event-polyfill-1.0.6.tgz#6b026e81cd9f7bc896bd6b016a427407bb068db1" + integrity sha512-3FxpFlzGcHrDykwWu+xWVXZ8PfykM/9/bI3zXb953sh+AjInZWcQmrnmvPoZgiqNjmbtTm10PWvYqvRW527x6g== d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" dateformat@^1.0.11, dateformat@^1.0.7-1.2.3: version "1.0.12" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= dependencies: get-stdin "^4.0.1" meow "^3.3.0" @@ -1787,40 +1938,49 @@ dateformat@^1.0.11, dateformat@^1.0.7-1.2.3: dateformat@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= debug-fabulous@1.X: - version "1.0.0" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.0.0.tgz#57f6648646097b1b0849dcda0017362c1ec00f8b" + version "1.1.0" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" + integrity sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg== dependencies: debug "3.X" memoizee "0.4.X" object-assign "4.X" -debug@3.1.0, debug@3.X, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" +debug@3.X, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: - ms "2.0.0" + ms "^2.1.1" debug@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/debug/-/debug-1.0.5.tgz#f7241217430f99dec4c2b473eab92228e874c2ac" + integrity sha1-9yQSF0MPmd7EwrRz6rkiKOh0wqw= dependencies: ms "2.0.0" -debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debuglog@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" +debug@^4.0.0, debug@^4.0.1, debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -1828,59 +1988,68 @@ decamelize-keys@^1.0.0: decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -defaults@^1.0.0, defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" +default-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== dependencies: - clone "^1.0.2" + kind-of "^5.0.2" + +default-resolution@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" + integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - del@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" + integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= dependencies: globby "^6.1.0" is-path-cwd "^1.0.0" @@ -1892,54 +2061,44 @@ del@^3.0.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -deprecated@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -detect-indent@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -detect-newline@2.X, detect-newline@^2.1.0: +detect-newline@2.X: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= -dezalgo@^1.0.0, dezalgo@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - dependencies: - asap "^2.0.0" - wrappy "1" - -dir-glob@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" +dir-glob@^2.0.0, dir-glob@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== dependencies: - arrify "^1.0.1" path-type "^3.0.0" dlv@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.1.tgz#c79d96bfe659a5568001250ed2aaf653992bdd3f" + version "1.1.2" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.2.tgz#270f6737b30d25b6657a7e962c784403f85137e5" + integrity sha512-xxD4VSH67GbRvSGUrckvha94RD7hjgOH7rqGxiytLpkaeMvixOHFZTGFK6EkIm3T761OVHT8ABHmGkq9gXgu6Q== doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -1947,40 +2106,47 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= dependencies: domelementtype "~1.1.1" entities "~1.1.1" domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= domhandler@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== dependencies: domelementtype "1" domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= dependencies: dom-serializer "0" domelementtype "1" -domutils@^1.5.1: +domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: dom-serializer "0" domelementtype "1" @@ -1988,123 +2154,143 @@ domutils@^1.5.1: dot-prop@^4.1.0, dot-prop@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== dependencies: is-obj "^1.0.0" -dotenv@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" - duplexer2@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= dependencies: readable-stream "~1.1.9" duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@^0.1.1, duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= -duplexify@^3.4.2, duplexify@^3.5.3: - version "3.5.4" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" +duplexify@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" + integrity sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA== dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" readable-stream "^2.0.0" stream-shift "^1.0.0" +each-props@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" + integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== + dependencies: + is-plain-object "^2.0.1" + object.defaults "^1.1.0" + ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" + safer-buffer "^2.1.0" -editor@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" +editions@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" + integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== -electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.36: - version "1.3.38" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.38.tgz#49234b00c0592f62921f9426bccefee23de086bb" +electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.30: + version "1.3.108" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.108.tgz#2e79a6fcaa4b3e7c75abf871505bda8e268c910e" + integrity sha512-/QI4hMpAh48a1Sea6PALGv+kuVne9A2EWGd8HrWHMdYhIzGtbhVVHh6heL5fAzGaDnZuPyrlWJRl8WPm4RyiQQ== -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" +"emoji-regex@>=6.0.0 <=6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" + integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4= + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" -end-of-stream@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - dependencies: - once "~1.3.0" - entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -err-code@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" - -errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - dependencies: - prr "~1.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.40" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.40.tgz#ab3d2179b943008c5e9ef241beb25ef41424c774" +es-abstract@^1.12.0, es-abstract@^1.5.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.47" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.47.tgz#d24232e1380daad5449a817be19bde9729024a11" + integrity sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" + next-tick "1" es6-iterator@^2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@^4.0.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - dependencies: - es6-promise "^4.0.3" - es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" -es6-weak-map@^2.0.2: +es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2114,66 +2300,99 @@ es6-weak-map@^2.0.2: escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-airbnb-base@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944" +eslint-config-airbnb-base@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz#b5a1b480b80dfad16433d6c4ad84e6605052c05c" + integrity sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw== dependencies: eslint-restricted-globals "^0.1.1" + object.assign "^4.1.0" + object.entries "^1.0.4" -eslint-config-prettier@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" +eslint-config-prettier@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz#8ca3ffac4bd6eeef623a0651f9d754900e3ec217" + integrity sha512-ixJ4U3uTLXwJts4rmSVW/lMXjlGwCijhBJHk8iVqKKSifeI0qgFEfWl8L63isfc8Od7EiBALF6BX3jKLluf/jQ== dependencies: - get-stdin "^5.0.1" + get-stdin "^6.0.0" -eslint-import-resolver-node@^0.3.1: +eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" -eslint-module-utils@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" +eslint-module-utils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" + integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== dependencies: debug "^2.6.8" - pkg-dir "^1.0.0" + pkg-dir "^2.0.0" -eslint-plugin-import@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.11.0.tgz#15aeea37a67499d848e8e981806d4627b5503816" +eslint-plugin-import@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.15.0.tgz#d8f3c28b8988ccde5df964706faa7c1e52f0602a" + integrity sha512-LEHqgR+RcnpGqYW7h9WMkPb/tP+ekKxWdQDztfTtZeV43IHF+X8lXU+1HOCcR4oXD24qRgEwNSxIweD5uNKGVg== dependencies: contains-path "^0.1.0" - debug "^2.6.8" + debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.2.0" - has "^1.0.1" - lodash "^4.17.4" - minimatch "^3.0.3" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.3.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" read-pkg-up "^2.0.0" - resolve "^1.6.0" + resolve "^1.9.0" eslint-restricted-globals@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" + integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc= -eslint-scope@^3.7.1, eslint-scope@~3.7.1: +eslint-scope@3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^3.7.1: + version "3.7.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" + integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" + integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== + eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^4.0.0: - version "4.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.0.tgz#9e900efb5506812ac374557034ef6f5c3642fc4c" + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -2214,118 +2433,125 @@ eslint@^4.0.0: table "4.0.2" text-table "~0.2.0" -eslint@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" +eslint@^5.12.1: + version "5.12.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.12.1.tgz#5ca9931fb9029d04e7be92b03ce3b58edfac7e3b" + integrity sha512-54NV+JkTpTu0d8+UYSA8mMKAG4XAsaOrozA9rCW7tgneg1mevcL7wIotPC+fZ0SkWwdhNqoXoxnQCTBp7UvTsg== dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" + "@babel/code-frame" "^7.0.0" + ajv "^6.5.3" chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" doctrine "^2.1.0" - eslint-scope "^3.7.1" + eslint-scope "^4.0.0" + eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" + espree "^5.0.0" + esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" + inquirer "^6.1.0" + js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" + lodash "^4.17.5" + minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" pluralize "^7.0.0" progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" + regexpp "^2.0.1" + semver "^5.5.1" strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" + strip-json-comments "^2.0.1" + table "^5.0.2" + text-table "^0.2.0" -espree@^3.5.4: +espree@^3.5.2, espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" -esprima@^2.6.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +espree@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.0.tgz#fc7f984b62b36a0f543b13fb9cd7b9f4a7f5b65c" + integrity sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA== + dependencies: + acorn "^6.0.2" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" +esquery@^1.0.0, esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= -estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - -estree-walker@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" - -estree-walker@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.1.tgz#64fc375053abc6f57d73e9bd2f004644ad3c5854" +estree-walker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" + integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig== esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= event-emitter@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" event-stream@*: - version "3.3.4" - resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + version "4.0.1" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-4.0.1.tgz#4092808ec995d0dd75ea4580c1df6a74db2cde65" + integrity sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA== dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" + duplexer "^0.1.1" + from "^0.1.7" + map-stream "0.0.7" + pause-stream "^0.0.11" + split "^1.0.1" + stream-combiner "^0.2.2" + through "^2.3.8" execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -2338,18 +2564,21 @@ execa@^0.7.0: execall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" + integrity sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M= dependencies: clone-regexp "^1.0.0" expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -2362,55 +2591,78 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" extend-shallow@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= dependencies: kind-of "^1.1.0" extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extend@~2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-2.0.2.tgz#1b74985400171b85554894459c978de6ef453ab7" + integrity sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ== external-editor@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" tmp "^0.0.33" +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -2424,92 +2676,121 @@ extglob@^2.0.4: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fancy-log@^1.1.0, fancy-log@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + version "1.3.3" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== dependencies: ansi-gray "^0.1.1" color-support "^1.1.3" + parse-node-version "^1.0.0" time-stamp "^1.0.0" fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= -fast-glob@^2.0.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.0.tgz#e9d032a69b86bef46fc03d935408f02fb211d9fc" +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-glob@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" + integrity sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" glob-parent "^3.1.0" is-glob "^4.0.0" - merge2 "^1.2.1" - micromatch "^3.1.8" + merge2 "^1.2.3" + micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -figgy-pudding@^3.0.0, figgy-pudding@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.1.0.tgz#a77ed2284175976c424b390b298569e9df86dd1e" +fastly-purge@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fastly-purge/-/fastly-purge-1.0.1.tgz#3bdfe9ea1d0fbf2a65712f2f5fe2eca63fcb5960" + integrity sha1-O9/p6h0PvyplcS8vX+Lspj/LWWA= + dependencies: + request "^2.55.0" + +fault@^1.0.0, fault@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa" + integrity sha512-o2eo/X2syzzERAtN5LcGbiVQ0WwZSlN3qLtadwAz3X8Bu+XWD16dja/KMsjZLiQr+BLGPDnHGkc4yUJf1Xpkpw== + dependencies: + format "^0.2.2" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" +file-entry-cache@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-4.0.0.tgz#633567d15364aefe0b299e1e217735e8f3a9f6e8" + integrity sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA== + dependencies: + flat-cache "^2.0.1" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" - randomatic "^1.1.3" + randomatic "^3.0.0" repeat-element "^1.1.2" repeat-string "^1.5.2" fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-index@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" - -find-npm-prefix@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -2517,12 +2798,14 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= dependencies: detect-file "^1.0.0" is-glob "^3.1.0" @@ -2530,8 +2813,9 @@ findup-sync@^2.0.0: resolve-dir "^1.0.1" fined@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" + version "1.1.1" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.1.tgz#95d88ff329123dd1a6950fdfcd321f746271e01f" + integrity sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g== dependencies: expand-tilde "^2.0.2" is-plain-object "^2.0.3" @@ -2539,137 +2823,155 @@ fined@^1.0.1: object.pick "^1.2.0" parse-filepath "^1.0.1" -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - flagged-respawn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" + version "1.0.1" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" + integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== dependencies: circular-json "^0.3.1" - del "^2.0.2" graceful-fs "^4.1.2" + rimraf "~2.6.2" write "^0.2.1" -flush-write-stream@^1.0.0: +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" + integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= + +flush-write-stream@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" + integrity sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw== dependencies: inherits "^2.0.1" readable-stream "^2.0.4" +fn-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" + integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= + for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" for-own@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "^1.0.6" mime-types "^2.1.12" -form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" +format@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" -from2@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" - dependencies: - inherits "~2.0.1" - readable-stream "~1.1.10" - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -from@~0: +from@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" -fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: - version "1.2.10" - resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" - dependencies: - graceful-fs "^4.1.2" - path-is-inside "^1.0.1" - rimraf "^2.5.2" - -fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" + graceful-fs "^4.1.11" + through2 "^2.0.3" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.2: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" + integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" fstream@^1.0.0, fstream@^1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.0.2: +function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -2680,84 +2982,68 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gaze@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" - dependencies: - globule "~0.1.0" - gaze@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== dependencies: globule "^1.0.0" -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -genfun@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" - -gentle-fs@^2.0.0, gentle-fs@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.0.1.tgz#585cfd612bfc5cd52471fdb42537f016a5ce3687" - dependencies: - aproba "^1.1.2" - fs-vacuum "^1.2.10" - graceful-fs "^4.1.11" - iferr "^0.1.5" - mkdirp "^0.5.1" - path-is-inside "^1.0.2" - read-cmd-shim "^1.0.1" - slide "^1.1.6" - get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" git-branch@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/git-branch/-/git-branch-2.0.1.tgz#442724a97574c66ede4290ded75b7430785da08f" + integrity sha512-jMCT1kjXvsUdZKQd2p8E1uZhKsIuR1pnHgcDYQpQiXBtzE9cmYGvOcCSGqqi58x0B9CPS0lUSu/yti866est8g== dependencies: findup-sync "^2.0.0" +github-slugger@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.2.1.tgz#47e904e70bf2dccd0014748142d31126cfd49508" + integrity sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ== + dependencies: + emoji-regex ">=6.0.0 <=6.1.1" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -2765,65 +3051,55 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-stream@^3.1.5: - version "3.1.18" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= dependencies: - glob "^4.3.1" - glob2base "^0.0.12" - minimatch "^2.0.1" - ordered-read-streams "^0.1.0" - through2 "^0.6.1" - unique-stream "^1.0.0" + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob-watcher@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" - dependencies: - gaze "^0.5.1" - -glob2base@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" - dependencies: - find-index "^0.1.1" - -glob@^4.3.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" +glob-watcher@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" + integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + dependencies: + anymatch "^2.0.0" + async-done "^1.2.0" + chokidar "^2.0.0" + is-negated-glob "^1.0.0" + just-debounce "^1.0.0" + object.defaults "^1.1.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2832,31 +3108,33 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, gl once "^1.3.0" path-is-absolute "^1.0.0" -glob@~3.1.21: - version "3.1.21" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" - dependencies: - graceful-fs "~1.2.0" - inherits "1" - minimatch "~0.2.11" - global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= dependencies: ini "^1.3.4" global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" is-windows "^1.0.1" resolve-dir "^1.0.0" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: expand-tilde "^2.0.2" homedir-polyfill "^1.0.1" @@ -2864,28 +3142,24 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" -globals@^11.0.1, globals@^11.1.0: - version "11.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0" - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.0.1, globals@^11.1.0, globals@^11.7.0: + version "11.10.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.10.0.tgz#1e09776dffda5e01816b3bb4077c8b59c24eaa50" + integrity sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ== globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= dependencies: array-union "^1.0.1" glob "^7.0.3" @@ -2896,6 +3170,7 @@ globby@^6.1.0: globby@^7.0.0: version "7.1.1" resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= dependencies: array-union "^1.0.1" dir-glob "^2.0.0" @@ -2904,53 +3179,51 @@ globby@^7.0.0: pify "^3.0.0" slash "^1.0.0" -globby@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" +globby@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-9.0.0.tgz#3800df736dc711266df39b4ce33fe0d481f94c23" + integrity sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw== dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - fast-glob "^2.0.2" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" + array-union "^1.0.2" + dir-glob "^2.2.1" + fast-glob "^2.2.6" + glob "^7.1.3" + ignore "^4.0.3" + pify "^4.0.1" + slash "^2.0.0" globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= globule@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" + version "1.2.1" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" + integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ== dependencies: glob "~7.1.1" - lodash "~4.17.4" + lodash "~4.17.10" minimatch "~3.0.2" -globule@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" - dependencies: - glob "~3.1.21" - lodash "~1.0.1" - minimatch "~0.2.11" - glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== dependencies: sparkles "^1.0.0" gonzales-pe@^4.0.3, gonzales-pe@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" + integrity sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw== dependencies: minimist "1.1.x" got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= dependencies: create-error-class "^3.0.0" duplexer3 "^0.1.4" @@ -2964,53 +3237,72 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -graceful-fs@4.X, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@~4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graceful-fs@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" - dependencies: - natives "^1.1.0" - -graceful-fs@~1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" - -gulp-autoprefixer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/gulp-autoprefixer/-/gulp-autoprefixer-5.0.0.tgz#8237c278a69775270a1cafe7d6f101cfcd585544" +gulp-autoprefixer@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gulp-autoprefixer/-/gulp-autoprefixer-6.0.0.tgz#7034ef12c24a92a5b20158d63623ebbd900faed8" + integrity sha512-MyLymXKVGTVBx/okQSBqmdhwhyqi3igBmZBwgpZp0GRbY1LY8VctOTLzwkQ18bZKJkSDnOKR5u32TMY9wSYdqQ== dependencies: - autoprefixer "^8.0.0" + autoprefixer "^9.1.3" fancy-log "^1.3.2" plugin-error "^1.0.1" - postcss "^6.0.1" + postcss "^7.0.2" through2 "^2.0.0" vinyl-sourcemaps-apply "^0.2.0" -gulp-better-rollup@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/gulp-better-rollup/-/gulp-better-rollup-3.1.0.tgz#b226ba0c672882075472158b82d22ba9976d4ecb" +gulp-better-rollup@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/gulp-better-rollup/-/gulp-better-rollup-3.4.0.tgz#a66094de51044e73472639e6d7c84e70a71fdfac" + integrity sha512-x43aG/5jj26qJdfvvCFJ1R+w6oNEuiTxmxkTiq0Oh3jpO0DsoF6c4t0L7oyyNQ6avlDxPRj8QQF+Lwj6YAIPXQ== dependencies: lodash.camelcase "^4.3.0" - plugin-error "^0.1.2" - rollup ">=0.48 <0.57" + plugin-error "^1.0.1" + rollup "^0.66.0" vinyl "^2.1.0" vinyl-sourcemaps-apply "^0.2.1" -gulp-clean-css@^3.9.4: - version "3.9.4" - resolved "https://registry.yarnpkg.com/gulp-clean-css/-/gulp-clean-css-3.9.4.tgz#c6d3f8bb7a600fbe661962a72348a330954d343b" +gulp-clean-css@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/gulp-clean-css/-/gulp-clean-css-4.0.0.tgz#1b67f1636e2b0da73499a7602396a0d570eb9626" + integrity sha512-/Hs+dmclQfFBSpwrAKd4wTVsahJvrVIg2ga0J7Eo7DKVTVfJrM7wXlfU1mK9iJ9Y7OmkO/YstZVtmhfAKzZ00g== dependencies: - clean-css "4.1.11" + clean-css "4.2.1" plugin-error "1.0.1" - through2 "2.0.3" + through2 "3.0.0" vinyl-sourcemaps-apply "0.2.1" +gulp-cli@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.0.1.tgz#7847e220cb3662f2be8a6d572bf14e17be5a994b" + integrity sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ== + dependencies: + ansi-colors "^1.0.1" + archy "^1.0.0" + array-sort "^1.0.0" + color-support "^1.1.3" + concat-stream "^1.6.0" + copy-props "^2.0.1" + fancy-log "^1.3.2" + gulplog "^1.0.0" + interpret "^1.1.0" + isobject "^3.0.1" + liftoff "^2.5.0" + matchdep "^2.0.0" + mute-stdout "^1.0.0" + pretty-hrtime "^1.0.0" + replace-homedir "^1.0.0" + semver-greatest-satisfied-range "^1.1.0" + v8flags "^3.0.1" + yargs "^7.1.0" + gulp-concat@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" + integrity sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M= dependencies: concat-with-sourcemaps "^1.0.0" through2 "^2.0.0" @@ -3019,35 +3311,61 @@ gulp-concat@^2.6.1: gulp-filter@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" + integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= dependencies: multimatch "^2.0.0" plugin-error "^0.1.2" streamfilter "^1.0.5" +gulp-header@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-2.0.7.tgz#07505740eb432e8d2bb2af68744858dabaaf491b" + integrity sha512-qppGkYGQZnt/mRJiiR5wYZIUwNUn47Xpg4+6tHYDVeAW5IDLbHBQwbw7axfMLWGE+gKQpB+yXLeslHMw1/Haog== + dependencies: + concat-with-sourcemaps "^1.1.0" + lodash.template "^4.4.0" + map-stream "0.0.7" + through2 "^2.0.0" + gulp-open@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/gulp-open/-/gulp-open-3.0.1.tgz#a2f747b4aa31abec9399b527158b0368c57e2102" + integrity sha512-dohokw+npnt48AsD0hhvCLEHLnDMqM35F+amvIfJlX1H2nNHYUClR0Oy1rI0TvbL1/pHiHGNLmohhk+kvwIKjA== dependencies: colors "^1.1.2" opn "5.2.0" plugin-log "^0.1.0" through2 "^2.0.1" -gulp-rename@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817" +gulp-postcss@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/gulp-postcss/-/gulp-postcss-8.0.0.tgz#8d3772cd4d27bca55ec8cb4c8e576e3bde4dc550" + integrity sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg== + dependencies: + fancy-log "^1.3.2" + plugin-error "^1.0.1" + postcss "^7.0.2" + postcss-load-config "^2.0.0" + vinyl-sourcemaps-apply "^0.2.1" -gulp-replace@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066" +gulp-rename@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd" + integrity sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg== + +gulp-replace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-1.0.0.tgz#b32bd61654d97b8d78430a67b3e8ce067b7c9143" + integrity sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw== dependencies: - istextorbinary "1.0.2" + istextorbinary "2.2.1" readable-stream "^2.0.1" replacestream "^4.0.0" gulp-s3@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/gulp-s3/-/gulp-s3-0.11.0.tgz#9e302b5645206e217a525d20befa1ed293442492" + integrity sha1-njArVkUgbiF6Ul0gvvoe0pNEJJI= dependencies: async "" event-stream "*" @@ -3055,9 +3373,10 @@ gulp-s3@^0.11.0: knox "" mime "~1.2.11" -gulp-sass@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9" +gulp-sass@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.2.tgz#cfb1e3eff2bd9852431c7ce87f43880807d8d505" + integrity sha512-q8psj4+aDrblJMMtRxihNBdovfzGrXJp1l4JU0Sz4b/Mhsi2DPrKFYCGDwjIWRENs04ELVHxdOJQ7Vs98OFohg== dependencies: chalk "^2.3.0" lodash.clonedeep "^4.3.2" @@ -3071,6 +3390,7 @@ gulp-sass@^4.0.1: gulp-size@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/gulp-size/-/gulp-size-3.0.0.tgz#cb1ac8e6ba83dede52430c47fd039324f003ff82" + integrity sha1-yxrI5rqD3t5SQwxH/QOTJPAD/4I= dependencies: chalk "^2.3.0" fancy-log "^1.3.2" @@ -3083,6 +3403,7 @@ gulp-size@^3.0.0: gulp-sourcemaps@^2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz#cbb2008450b1bcce6cd23bf98337be751bf6e30a" + integrity sha1-y7IAhFCxvM5s0jv5gze+dRv24wo= dependencies: "@gulp-sourcemaps/identity-map" "1.X" "@gulp-sourcemaps/map-sources" "1.X" @@ -3096,35 +3417,39 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-svgmin@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/gulp-svgmin/-/gulp-svgmin-1.2.4.tgz#a4aa9e2615cf1105ef555aea86e86296cc20e273" +gulp-svgmin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/gulp-svgmin/-/gulp-svgmin-2.1.0.tgz#0d8a585c5369d1e77273965a629afddf23e430ff" + integrity sha512-Borxf8zucgfqF+bzJDz10YDkAS9zhKVHf/FhgHdjgD4+PnvyETCJWaeumg7j8ilCdAJsoMs8dS9TpHwI2hfbUQ== dependencies: - gulp-util "^3.0.4" - svgo "^0.7.0" + plugin-error "^1.0.1" + svgo "^1.1.1" -gulp-svgstore@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/gulp-svgstore/-/gulp-svgstore-6.1.1.tgz#7fa8af005c23bb0338f9f365a6010c86651f13d0" +gulp-svgstore@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/gulp-svgstore/-/gulp-svgstore-7.0.1.tgz#885b9bb911bded726129a5594d3b3528c94ea423" + integrity sha512-oiAXvkRnBBt6ZML+lit7W15ryClB45k0V9eCVW/i73EymunoQlzZal0Luj3NDrbPLbPIllL8/ltCXFa9Jv03Pg== dependencies: cheerio "0.*" fancy-log "^1.3.2" plugin-error "^0.1.2" vinyl "^2.1.0" -gulp-uglify-es@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gulp-uglify-es/-/gulp-uglify-es-1.0.1.tgz#9f991de31c646fb37fe589086ffd3f6e2f9e20f1" +gulp-uglify-es@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/gulp-uglify-es/-/gulp-uglify-es-1.0.4.tgz#59ee0d5ea98c1e09c6eaa58c8b018a6ad33f48d4" + integrity sha512-UMRufZsBmQizCYpftutaiVoLswpbzFEfY90EJLU4YlTgculeHnanb794s88TMd5tpCZVC638sAX6JrLVYTP/Wg== dependencies: o-stream "^0.2.2" plugin-error "^1.0.1" - uglify-es "^3.3.9" + terser "^3.7.5" vinyl "^2.1.0" vinyl-sourcemaps-apply "^0.2.1" -gulp-util@^3.0.0, gulp-util@^3.0.4, gulp-util@^3.0.8: +gulp-util@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= dependencies: array-differ "^1.0.0" array-uniq "^1.0.2" @@ -3148,6 +3473,7 @@ gulp-util@^3.0.0, gulp-util@^3.0.4, gulp-util@^3.0.8: gulp-util@~2.2.6: version "2.2.20" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" + integrity sha1-1xRuVyiRC9jwR6awseVJvCLb1kw= dependencies: chalk "^0.5.0" dateformat "^1.0.7-1.2.3" @@ -3158,33 +3484,27 @@ gulp-util@~2.2.6: through2 "^0.5.0" vinyl "^0.2.1" -gulp@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" +gulp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.0.tgz#95766c601dade4a77ed3e7b2b6dc03881b596366" + integrity sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y= dependencies: - archy "^1.0.0" - chalk "^1.0.0" - deprecated "^0.0.1" - gulp-util "^3.0.0" - interpret "^1.0.0" - liftoff "^2.1.0" - minimist "^1.1.0" - orchestrator "^0.3.0" - pretty-hrtime "^1.0.0" - semver "^4.1.0" - tildify "^1.0.0" - v8flags "^2.0.2" - vinyl-fs "^0.3.0" + glob-watcher "^5.0.0" + gulp-cli "^2.0.0" + undertaker "^1.0.0" + vinyl-fs "^3.0.0" gulplog@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= dependencies: glogg "^1.0.0" gzip-size@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-4.1.0.tgz#8ae096257eabe7d69c45be2b67c448124ffb517c" + integrity sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw= dependencies: duplexer "^0.1.1" pify "^3.0.0" @@ -3192,56 +3512,61 @@ gzip-size@^4.1.0: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: - ajv "^5.1.0" + ajv "^6.5.5" har-schema "^2.0.0" has-ansi@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" + integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= dependencies: ansi-regex "^0.2.0" has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= dependencies: sparkles "^1.0.0" -has-unicode@^2.0.0, has-unicode@~2.0.1: +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3250,6 +3575,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3258,157 +3584,134 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" + function-bind "^1.1.1" homedir-polyfill@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= dependencies: parse-passwd "^1.0.0" -hosted-git-info@^2.1.4, hosted-git-info@^2.4.2, hosted-git-info@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" +hosted-git-info@^2.1.4, hosted-git-info@^2.5.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== html-tags@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" + integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= -htmlparser2@^3.9.1, htmlparser2@^3.9.2: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" +htmlparser2@^3.10.0, htmlparser2@^3.9.1, htmlparser2@^3.9.2: + version "3.10.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" + integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== dependencies: domelementtype "^1.3.0" domhandler "^2.3.0" domutils "^1.5.1" entities "^1.1.1" inherits "^2.0.1" - readable-stream "^2.0.2" - -http-cache-semantics@^3.8.0, http-cache-semantics@^3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - -http-proxy-agent@^2.0.0, http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - dependencies: - agent-base "4" - debug "3.1.0" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" + readable-stream "^3.0.6" http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^2.1.0, https-proxy-agent@^2.2.0, https-proxy-agent@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" +iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: - agent-base "^4.1.0" - debug "^3.1.0" + safer-buffer ">= 2.1.2 < 3" -humanize-ms@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: - ms "^2.0.0" + minimatch "^3.0.4" -iconv-lite@^0.4.17: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +ignore@^3.2.0, ignore@^3.3.3, ignore@^3.3.5: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -iconv-lite@~0.4.13: - version "0.4.21" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.21.tgz#c47f8733d02171189ebc4a400f3218d348094798" - dependencies: - safer-buffer "^2.1.0" +ignore@^4.0.3, ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" +ignore@^5.0.4: + version "5.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" + integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== -iferr@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.0.tgz#36700e6a6d5d42e3e66b6d90fb55a018970b0aab" +import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= + dependencies: + import-from "^2.1.0" -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= dependencies: - minimatch "^3.0.4" + caller-path "^2.0.0" + resolve-from "^3.0.0" -ignore@^3.3.3, ignore@^3.3.5: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" +import-fresh@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" + integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + integrity sha1-M1238qev/VOqpHHUuAId7ja387E= + dependencies: + resolve-from "^3.0.0" import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= import-lazy@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" + integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== import-local@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/import-local/-/import-local-0.1.1.tgz#b1179572aacdc11c6a91009fb430dbcab5f668a8" + integrity sha1-sReVcqrNwRxqkQCftDDbyrX2aKg= dependencies: pkg-dir "^2.0.0" resolve-cwd "^2.0.0" @@ -3416,60 +3719,52 @@ import-local@^0.1.1: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= in-publish@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= dependencies: repeating "^2.0.0" indent-string@^3.0.0, indent-string@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -inflight@^1.0.4, inflight@~1.0.6: +inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" -inherits@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" - inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - -init-package-json@^1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" - dependencies: - glob "^7.1.1" - npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" - promzard "^0.3.0" - read "~1.0.1" - read-package-json "1 || 2" - semver "2.x || 3.x || 4 || 5" - validate-npm-package-license "^3.0.1" - validate-npm-package-name "^3.0.0" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3486,31 +3781,46 @@ inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" -interpret@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +inquirer@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" + integrity sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.0" + figures "^2.0.0" + lodash "^4.17.10" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.1.0" + string-width "^2.1.0" + strip-ansi "^5.0.0" + through "^2.3.6" -invariant@^2.2.0, invariant@^2.2.2: +interpret@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - -ip@^1.1.4, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== dependencies: is-relative "^1.0.0" is-windows "^1.0.1" @@ -3518,26 +3828,31 @@ is-absolute@^1.0.0: is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-alphabetical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.1.tgz#c77079cc91d4efac775be1034bf2d243f95e6f08" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" + integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg== is-alphanumeric@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" + integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ= is-alphanumerical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" + integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg== dependencies: is-alphabetical "^1.0.0" is-decimal "^1.0.0" @@ -3545,48 +3860,72 @@ is-alphanumerical@^1.0.0: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" is-buffer@^1.1.4, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" -is-ci@^1.0.10: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" - dependencies: - ci-info "^1.0.0" +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== -is-cidr@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-2.0.5.tgz#13227927d71865d1177fe0e5b60e6ddd3dee0034" +is-ci@^1.0.10: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== dependencies: - cidr-regex "^2.0.8" + ci-info "^1.5.0" is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" -is-decimal@^1.0.0: +is-date-object@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.1.tgz#f5fb6a94996ad9e8e3761fbfbd091f1fca8c4e82" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-decimal@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" + integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg== is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -3595,6 +3934,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -3603,76 +3943,101 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-empty@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-empty/-/is-empty-1.2.0.tgz#de9bb5b278738a05a0b09a57e1fb4d4a341a9f6b" + integrity sha1-3pu1snhzigWgsJpX4ftNSjQan2s= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" + integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A== + +is-hidden@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-hidden/-/is-hidden-1.1.1.tgz#82ee6a93aeef3fb007ad5b9457c0584d45329f38" + integrity sha512-175UKecS8+U4hh2PSY0j4xnm2GKYzvSKnbh+naC93JjuBA7LgIo6YxlbcsSo6seFBdQO3RuIcH980yvqqD/2cA== is-installed-globally@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= dependencies: global-dirs "^0.1.0" is-path-inside "^1.0.0" @@ -3680,304 +4045,372 @@ is-installed-globally@^0.1.0: is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= -is-my-ip-valid@^1.0.0: +is-negated-glob@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.12.4: - version "2.17.2" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= -is-odd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" - dependencies: - is-number "^4.0.0" +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-relative@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== dependencies: is-unc-path "^1.0.0" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-supported-regexp-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca" + integrity sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ== + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-unc-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== dependencies: unc-path-regex "^0.1.2" -is-utf8@^0.2.0: +is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= is-whitespace-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" + integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ== is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-word-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" + integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA== is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istextorbinary@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf" +istextorbinary@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" + integrity sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw== dependencies: - binaryextensions "~1.0.0" - textextensions "~1.0.0" + binaryextensions "2" + editions "^1.3.3" + textextensions "2" js-base64@^2.1.8, js-base64@^2.1.9: - version "2.4.3" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582" + version "2.5.1" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== + +js-levenshtein@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.0, js-tokens@^3.0.2: +js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@^3.9.0, js-yaml@^3.9.1: - version "3.11.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" +js-yaml@^3.12.0, js-yaml@^3.6.1, js-yaml@^3.9.0, js-yaml@^3.9.1: + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== dependencies: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - -json-parse-better-errors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" +json5@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" json-schema "0.2.3" verror "1.10.0" +just-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" + integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= + kind-of@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0: +kind-of@^5.0.0, kind-of@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +known-css-properties@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" + integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== known-css-properties@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.5.0.tgz#6ff66943ed4a5b55657ee095779a91f4536f8084" - -known-css-properties@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.6.1.tgz#31b5123ad03d8d1a3f36bd4155459c981173478b" + integrity sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA== knox@: version "0.9.2" resolved "https://registry.yarnpkg.com/knox/-/knox-0.9.2.tgz#3736593669e24f024fdaf723b6a1dc4afd839a71" + integrity sha1-NzZZNmniTwJP2vcjtqHcSv2DmnE= dependencies: debug "^1.0.2" mime "*" @@ -3985,70 +4418,64 @@ knox@: stream-counter "^1.0.0" xml2js "^0.4.4" +last-run@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" + integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= + dependencies: + default-resolution "^2.0.0" + es6-weak-map "^2.0.1" + latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= dependencies: package-json "^4.0.0" -lazy-property@~1.0.0: +lazystream@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + +leven@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= + +levenshtein-edit-distance@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/levenshtein-edit-distance/-/levenshtein-edit-distance-1.0.0.tgz#895baf478cce8b5c1a0d27e45d7c1d978a661e49" + integrity sha1-iVuvR4zOi1waDSfkXXwdl4pmHkk= + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -libcipm@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-1.6.2.tgz#5a9d83b8606b9733cfff016ad9b37d3b8198ae09" - dependencies: - bin-links "^1.1.0" - bluebird "^3.5.1" - find-npm-prefix "^1.0.2" - graceful-fs "^4.1.11" - lock-verify "^2.0.0" - npm-lifecycle "^2.0.0" - npm-logical-tree "^1.2.1" - npm-package-arg "^6.0.0" - pacote "^7.5.1" - protoduck "^5.0.0" - read-package-json "^2.0.12" - rimraf "^2.6.2" - worker-farm "^1.5.4" - -libnpmhook@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-4.0.1.tgz#63641654de772cbeb96a88527a7fd5456ec3c2d7" - dependencies: - figgy-pudding "^3.1.0" - npm-registry-fetch "^3.0.0" - -libnpx@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.0.tgz#1bf4a1c9f36081f64935eb014041da10855e3102" - dependencies: - dotenv "^5.0.1" - npm-package-arg "^6.0.0" - rimraf "^2.6.2" - safe-buffer "^5.1.0" - update-notifier "^2.3.0" - which "^1.3.0" - y18n "^4.0.0" - yargs "^11.0.0" - -liftoff@^2.1.0: +liftoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= dependencies: extend "^3.0.0" findup-sync "^2.0.0" @@ -4062,6 +4489,7 @@ liftoff@^2.1.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4072,6 +4500,7 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4081,149 +4510,165 @@ load-json-file@^2.0.0: load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" pify "^3.0.0" strip-bom "^3.0.0" -loadjs@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/loadjs/-/loadjs-3.5.4.tgz#ef0f4eb5a6ac2b86c7597a3d4de97b83816e36b8" +load-plugin@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/load-plugin/-/load-plugin-2.3.0.tgz#577b6a956b344fd2ae80d8ecff5944febeea8eb7" + integrity sha512-OxHNMfT3aeHFSpzeMQRcE40kXULv3KA8fGgnySC+rO3Be+0oMWkcRKMJ5zWzUCTuUnabCsQyJzNjo/BLdbmRxA== + dependencies: + npm-prefix "^1.2.0" + resolve-from "^4.0.0" + +loadjs@^3.5.5: + version "3.5.5" + resolved "https://registry.yarnpkg.com/loadjs/-/loadjs-3.5.5.tgz#2fbaa981ffdd079e0f8786ea75aeed643483b368" + integrity sha512-qBuLnKt4C6+vctutozFqPHQ6s4SSa9tcE64NsvDJ92UZmUrFvqGI1oVOtnZz2xwpgOT+2niQtHtQIDP4e/wlTA== locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" -lock-verify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.0.1.tgz#6d671eea60b459c6048b3b26b62959208be67682" - dependencies: - npm-package-arg "^5.1.2" - semver "^5.4.1" - -lockfile@~1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" - dependencies: - signal-exit "^3.0.2" - lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= lodash._basetostring@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._baseuniq@~4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" - dependencies: - lodash._createset "~4.0.0" - lodash._root "~3.0.0" + integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= lodash._basevalues@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - -lodash._createset@~4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= lodash._escapehtmlchar@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" + integrity sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0= dependencies: lodash._htmlescapes "~2.4.1" lodash._escapestringchar@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" + integrity sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I= lodash._getnative@^3.0.0: version "3.9.1" resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= lodash._htmlescapes@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" + integrity sha1-MtFL8IRLbeb4tioFG09nwii2JMs= lodash._isiterateecall@^3.0.0: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= lodash._isnative@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" + integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw= lodash._objecttypes@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" + integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE= lodash._reescape@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= lodash._reevaluate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" + integrity sha1-TxInqlqHEfxjL1sHofRgequLMiI= -lodash._reinterpolate@^3.0.0: +lodash._reinterpolate@^3.0.0, lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= lodash._reunescapedhtml@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" + integrity sha1-dHxPxAED6zu4oJduVx96JlnpO6c= dependencies: lodash._htmlescapes "~2.4.1" lodash.keys "~2.4.1" -lodash._root@^3.0.0, lodash._root@~3.0.0: +lodash._root@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= lodash._shimkeys@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" + integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM= dependencies: lodash._objecttypes "~2.4.1" lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.clonedeep@^4.3.2, lodash.clonedeep@~4.5.0: +lodash.clonedeep@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= lodash.defaults@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" + integrity sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ= dependencies: lodash._objecttypes "~2.4.1" lodash.keys "~2.4.1" @@ -4231,12 +4676,14 @@ lodash.defaults@~2.4.1: lodash.escape@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= dependencies: lodash._root "^3.0.0" lodash.escape@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" + integrity sha1-LOEsXghNsKV92l5dHu659dF1o7Q= dependencies: lodash._escapehtmlchar "~2.4.1" lodash._reunescapedhtml "~2.4.1" @@ -4245,32 +4692,39 @@ lodash.escape@~2.4.1: lodash.filter@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= lodash.flatten@^4.2.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= lodash.isobject@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" + integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU= dependencies: lodash._objecttypes "~2.4.1" lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= dependencies: lodash._getnative "^3.0.0" lodash.isarguments "^3.0.0" @@ -4279,6 +4733,7 @@ lodash.keys@^3.0.0: lodash.keys@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" + integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc= dependencies: lodash._isnative "~2.4.1" lodash._shimkeys "~2.4.1" @@ -4287,38 +4742,47 @@ lodash.keys@~2.4.1: lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= lodash.merge@^4.4.0, lodash.merge@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" + integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ== lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" + integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ== lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= lodash.reduce@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= lodash.template@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" + integrity sha1-nmEQB+32KRKal0qzxIuBez4c8g0= dependencies: lodash._escapestringchar "~2.4.1" lodash._reinterpolate "~2.4.1" @@ -4331,6 +4795,7 @@ lodash.template@^2.4.1: lodash.template@^3.0.0: version "3.6.2" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= dependencies: lodash._basecopy "^3.0.0" lodash._basetostring "^3.0.0" @@ -4342,16 +4807,33 @@ lodash.template@^3.0.0: lodash.restparam "^3.0.0" lodash.templatesettings "^3.0.0" +lodash.template@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" + integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= + dependencies: + lodash._reinterpolate "~3.0.0" + lodash.templatesettings "^4.0.0" + lodash.templatesettings@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= dependencies: lodash._reinterpolate "^3.0.0" lodash.escape "^3.0.0" +lodash.templatesettings@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" + integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= + dependencies: + lodash._reinterpolate "~3.0.0" + lodash.templatesettings@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" + integrity sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk= dependencies: lodash._reinterpolate "~2.4.1" lodash.escape "~2.4.1" @@ -4359,46 +4841,31 @@ lodash.templatesettings@~2.4.1: lodash.unescape@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" - -lodash.union@~4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" - -lodash.uniq@~4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= lodash.values@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" + integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ= dependencies: lodash.keys "~2.4.1" -lodash.without@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" - -lodash@>=3.10.0, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" - -lodash@^3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - -lodash@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" +lodash@>=3.10.0, lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== -log-symbols@^2.0.0: +log-symbols@^2.0.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" loglevel-colored-level-prefix@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz#6a40218fdc7ae15fc76c3d0f3e676c465388603e" + integrity sha1-akAhj9x64V/HbD0PPmdsRlOIYD4= dependencies: chalk "^1.1.3" loglevel "^1.4.1" @@ -4406,35 +4873,37 @@ loglevel-colored-level-prefix@^1.0.0: loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" + integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= longest-streak@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" + integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA== loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: - js-tokens "^3.0.0" + js-tokens "^3.0.0 || ^4.0.0" loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= dependencies: currently-unhandled "^0.4.1" signal-exit "^3.0.0" lowercase-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f" +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4442,142 +4911,142 @@ lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" -magic-string@^0.22.4: - version "0.22.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" +magic-string@^0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.1.tgz#b1c248b399cd7485da0fe7385c2fc7011843266e" + integrity sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg== dependencies: - vlq "^0.2.2" + sourcemap-codec "^1.4.1" make-dir@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b" + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" -make-fetch-happen@^2.5.0, make-fetch-happen@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-2.6.0.tgz#8474aa52198f6b1ae4f3094c04e8370d35ea8a38" - dependencies: - agentkeepalive "^3.3.0" - cacache "^10.0.0" - http-cache-semantics "^3.8.0" - http-proxy-agent "^2.0.0" - https-proxy-agent "^2.1.0" - lru-cache "^4.1.1" - mississippi "^1.2.0" - node-fetch-npm "^2.0.2" - promise-retry "^1.1.1" - socks-proxy-agent "^3.0.1" - ssri "^5.0.0" - -make-fetch-happen@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-3.0.0.tgz#7b661d2372fc4710ab5cc8e1fa3c290eea69a961" - dependencies: - agentkeepalive "^3.4.1" - cacache "^10.0.4" - http-cache-semantics "^3.8.1" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.0" - lru-cache "^4.1.2" - mississippi "^3.0.0" - node-fetch-npm "^2.0.2" - promise-retry "^1.1.1" - socks-proxy-agent "^3.0.1" - ssri "^5.2.4" - -make-fetch-happen@^4.0.0, make-fetch-happen@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" - dependencies: - agentkeepalive "^3.4.1" - cacache "^11.0.1" - http-cache-semantics "^3.8.1" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" - mississippi "^3.0.0" - node-fetch-npm "^2.0.2" - promise-retry "^1.1.1" - socks-proxy-agent "^4.0.0" - ssri "^6.0.0" - make-iterator@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b" + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== dependencies: - kind-of "^3.1.0" + kind-of "^6.0.2" map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" +map-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" + integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" markdown-escapes@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" + version "1.0.2" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" + integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA== -markdown-table@^1.1.0: +markdown-extensions@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.1.tgz#4b3dd3a133d1518b8ef0dbc709bf2a1b4824bc8c" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" + integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== + +markdown-table@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786" + integrity sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw== + +matchdep@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" + integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= + dependencies: + findup-sync "^2.0.0" + micromatch "^3.0.4" + resolve "^1.4.0" + stack-trace "0.0.10" + +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== mathml-tag-names@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578" + version "2.1.0" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz#490b70e062ee24636536e3d9481e333733d00f2c" + integrity sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg== mdast-util-compact@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" + version "1.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz#c12ebe16fffc84573d3e19767726de226e95f649" + integrity sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg== dependencies: - unist-util-modify-children "^1.0.0" unist-util-visit "^1.1.0" -meant@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" +mdast-util-definitions@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz#49f936b09207c45b438db19551652934312f04f0" + integrity sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g== + dependencies: + unist-util-visit "^1.0.0" + +mdast-util-to-string@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz#3552b05428af22ceda34f156afe62ec8e6d731ca" + integrity sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A== + +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memoizee@0.4.X: - version "0.4.12" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.12.tgz#780e99a219c50c549be6d0fc61765080975c58fb" + version "0.4.14" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" - es5-ext "^0.10.30" + es5-ext "^0.10.45" es6-weak-map "^2.0.2" event-emitter "^0.3.5" is-promise "^2.1" lru-queue "0.1" next-tick "1" - timers-ext "^0.1.2" + timers-ext "^0.1.5" meow@^3.3.0, meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= dependencies: camelcase-keys "^2.0.0" decamelize "^1.1.2" @@ -4591,8 +5060,9 @@ meow@^3.3.0, meow@^3.7.0: trim-newlines "^1.0.0" meow@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.0.tgz#fd5855dd008db5b92c552082db1c307cba20b29d" + version "4.0.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975" + integrity sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A== dependencies: camelcase-keys "^4.0.0" decamelize-keys "^1.0.0" @@ -4604,13 +5074,30 @@ meow@^4.0.0: redent "^2.0.0" trim-newlines "^2.0.0" -merge2@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.1.tgz#271d2516ff52d4af7f7b710b8bf3e16e183fef66" +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + +merge2@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" + integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4626,27 +5113,10 @@ micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.4: - version "3.1.9" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -micromatch@^3.1.8: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4662,50 +5132,44 @@ micromatch@^3.1.8: snapdragon "^0.8.1" to-regex "^3.0.2" -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" + integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== dependencies: - mime-db "~1.33.0" + mime-db "~1.37.0" mime@*: - version "2.2.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.2.0.tgz#161e541965551d3b549fa1114391e3a3d55b923b" + version "2.4.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" + integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w== mime@~1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" + integrity sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA= mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - dependencies: - brace-expansion "^1.0.0" - -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - minimist-options@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" @@ -4713,112 +5177,67 @@ minimist-options@^3.0.1: minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@1.1.x: version "1.1.3" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" + integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= minimist@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" + integrity sha1-Tf/lJdriuGTGbC4jxicdev3s784= minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minipass@^2.2.1, minipass@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.2.4.tgz#03c824d84551ec38a8d1bb5bc350a5a30a354a40" +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: - safe-buffer "^5.1.1" + safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== dependencies: minipass "^2.2.1" -mississippi@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.1.tgz#2a8bb465e86550ac8b36a7b6f45599171d78671e" - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^1.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mississippi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^2.0.1" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.0.0: +ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multimatch@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" + integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= dependencies: array-differ "^1.0.0" array-union "^1.0.1" @@ -4828,27 +5247,35 @@ multimatch@^2.0.0: multipipe@^0.1.0, multipipe@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= dependencies: duplexer2 "0.0.2" -mute-stream@0.0.7, mute-stream@~0.0.4: +mute-stdout@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" + integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== + +mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" +nan@^2.10.0, nan@^2.9.2: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== nanomatch@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" define-property "^2.0.2" extend-shallow "^3.0.2" fragment-cache "^0.2.1" - is-odd "^2.0.0" is-windows "^1.0.2" kind-of "^6.0.2" object.pick "^1.3.0" @@ -4856,47 +5283,75 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -natives@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.3.tgz#44a579be64507ea2d6ed1ca04a9415915cf75558" - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +needle@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= -node-fetch-npm@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" - dependencies: - encoding "^0.1.11" - json-parse-better-errors "^1.0.0" - safe-buffer "^5.1.1" +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-gyp@^3.3.1, node-gyp@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" +node-gyp@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" + integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== dependencies: fstream "^1.0.0" glob "^7.0.3" graceful-fs "^4.1.2" - minimatch "^3.0.2" mkdirp "^0.5.0" nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" osenv "0" - request "2" + request "^2.87.0" rimraf "2" semver "~5.3.0" tar "^2.0.0" which "1" +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.3.tgz#aad9ce0dcb98129c753f772c0aa01360fb90fbd2" + integrity sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ== + dependencies: + semver "^5.3.0" + node-sass@^4.8.3: - version "4.8.3" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.8.3.tgz#d077cc20a08ac06f661ca44fb6f19cd2ed41debb" + version "4.11.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a" + integrity sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -4911,9 +5366,9 @@ node-sass@^4.8.3: meow "^3.7.0" mkdirp "^0.5.1" nan "^2.10.0" - node-gyp "^3.3.1" + node-gyp "^3.8.0" npmlog "^4.0.0" - request "~2.79.0" + request "^2.88.0" sass-graph "^2.2.4" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -4921,19 +5376,22 @@ node-sass@^4.8.3: "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" -nopt@~4.0.1: +nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -4943,323 +5401,166 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package- normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-selector@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -npm-audit-report@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.0.5.tgz#f16fa7c61459dd660913509685193148ce2cd85f" +now-and-later@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" + integrity sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4= dependencies: - ansicolors "^0.3.2" - ansistyles "^0.1.3" - cli-table2 "^0.2.0" + once "^1.3.2" npm-bundled@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" - -npm-cache-filename@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" - -npm-install-checks@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7" - dependencies: - semver "^2.3.0 || 3.x || 4 || 5" - -npm-lifecycle@^2.0.0, npm-lifecycle@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.0.1.tgz#897313f05ed24db8e28d99fa8b42c31b625e6237" - dependencies: - byline "^5.0.0" - graceful-fs "^4.1.11" - node-gyp "^3.6.2" - resolve-from "^4.0.0" - slide "^1.1.6" - uid-number "0.0.6" - umask "^1.1.0" - which "^1.3.0" - -npm-logical-tree@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" - -"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" - dependencies: - hosted-git-info "^2.6.0" - osenv "^0.1.5" - semver "^5.5.0" - validate-npm-package-name "^3.0.0" - -npm-package-arg@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-5.1.2.tgz#fb18d17bb61e60900d6312619919bd753755ab37" - dependencies: - hosted-git-info "^2.4.2" - osenv "^0.1.4" - semver "^5.1.0" - validate-npm-package-name "^3.0.0" + version "1.0.5" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== -npm-packlist@^1.1.10, npm-packlist@~1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" +npm-packlist@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.2.0.tgz#55a60e793e272f00862c7089274439a4cc31fc7f" + integrity sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-pick-manifest@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.1.0.tgz#dc381bdd670c35d81655e1d5a94aa3dd4d87fce5" - dependencies: - npm-package-arg "^6.0.0" - semver "^5.4.1" - -npm-profile@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-3.0.1.tgz#65a1018340f14399a086b5d0a9bd0d13145d8e57" - dependencies: - aproba "^1.1.2" - make-fetch-happen "^2.5.0" - -npm-registry-client@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.5.1.tgz#8115809c0a4b40938b8a109b8ea74d26c6f5d7f1" - dependencies: - concat-stream "^1.5.2" - graceful-fs "^4.1.6" - normalize-package-data "~1.0.1 || ^2.0.0" - npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - once "^1.3.3" - request "^2.74.0" - retry "^0.10.0" - safe-buffer "^5.1.1" - semver "2 >=2.2.1 || 3.x || 4 || 5" - slide "^1.1.3" - ssri "^5.2.4" - optionalDependencies: - npmlog "2 || ^3.1.0 || ^4.0.0" - -npm-registry-fetch@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-1.1.1.tgz#710bc5947d9ee2c549375072dab6d5d17baf2eb2" - dependencies: - bluebird "^3.5.1" - figgy-pudding "^3.0.0" - lru-cache "^4.1.2" - make-fetch-happen "^3.0.0" - npm-package-arg "^6.0.0" - safe-buffer "^5.1.1" - -npm-registry-fetch@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.1.1.tgz#e96bae698afdd45d4a01aca29e881fc0bc55206c" +npm-prefix@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/npm-prefix/-/npm-prefix-1.2.0.tgz#e619455f7074ba54cc66d6d0d37dd9f1be6bcbc0" + integrity sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A= dependencies: - bluebird "^3.5.1" - figgy-pudding "^3.1.0" - lru-cache "^4.1.2" - make-fetch-happen "^4.0.0" - npm-package-arg "^6.0.0" + rc "^1.1.0" + shellsubstitute "^1.1.0" + untildify "^2.1.0" npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" -npm-user-validate@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" - -npm@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/npm/-/npm-6.0.0.tgz#f5518c860ab91586db2a24aad4de1433cda108d9" - dependencies: - JSONStream "^1.3.2" - abbrev "~1.1.1" - ansi-regex "~3.0.0" - ansicolors "~0.3.2" - ansistyles "~0.1.3" - aproba "~1.2.0" - archy "~1.0.0" - bin-links "^1.1.2" - bluebird "~3.5.1" - byte-size "^4.0.2" - cacache "^11.0.1" - call-limit "~1.1.0" - chownr "~1.0.1" - cli-columns "^3.1.2" - cli-table2 "~0.2.0" - cmd-shim "~2.0.2" - columnify "~1.5.4" - config-chain "~1.1.11" - detect-indent "~5.0.0" - detect-newline "^2.1.0" - dezalgo "~1.0.3" - editor "~1.0.0" - figgy-pudding "^3.1.0" - find-npm-prefix "^1.0.2" - fs-vacuum "~1.2.10" - fs-write-stream-atomic "~1.0.10" - gentle-fs "^2.0.1" - glob "~7.1.2" - graceful-fs "~4.1.11" - has-unicode "~2.0.1" - hosted-git-info "^2.6.0" - iferr "^1.0.0" - inflight "~1.0.6" - inherits "~2.0.3" - ini "^1.3.5" - init-package-json "^1.10.3" - is-cidr "^2.0.5" - json-parse-better-errors "^1.0.2" - lazy-property "~1.0.0" - libcipm "^1.6.2" - libnpmhook "^4.0.1" - libnpx "^10.2.0" - lockfile "~1.0.3" - lodash._baseuniq "~4.6.0" - lodash.clonedeep "~4.5.0" - lodash.union "~4.6.0" - lodash.uniq "~4.5.0" - lodash.without "~4.4.0" - lru-cache "^4.1.2" - meant "~1.0.1" - mississippi "^3.0.0" - mkdirp "~0.5.1" - move-concurrently "^1.0.1" - node-gyp "^3.6.2" - nopt "~4.0.1" - normalize-package-data "~2.4.0" - npm-audit-report "^1.0.5" - npm-cache-filename "~1.0.2" - npm-install-checks "~3.0.0" - npm-lifecycle "^2.0.1" - npm-package-arg "^6.1.0" - npm-packlist "~1.1.10" - npm-pick-manifest "^2.1.0" - npm-profile "^3.0.1" - npm-registry-client "^8.5.1" - npm-registry-fetch "^1.1.0" - npm-user-validate "~1.0.0" - npmlog "~4.1.2" - once "~1.4.0" - opener "~1.4.3" - osenv "^0.1.5" - pacote "^8.1.0" - path-is-inside "~1.0.2" - promise-inflight "~1.0.1" - qrcode-terminal "^0.12.0" - query-string "^6.0.0" - qw "~1.0.1" - read "~1.0.7" - read-cmd-shim "~1.0.1" - read-installed "~4.0.3" - read-package-json "^2.0.13" - read-package-tree "^5.2.1" - readable-stream "^2.3.6" - request "^2.85.0" - retry "^0.12.0" - rimraf "~2.6.2" - safe-buffer "~5.1.1" - semver "^5.5.0" - sha "~2.0.1" - slide "~1.1.6" - sorted-object "~2.0.1" - sorted-union-stream "~2.1.3" - ssri "^6.0.0" - strip-ansi "~4.0.0" - tar "^4.4.1" - text-table "~0.2.0" - tiny-relative-date "^1.3.0" - uid-number "0.0.6" - umask "~1.1.0" - unique-filename "~1.1.0" - unpipe "~1.0.0" - update-notifier "^2.4.0" - uuid "^3.2.1" - validate-npm-package-license "^3.0.3" - validate-npm-package-name "~3.0.0" - which "~1.3.0" - worker-farm "^1.6.0" - wrappy "~1.0.2" - write-file-atomic "^2.3.0" - -"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@~4.1.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" +nth-check@^1.0.2, nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: boolbase "~1.0.0" num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= o-stream@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/o-stream/-/o-stream-0.2.2.tgz#7fe03af870b8f9537af33b312b381b3034ab410f" + integrity sha512-V3j76KU3g/Gyl8rpdi2z72rn5zguMvTCQgAXfBe3pxEefKqXmOUOD7mvx/mNjykdxGqDVfpSoo8r+WdrkWg/1Q== -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== + object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" -object.defaults@^1.1.0: +object.assign@^4.0.4, object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= dependencies: array-each "^1.0.1" array-slice "^1.0.0" for-own "^1.0.0" isobject "^3.0.0" +object.entries@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" + integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + object.map@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= dependencies: for-own "^1.0.0" make-iterator "^1.0.0" @@ -5267,6 +5568,7 @@ object.map@^1.0.0: object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -5274,40 +5576,53 @@ object.omit@^2.0.0: object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" -once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" +object.reduce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" + integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= dependencies: - wrappy "1" + for-own "^1.0.0" + make-iterator "^1.0.0" -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" +object.values@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" -opener@~1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" - opn@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225" + integrity sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ== dependencies: is-wsl "^1.1.0" optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -5316,43 +5631,43 @@ optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -orchestrator@^0.3.0: - version "0.3.8" - resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= dependencies: - end-of-stream "~0.1.5" - sequencify "~0.0.7" - stream-consume "~0.1.0" - -ordered-read-streams@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" + readable-stream "^2.0.1" os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" mem "^1.1.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.4, osenv@^0.1.5: +osenv@0, osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -5360,105 +5675,53 @@ osenv@0, osenv@^0.1.4, osenv@^0.1.5: p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" + integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= dependencies: got "^6.7.1" registry-auth-token "^3.0.1" registry-url "^3.0.3" semver "^5.1.0" -pacote@^7.5.1: - version "7.6.1" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-7.6.1.tgz#d44621c89a5a61f173989b60236757728387c094" - dependencies: - bluebird "^3.5.1" - cacache "^10.0.4" - get-stream "^3.0.0" - glob "^7.1.2" - lru-cache "^4.1.1" - make-fetch-happen "^2.6.0" - minimatch "^3.0.4" - mississippi "^3.0.0" - mkdirp "^0.5.1" - normalize-package-data "^2.4.0" - npm-package-arg "^6.0.0" - npm-packlist "^1.1.10" - npm-pick-manifest "^2.1.0" - osenv "^0.1.5" - promise-inflight "^1.0.1" - promise-retry "^1.1.1" - protoduck "^5.0.0" - rimraf "^2.6.2" - safe-buffer "^5.1.1" - semver "^5.5.0" - ssri "^5.2.4" - tar "^4.4.0" - unique-filename "^1.1.0" - which "^1.3.0" - -pacote@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-8.1.1.tgz#7ee85dad2bccf5524e5460508f833c60dddf5183" - dependencies: - bluebird "^3.5.1" - cacache "^11.0.1" - get-stream "^3.0.0" - glob "^7.1.2" - lru-cache "^4.1.2" - make-fetch-happen "^4.0.1" - minimatch "^3.0.4" - mississippi "^3.0.0" - mkdirp "^0.5.1" - normalize-package-data "^2.4.0" - npm-package-arg "^6.1.0" - npm-packlist "^1.1.10" - npm-pick-manifest "^2.1.0" - osenv "^0.1.5" - promise-inflight "^1.0.1" - promise-retry "^1.1.1" - protoduck "^5.0.0" - rimraf "^2.6.2" - safe-buffer "^5.1.1" - semver "^5.5.0" - ssri "^6.0.0" - tar "^4.4.1" - unique-filename "^1.1.0" - which "^1.3.0" - -parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" +parent-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" + integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== dependencies: - cyclist "~0.2.2" - inherits "^2.0.3" - readable-stream "^2.1.5" + callsites "^3.0.0" parse-entities@^1.0.2, parse-entities@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" + version "1.2.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4" + integrity sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g== dependencies: character-entities "^1.0.0" character-entities-legacy "^1.0.0" @@ -5470,6 +5733,7 @@ parse-entities@^1.0.2, parse-entities@^1.1.0: parse-filepath@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= dependencies: is-absolute "^1.0.0" map-cache "^0.2.0" @@ -5478,6 +5742,7 @@ parse-filepath@^1.0.1: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -5487,73 +5752,93 @@ parse-glob@^3.0.4: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parse-json@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-3.0.0.tgz#fa6f47b18e23826ead32f263e744d0e1e847fb13" + integrity sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM= dependencies: error-ex "^1.3.1" parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-node-version@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.0.tgz#33d9aa8920dcc3c0d33658ec18ce237009a56d53" + integrity sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg== + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= -path-key@^2.0.0: +path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-root-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= path-root@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= dependencies: path-root-regex "^0.1.0" path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -5562,58 +5847,67 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== dependencies: pify "^3.0.0" -pause-stream@0.0.11: +pause-stream@^0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= dependencies: through "~2.3" performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.0, pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= dependencies: find-up "^2.1.0" plugin-error@1.0.1, plugin-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" + integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== dependencies: ansi-colors "^1.0.1" arr-diff "^4.0.0" @@ -5623,6 +5917,7 @@ plugin-error@1.0.1, plugin-error@^1.0.1: plugin-error@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= dependencies: ansi-cyan "^0.1.1" ansi-red "^0.1.1" @@ -5633,6 +5928,7 @@ plugin-error@^0.1.2: plugin-log@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/plugin-log/-/plugin-log-0.1.0.tgz#86049cf6ab10833398a931f3689cbaee7b5e1333" + integrity sha1-hgSc9qsQgzOYqTHzaJy67nteEzM= dependencies: chalk "^1.1.1" dateformat "^1.0.11" @@ -5640,168 +5936,249 @@ plugin-log@^0.1.0: pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-bem-linter@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-bem-linter/-/postcss-bem-linter-3.1.0.tgz#55352412fb481aad0d05148185a990734e1ca030" + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-bem-linter/-/postcss-bem-linter-3.2.0.tgz#6b57e2861a6b5c03d1cedc1777ea52addecd4ff1" + integrity sha512-VnmbgTrFveO5jZwmG2C3RRQkl2TuTkWaFcDaiDk2zUiksQ5yUz6cNkb0C9xkVOEpVHnpFaO4kMziiHBnd+S+FQ== dependencies: minimatch "^3.0.3" postcss "^6.0.6" postcss-resolve-nested-selector "^0.1.1" +postcss-custom-properties@^8.0.9: + version "8.0.9" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.9.tgz#8943870528a6eae4c8e8d285b6ccc9fd1f97e69c" + integrity sha512-/Lbn5GP2JkKhgUO2elMs4NnbUJcvHX4AaF5nuJDaNkd2chYW1KA5qtOGGgdkBEWcXtKSQfHXzT7C6grEVyb13w== + dependencies: + postcss "^7.0.5" + postcss-values-parser "^2.0.0" + postcss-html@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.12.0.tgz#39b6adb4005dfc5464df7999c0f81c95bced7e50" + integrity sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ== dependencies: htmlparser2 "^3.9.2" remark "^8.0.0" unist-util-find-all-after "^1.0.1" -postcss-html@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.15.0.tgz#11ba3c07c817d0816f091fe40817a8ecd861300f" +postcss-html@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== dependencies: - htmlparser2 "^3.9.2" - remark "^9.0.0" - unist-util-find-all-after "^1.0.1" + htmlparser2 "^3.10.0" -postcss-html@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.18.0.tgz#992a84117cc56f9f28915fbadba576489641e652" +postcss-jsx@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.0.tgz#b7685ed3d070a175ef0aa48f83d9015bd772c82d" + integrity sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g== dependencies: - "@babel/core" "^7.0.0-beta.42" - "@babel/traverse" "^7.0.0-beta.42" - babylon "^7.0.0-beta.42" - htmlparser2 "^3.9.2" - remark "^9.0.0" - unist-util-find-all-after "^1.0.1" + "@babel/core" ">=7.1.0" postcss-less@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-1.1.3.tgz#6930525271bfe38d5793d33ac09c1a546b87bb51" - dependencies: - postcss "^5.2.16" - -postcss-less@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-1.1.5.tgz#a6f0ce180cf3797eeee1d4adc0e9e6d6db665609" + integrity sha512-QQIiIqgEjNnquc0d4b6HDOSFZxbFQoy4MPpli2lSLpKhMyBkKwwca2HFqu4xzxlKID/F2fxSOowwtKpgczhF7A== dependencies: postcss "^5.2.16" +postcss-less@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.2.tgz#fb67e7ba351dbdf69de3c52eebd1184c52bfaea6" + integrity sha512-66ZBVo1JGkQ7r13M97xcHcyarWpgg21RaqIZWZXHE3XOtb5+ywK1uZWeY1DYkYRkIX/l8Hvxnx9iSKB68nFr+w== + dependencies: + postcss "^7.0.14" + +postcss-load-config@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" + integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== + dependencies: + cosmiconfig "^4.0.0" + import-cwd "^2.0.0" + +postcss-markdown@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560" + integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ== + dependencies: + remark "^10.0.1" + unist-util-find-all-after "^1.0.2" + postcss-media-query-parser@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= postcss-reporter@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-5.0.0.tgz#a14177fd1342829d291653f2786efd67110332c3" + integrity sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg== dependencies: chalk "^2.0.1" lodash "^4.17.4" log-symbols "^2.0.0" postcss "^6.0.8" +postcss-reporter@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f" + integrity sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw== + dependencies: + chalk "^2.4.1" + lodash "^4.17.11" + log-symbols "^2.2.0" + postcss "^7.0.7" + postcss-resolve-nested-selector@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= postcss-safe-parser@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz#b753eff6c7c0aea5e8375fbe4cde8bf9063ff142" + integrity sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI= dependencies: postcss "^6.0.6" +postcss-safe-parser@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea" + integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ== + dependencies: + postcss "^7.0.0" + postcss-sass@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.2.0.tgz#e55516441e9526ba4b380a730d3a02e9eaa78c7a" + integrity sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg== dependencies: gonzales-pe "^4.0.3" postcss "^6.0.6" -postcss-sass@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.0.tgz#dc2582ee0e61541aa88bafdc5a8aebb53deaae75" +postcss-sass@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.5.tgz#6d3e39f101a53d2efa091f953493116d32beb68c" + integrity sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A== dependencies: gonzales-pe "^4.2.3" - postcss "^6.0.16" + postcss "^7.0.1" postcss-scss@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.4.tgz#6310fe1a15be418707a2cfd77f21dd4a06d1e09d" + version "1.0.6" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.6.tgz#ab903f3bb20161bc177896462293a53d4bff5f7a" + integrity sha512-4EFYGHcEw+H3E06PT/pQQri06u/1VIIPjeJQaM8skB80vZuXMhp4cSNV5azmdNkontnOID/XYWEvEEELLFB1ww== dependencies: - postcss "^6.0.19" + postcss "^6.0.23" -postcss-selector-parser@^3.1.0, postcss-selector-parser@^3.1.1: +postcss-scss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.0.0.tgz#248b0a28af77ea7b32b1011aba0f738bda27dea1" + integrity sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug== + dependencies: + postcss "^7.0.0" + +postcss-selector-parser@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= dependencies: dot-prop "^4.1.1" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-4.0.0.tgz#50c6570f40579036d8e63f23e6c0626fe5743527" +postcss-selector-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== dependencies: - cssesc "^1.0.1" + cssesc "^2.0.0" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-sorting@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-3.1.0.tgz#af7c90ee73ad12569a57664eaf06735c2e25bec0" +postcss-sorting@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-4.0.1.tgz#4bb4eb40e07e2b74e49f6f97fd4317fa73bd65a8" + integrity sha512-YNRq7ChWFsLsns78zutLBWp6kvfZr/3YYf9q54P/fBpIHhf8gwbKvr5XHAt2l69SS08lfGtB8gG8m/62gsuTgw== dependencies: lodash "^4.17.4" - postcss "^6.0.13" + postcss "^7.0.0" -postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" +postcss-syntax@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== -postcss@>=5.0.19, postcss@^6.0.1, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.16, postcss@^6.0.19, postcss@^6.0.6, postcss@^6.0.8: - version "6.0.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" +postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-values-parser@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== dependencies: - chalk "^2.3.1" + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss@>=5.0.19, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.5, postcss@^7.0.7: + version "7.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" + integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== + dependencies: + chalk "^2.4.2" source-map "^0.6.1" - supports-color "^5.2.0" + supports-color "^6.1.0" postcss@^5.2.16: version "5.2.18" resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== dependencies: chalk "^1.1.3" js-base64 "^2.1.9" source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0.17: - version "6.0.20" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.20.tgz#686107e743a12d5530cb68438c590d5b2bf72c3c" +postcss@^6.0.14, postcss@^6.0.17, postcss@^6.0.23, postcss@^6.0.6, postcss@^6.0.8: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== dependencies: - chalk "^2.3.2" + chalk "^2.4.1" source-map "^0.6.1" - supports-color "^5.3.0" + supports-color "^5.4.0" prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -prettier-eslint@^8.8.1: - version "8.8.1" - resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-8.8.1.tgz#38505163274742f2a0b31653c39e40f37ebd07da" +prettier-eslint@^8.8.2: + version "8.8.2" + resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-8.8.2.tgz#fcb29a48ab4524e234680797fe70e9d136ccaf0b" + integrity sha512-2UzApPuxi2yRoyMlXMazgR6UcH9DKJhNgCviIwY3ixZ9THWSSrUww5vkiZ3C48WvpFl1M1y/oU63deSy1puWEA== dependencies: babel-runtime "^6.26.0" common-tags "^1.4.0" @@ -5811,14 +6188,16 @@ prettier-eslint@^8.8.1: lodash.merge "^4.6.0" loglevel-colored-level-prefix "^1.0.0" prettier "^1.7.0" - pretty-format "^22.0.3" + pretty-format "^23.0.1" require-relative "^0.8.7" typescript "^2.5.1" - typescript-eslint-parser "^11.0.0" + typescript-eslint-parser "^16.0.0" + vue-eslint-parser "^2.0.2" prettier-stylelint@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/prettier-stylelint/-/prettier-stylelint-0.4.2.tgz#62845e342f786218b008da69eef14f0a5c05bcfb" + integrity sha512-CmatjDsW8xKMtWg/Tc6/W02wC59p50kkItrXmkgbhR4b2EKMU5Pm55x1WuCahkkZeZoNVReWRxA8VL/s69mkBg== dependencies: cosmiconfig "^3.0.1" debug "^3.0.1" @@ -5836,16 +6215,19 @@ prettier-stylelint@^0.4.2: update-notifier "^2.2.0" prettier@^1.7.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75" + version "1.16.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.1.tgz#534c2c9d7853f8845e5e078384e71973bd74089f" + integrity sha512-XXUITwIkGb3CPJ2hforHah/zTINRyie5006Jd2HKy2qz7snEJXl0KLfsJZW/wst9g6R2rFvqba3VpNYdu1hDcA== pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" + integrity sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk= -pretty-format@^22.0.3: - version "22.4.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.0.tgz#237b1f7e1c50ed03bc65c03ccc29d7c8bb7beb94" +pretty-format@^23.0.1: + version "23.6.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" + integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" @@ -5853,181 +6235,115 @@ pretty-format@^22.0.3: pretty-hrtime@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= -private@^0.1.6, private@^0.1.7, private@^0.1.8: +private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - -promise-inflight@^1.0.1, promise-inflight@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - -promise-retry@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" - dependencies: - err-code "^1.0.0" - retry "^0.10.0" - -promzard@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" - dependencies: - read "1" - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -protoduck@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.0.tgz#752145e6be0ad834cb25716f670a713c860dce70" +propose@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/propose/-/propose-0.0.5.tgz#48a065d9ec7d4c8667f4050b15c4a2d85dbca56b" + integrity sha1-SKBl2ex9TIZn9AULFcSi2F28pWs= dependencies: - genfun "^4.0.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + levenshtein-edit-distance "^1.0.0" pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== -pump@^2.0.0, pump@^2.0.1: +pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb" +pumpify@^1.3.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: - duplexify "^3.5.3" + duplexify "^3.6.0" inherits "^2.0.3" pump "^2.0.0" punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qrcode-terminal@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - -query-string@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.0.0.tgz#8b8f39447b73e8290d6f5e3581779218e9171142" - dependencies: - decode-uri-component "^0.2.0" - strict-uri-encode "^2.0.0" +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= -qw@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" -raven-js@^3.24.2: - version "3.24.2" - resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.2.tgz#c5cacb363b198812e80cd4c6714e5e478549ebcf" +raven-js@^3.27.0: + version "3.27.0" + resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.27.0.tgz#9f47c03e17933ce756e189f3669d49c441c1ba6e" + integrity sha512-vChdOL+yzecfnGA+B5EhEZkJ3kY3KlMzxEhShKh6Vdtooyl0yZfYNFQfYzgMf2v4pyQa+OTZ5esTxxgOOZDHqw== -rc@^1.0.1, rc@^1.1.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" +rc@^1.0.1, rc@^1.1.0, rc@^1.1.6, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: - deep-extend "~0.4.0" + deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" strip-json-comments "~2.0.1" -read-cmd-shim@^1.0.1, read-cmd-shim@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" - dependencies: - graceful-fs "^4.1.2" - -read-installed@~4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" - dependencies: - debuglog "^1.0.1" - read-package-json "^2.0.0" - readdir-scoped-modules "^1.0.0" - semver "2 || 3 || 4 || 5" - slide "~1.1.3" - util-extend "^1.0.1" - optionalDependencies: - graceful-fs "^4.1.2" - -"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.12, read-package-json@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" - dependencies: - glob "^7.1.1" - json-parse-better-errors "^1.0.1" - normalize-package-data "^2.0.0" - slash "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.2" - -read-package-tree@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" - dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - once "^1.3.0" - read-package-json "^2.0.0" - readdir-scoped-modules "^1.0.0" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -6035,6 +6351,7 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -6042,6 +6359,7 @@ read-pkg-up@^2.0.0: read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= dependencies: find-up "^2.0.0" read-pkg "^3.0.0" @@ -6049,6 +6367,7 @@ read-pkg-up@^3.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -6057,6 +6376,7 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" @@ -6065,20 +6385,25 @@ read-pkg@^2.0.0: read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= dependencies: load-json-file "^4.0.0" normalize-package-data "^2.3.2" path-type "^3.0.0" -read@1, read@~1.0.1, read@~1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" +"readable-stream@2 || 3", readable-stream@^3.0.6: + version "3.1.1" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" + integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== dependencies: - mute-stream "~0.0.4" + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.4, readable-stream@^2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -6088,54 +6413,46 @@ read@1, read@~1.0.1, read@~1.0.7: string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.17: +readable-stream@~1.0.17: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.1.10, readable-stream@~1.1.9: +readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" isarray "0.0.1" string_decoder "~0.10.x" -readdir-scoped-modules@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" +readdirp@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - graceful-fs "^4.1.2" - once "^1.3.0" + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= dependencies: indent-string "^2.1.0" strip-indent "^1.0.1" @@ -6143,58 +6460,85 @@ redent@^1.0.0: redent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= dependencies: indent-string "^3.0.0" strip-indent "^2.0.0" -regenerate@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" +regenerate-unicode-properties@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" + integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== + dependencies: + regenerate "^1.4.0" -regenerator-runtime@^0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" +regenerator-transform@^0.13.3: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" + integrity sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA== dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" private "^0.1.6" regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp-tree@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.0.tgz#a56ad7746097888ea16457479029ec9345b96ab0" + integrity sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg== + dependencies: + cli-table3 "^0.5.0" + colors "^1.1.2" + yargs "^10.0.3" + regexpp@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.0.1.tgz#d857c3a741dce075c2848dcb019a0a975b190d43" + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpu-core@^4.1.3, regexpu-core@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" + integrity sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA== dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" + regenerate "^1.4.0" + regenerate-unicode-properties "^7.0.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.0.2" registry-auth-token@^3.0.1: version "3.3.2" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== dependencies: rc "^1.1.6" safe-buffer "^5.0.1" @@ -6202,22 +6546,35 @@ registry-auth-token@^3.0.1: registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= dependencies: rc "^1.0.1" -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" + integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== dependencies: jsesc "~0.5.0" +remark-cli@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/remark-cli/-/remark-cli-6.0.1.tgz#ace67b94c05df0516b6be8dd70f326b6fa9c3770" + integrity sha512-h7Hwnfdcm5J03t2mxhl9BAav+Goqauqfz3LhpE7TP+RIiPnK6njU7qRDD7qlUd/hLyMSB+WBjYc7gVDQT3pv0A== + dependencies: + markdown-extensions "^1.1.0" + remark "^10.0.0" + unified-args "^6.0.0" + remark-parse@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-4.0.0.tgz#99f1f049afac80382366e2e0d0bd55429dd45d8b" + integrity sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw== dependencies: collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" @@ -6235,9 +6592,10 @@ remark-parse@^4.0.0: vfile-location "^2.0.0" xtend "^4.0.1" -remark-parse@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" +remark-parse@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" + integrity sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg== dependencies: collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" @@ -6258,6 +6616,7 @@ remark-parse@^5.0.0: remark-stringify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-4.0.0.tgz#4431884c0418f112da44991b4e356cfe37facd87" + integrity sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w== dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -6274,9 +6633,10 @@ remark-stringify@^4.0.0: unherit "^1.0.4" xtend "^4.0.1" -remark-stringify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-5.0.0.tgz#336d3a4d4a6a3390d933eeba62e8de4bd280afba" +remark-stringify@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088" + integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg== dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -6293,127 +6653,155 @@ remark-stringify@^5.0.0: unherit "^1.0.4" xtend "^4.0.1" +remark-validate-links@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/remark-validate-links/-/remark-validate-links-8.0.0.tgz#4127c255a08610aa8acb1d7c072d878dc087222f" + integrity sha512-S9255mpPMLGKC5xHTgmJOcbKjUGXwag+5VBBbOZqkmstfg7wDnElgsGDOkOeqzSIrlq8Oom+aXTy/Pds3Lhhgg== + dependencies: + github-slugger "^1.2.0" + hosted-git-info "^2.5.0" + mdast-util-definitions "^1.0.0" + mdast-util-to-string "^1.0.4" + propose "0.0.5" + unist-util-visit "^1.0.0" + urljoin "^0.1.5" + xtend "^4.0.1" + +remark@^10.0.0, remark@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df" + integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ== + dependencies: + remark-parse "^6.0.0" + remark-stringify "^6.0.0" + unified "^7.0.0" + remark@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark/-/remark-8.0.0.tgz#287b6df2fe1190e263c1d15e486d3fa835594d6d" + integrity sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw== dependencies: remark-parse "^4.0.0" remark-stringify "^4.0.0" unified "^6.0.0" -remark@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/remark/-/remark-9.0.0.tgz#c5cfa8ec535c73a67c4b0f12bfdbd3a67d8b2f60" +remove-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== dependencies: - remark-parse "^5.0.0" - remark-stringify "^5.0.0" - unified "^6.0.0" + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" -remove-trailing-separator@^1.0.1: +remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" replace-ext@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= replace-ext@1.0.0, replace-ext@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +replace-homedir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" + integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= + dependencies: + homedir-polyfill "^1.0.1" + is-absolute "^1.0.0" + remove-trailing-separator "^1.1.0" replacestream@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.3.tgz#3ee5798092be364b1cdb1484308492cb3dff2f36" + integrity sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA== dependencies: escape-string-regexp "^1.0.3" object-assign "^4.0.1" readable-stream "^2.0.2" -request@2, request@^2.74.0, request@^2.85.0: - version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" +request@^2.55.0, request@^2.87.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" - aws4 "^1.6.0" + aws4 "^1.8.0" caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" + combined-stream "~1.0.6" + extend "~3.0.2" forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" + form-data "~2.3.2" + har-validator "~5.1.0" http-signature "~1.2.0" is-typedarray "~1.0.0" isstream "~0.1.2" json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" + mime-types "~2.1.19" + oauth-sign "~0.9.0" performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" + uuid "^3.3.2" require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-relative@^0.8.7: version "0.8.7" resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" + integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -6421,12 +6809,14 @@ require-uncached@^1.0.3: resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= dependencies: resolve-from "^3.0.0" resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= dependencies: expand-tilde "^2.0.0" global-modules "^1.0.0" @@ -6434,40 +6824,41 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-url@^0.2.1, resolve-url@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" +resolve-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= dependencies: - path-parse "^1.0.5" + value-or-function "^3.0.0" -resolve@^1.3.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" - dependencies: - path-parse "^1.0.5" +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -6475,126 +6866,120 @@ restore-cursor@^2.0.0: ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -retry@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@~2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" +rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.6.1, rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: - glob "^7.0.5" + glob "^7.1.3" -rollup-plugin-babel@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.4.tgz#41b3e762fe64450dd61da3105a2cf7ad76be4edc" +rollup-plugin-babel@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.3.2.tgz#8c0e1bd7aa9826e90769cf76895007098ffd1413" + integrity sha512-KfnizE258L/4enADKX61ozfwGHoqYauvoofghFJBhFnpH9Sb9dNPpWg8QHOaAfVASUYV8w0mCx430i9z0LJoJg== dependencies: - rollup-pluginutils "^1.5.0" + "@babel/helper-module-imports" "^7.0.0" + rollup-pluginutils "^2.3.0" -rollup-plugin-commonjs@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.3.tgz#37bfbf341292ea14f512438a56df8f9ca3ba4d67" +rollup-plugin-commonjs@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz#4604e25069e0c78a09e08faa95dc32dec27f7c89" + integrity sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA== dependencies: - estree-walker "^0.5.1" - magic-string "^0.22.4" - resolve "^1.5.0" - rollup-pluginutils "^2.0.1" + estree-walker "^0.5.2" + magic-string "^0.25.1" + resolve "^1.8.1" + rollup-pluginutils "^2.3.3" -rollup-plugin-node-resolve@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz#c26d110a36812cbefa7ce117cadcd3439aa1c713" +rollup-plugin-node-resolve@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz#9bc6b8205e9936cc0e26bba2415f1ecf1e64d9b2" + integrity sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw== dependencies: - builtin-modules "^2.0.0" + builtin-modules "^3.0.0" is-module "^1.0.0" - resolve "^1.1.6" - -rollup-pluginutils@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" + resolve "^1.8.1" -rollup-pluginutils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" +rollup-pluginutils@^2.3.0, rollup-pluginutils@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" + integrity sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA== dependencies: - estree-walker "^0.3.0" + estree-walker "^0.5.2" micromatch "^2.3.11" -"rollup@>=0.48 <0.57": - version "0.56.5" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.5.tgz#40fe3cf0cd1659d469baad11f4d5b6336c14ce84" +rollup@^0.66.0: + version "0.66.6" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.66.6.tgz#ce7d6185beb7acea644ce220c25e71ae03275482" + integrity sha512-J7/SWanrcb83vfIHqa8+aVVGzy457GcjA6GVZEnD0x2u4OnOd0Q1pCrEoNe8yLwM6z6LZP02zBT2uW0yh5TqOw== + dependencies: + "@types/estree" "0.0.39" + "@types/node" "*" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - dependencies: - aproba "^1.1.1" - -run-sequence@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/run-sequence/-/run-sequence-2.2.1.tgz#1ce643da36fd8c7ea7e1a9329da33fc2b8898495" - dependencies: - chalk "^1.1.3" - fancy-log "^1.3.2" - plugin-error "^0.1.2" - rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +rxjs@^6.1.0: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" + integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== + dependencies: + tslib "^1.9.0" -safe-buffer@^5.1.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" -safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" yargs "^7.0.0" -sax@>=0.6.0, sax@~1.2.1: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= dependencies: js-base64 "^2.1.8" source-map "^0.4.2" @@ -6602,36 +6987,41 @@ scss-tokenizer@^0.2.3: semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= dependencies: semver "^5.0.3" -"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" +semver-greatest-satisfied-range@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" + integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= + dependencies: + sver-compat "^1.5.0" -semver@5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== -semver@^4.1.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" +semver@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -sequencify@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6641,62 +7031,65 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" is-plain-object "^2.0.3" split-string "^3.0.1" -sha@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" - dependencies: - graceful-fs "^4.1.2" - readable-stream "^2.0.2" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" +shellsubstitute@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shellsubstitute/-/shellsubstitute-1.2.0.tgz#e4f702a50c518b0f6fe98451890d705af29b6b70" + integrity sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A= signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" -slide@^1.1.3, slide@^1.1.6, slide@~1.1.3, slide@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -smart-buffer@^1.0.13: - version "1.1.15" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" - -smart-buffer@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" +slice-ansi@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" + integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6705,12 +7098,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6721,446 +7116,419 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - -socks-proxy-agent@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" - dependencies: - agent-base "^4.1.0" - socks "^1.1.10" - -socks-proxy-agent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" - dependencies: - agent-base "~4.2.0" - socks "~2.2.0" - -socks@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" - dependencies: - ip "^1.1.4" - smart-buffer "^1.0.13" - -socks@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.0.tgz#144985b3331ced3ab5ccbee640ab7cb7d43fdd1f" - dependencies: - ip "^1.1.5" - smart-buffer "^4.0.1" - -sorted-object@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" - -sorted-union-stream@~2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7" - dependencies: - from2 "^1.3.0" - stream-iterate "^1.1.0" - -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" - dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - -source-map-resolve@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" +source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: - atob "^2.0.0" + atob "^2.1.1" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" +source-map-support@~0.5.6: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== dependencies: - source-map "^0.5.6" + buffer-from "^1.0.0" + source-map "^0.6.0" source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" - -source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha1-66T12pwNyZneaAMti092FzZSA2s= dependencies: amdefine ">=0.0.4" -source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sourcemap-codec@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" + integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + version "3.0.3" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" + integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== specificity@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.3.2.tgz#99e6511eceef0f8d9b57924937aac2cb13d13c42" + integrity sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A== + +specificity@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" +split@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== dependencies: through "2" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" ecc-jsbn "~0.1.1" + getpass "^0.1.1" jsbn "~0.1.0" + safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@^5.0.0, ssri@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" - dependencies: - safe-buffer "^5.1.1" +stable@~0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -ssri@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.0.tgz#fc21bfc90e03275ac3e23d5a42e38b8a1cbc130d" +stack-trace@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= state-toggle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" + version "1.0.1" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" + integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og== static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" stdout-stream@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + version "1.4.1" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" + integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== dependencies: readable-stream "^2.0.1" -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" +stream-combiner@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" + integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= dependencies: duplexer "~0.1.1" - -stream-consume@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48" + through "~2.3.4" stream-counter@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-1.0.0.tgz#91cf2569ce4dc5061febcd7acb26394a5a114751" + integrity sha1-kc8lac5NxQYf6816yyY5SloRR1E= -stream-each@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-iterate@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" - dependencies: - readable-stream "^2.1.5" - stream-shift "^1.0.0" +stream-exhaust@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" + integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= streamfilter@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" + integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== dependencies: readable-stream "^2.0.2" -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.0.0" -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" +string_decoder@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== dependencies: safe-buffer "~5.1.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-entities@^1.0.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.1.tgz#b150ec2d72ac4c1b5f324b51fb6b28c9cdff058c" + version "1.3.2" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" + integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A== dependencies: character-entities-html4 "^1.0.0" character-entities-legacy "^1.0.0" is-alphanumerical "^1.0.0" is-hexadecimal "^1.0.0" -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - strip-ansi@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" + integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= dependencies: ansi-regex "^0.2.1" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0, strip-ansi@~4.0.0: +strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" + integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== + dependencies: + ansi-regex "^4.0.0" + strip-bom-string@1.X: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - -strip-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" - dependencies: - first-chunk-stream "^1.0.0" - is-utf8 "^0.2.0" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= dependencies: get-stdin "^4.0.1" strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@~2.0.1: +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= -stylelint-config-prettier@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.2.0.tgz#af32b7845adeeddbf0a0bd642ace4ca1e68958e2" - dependencies: - stylelint "^9.1.1" +stylelint-config-prettier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-4.0.0.tgz#8c712977be13bd25191ab8b986b5c07a3342a5dc" + integrity sha512-cwh3QbBC2+3zBeMvuxFjT8XsbSdyoyELOY9BZqMuvphUKEQ+srkPWoN60FlvRwLB014TOke4Y12KvTtfKnaHhg== stylelint-config-recommended@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz#f526d5c771c6811186d9eaedbed02195fee30858" + integrity sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA== -stylelint-config-sass-guidelines@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/stylelint-config-sass-guidelines/-/stylelint-config-sass-guidelines-5.0.0.tgz#529fc101f4a15da3c54e66efdd9d79abc01668f7" +stylelint-config-sass-guidelines@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/stylelint-config-sass-guidelines/-/stylelint-config-sass-guidelines-5.3.0.tgz#145e8c10703c517e0961ef55b883091001104783" + integrity sha512-qZbYC7zDGkoPpY1WeEf4HXqHvOyV3Sv5SD51+8EEU+8CNAHSaqWOmB51GlGivSFtPCLGxPuUBjnIwojXskPAFA== dependencies: - stylelint-order "^0.8.0" - stylelint-scss "^2.0.0" + stylelint-order ">=1.0.0" + stylelint-scss "^3.4.0" -stylelint-order@^0.8.0, stylelint-order@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-0.8.1.tgz#35f71af3a15954154e0e99e5646ba3d6fbe34f8d" - dependencies: - lodash "^4.17.4" - postcss "^6.0.14" - postcss-sorting "^3.1.0" - -stylelint-scss@^2.0.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-2.5.0.tgz#ac4c83474c53b19cc1f9e93d332786cf89c8d217" +stylelint-order@>=1.0.0, stylelint-order@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-2.0.0.tgz#f19400e1d42a844bfd149fae1daa02e671a9b2f2" + integrity sha512-rGmvP5zSCxvmBYP8DgzmdMhMMM+degsQCXrzYDmqPmeyU2bWmQTt2mH157Svj0WwHQn1LG9aQHdvKZfpfg2t4A== dependencies: - lodash "^4.17.4" - postcss-media-query-parser "^0.2.3" - postcss-resolve-nested-selector "^0.1.1" - postcss-selector-parser "^3.1.1" - postcss-value-parser "^3.3.0" + lodash "^4.17.10" + postcss "^7.0.2" + postcss-sorting "^4.0.1" -stylelint-scss@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.1.0.tgz#aa46503014d1a6edb2fb4c5fefb73a7d0d5bc644" +stylelint-scss@^3.4.0, stylelint-scss@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.5.1.tgz#3759dbae8da4b03d8a9f60f5b8c098f23961db43" + integrity sha512-XNWKTU1a2EUNWdauxHPTJlGNNQzIbg48OTTIdBs5xTXxpbYAGtX/J+jBqMPjxfdySXijc/mexubuZ+ZinUGGgw== dependencies: - lodash "^4.17.4" + lodash "^4.17.11" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.1" - postcss-selector-parser "^4.0.0" - postcss-value-parser "^3.3.0" + postcss-selector-parser "^5.0.0" + postcss-value-parser "^3.3.1" stylelint-selector-bem-pattern@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/stylelint-selector-bem-pattern/-/stylelint-selector-bem-pattern-2.0.0.tgz#9a6130c9c90963b30e925c917079d6c8fed73f45" + integrity sha512-J5NQeNcweS56US29oHHb7GAX8taG44lYn5cY9YEE3xA5ibeWmPBiCGLg6HskPlmVBO0hcJ4JUQ9A4Ngyu8avxQ== dependencies: lodash ">=3.10.0" postcss ">=5.0.19" postcss-bem-linter "^3.0.0" stylelint ">=3.0.2" -stylelint@>=3.0.2, stylelint@^9.1.1: - version "9.1.3" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.1.3.tgz#8260f2a221b98e4afafd9b2b8a785d2e38cbb8a4" +stylelint@>=3.0.2, stylelint@^9.10.1: + version "9.10.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.10.1.tgz#5f0ee3701461dff1d68284e1386efe8f0677a75d" + integrity sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ== dependencies: - autoprefixer "^8.0.0" + autoprefixer "^9.0.0" balanced-match "^1.0.0" - chalk "^2.0.1" - cosmiconfig "^4.0.0" - debug "^3.0.0" + chalk "^2.4.1" + cosmiconfig "^5.0.0" + debug "^4.0.0" execall "^1.0.0" - file-entry-cache "^2.0.0" - get-stdin "^5.0.1" - globby "^7.0.0" + file-entry-cache "^4.0.0" + get-stdin "^6.0.0" + global-modules "^2.0.0" + globby "^9.0.0" globjoin "^0.1.4" html-tags "^2.0.0" - ignore "^3.3.3" + ignore "^5.0.4" + import-lazy "^3.1.0" imurmurhash "^0.1.4" - known-css-properties "^0.6.0" + known-css-properties "^0.11.0" + leven "^2.1.0" lodash "^4.17.4" log-symbols "^2.0.0" mathml-tag-names "^2.0.1" - meow "^4.0.0" - micromatch "^2.3.11" + meow "^5.0.0" + micromatch "^3.1.10" normalize-selector "^0.2.0" - pify "^3.0.0" - postcss "^6.0.16" - postcss-html "^0.15.0" - postcss-less "^1.1.0" + pify "^4.0.0" + postcss "^7.0.13" + postcss-html "^0.36.0" + postcss-jsx "^0.36.0" + postcss-less "^3.1.0" + postcss-markdown "^0.36.0" postcss-media-query-parser "^0.2.3" - postcss-reporter "^5.0.0" + postcss-reporter "^6.0.0" postcss-resolve-nested-selector "^0.1.1" - postcss-safe-parser "^3.0.1" - postcss-sass "^0.3.0" - postcss-scss "^1.0.2" + postcss-safe-parser "^4.0.0" + postcss-sass "^0.3.5" + postcss-scss "^2.0.0" postcss-selector-parser "^3.1.0" + postcss-syntax "^0.36.2" postcss-value-parser "^3.3.0" resolve-from "^4.0.0" signal-exit "^3.0.2" - specificity "^0.3.1" - string-width "^2.1.0" + slash "^2.0.0" + specificity "^0.4.1" + string-width "^3.0.0" style-search "^0.1.0" - sugarss "^1.0.0" + sugarss "^2.0.0" svg-tags "^1.0.0" - table "^4.0.1" + table "^5.0.0" stylelint@^8.1.1: version "8.4.0" resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-8.4.0.tgz#c2dbaeb17236917819f9206e1c0df5fddf6f83c3" + integrity sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q== dependencies: autoprefixer "^7.1.2" balanced-match "^1.0.0" @@ -7202,97 +7570,88 @@ stylelint@^8.1.1: svg-tags "^1.0.0" table "^4.0.1" -stylelint@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.2.0.tgz#f77a82518106074c1a795e962fd780da2c8af43b" - dependencies: - autoprefixer "^8.0.0" - balanced-match "^1.0.0" - chalk "^2.0.1" - cosmiconfig "^4.0.0" - debug "^3.0.0" - execall "^1.0.0" - file-entry-cache "^2.0.0" - get-stdin "^6.0.0" - globby "^8.0.0" - globjoin "^0.1.4" - html-tags "^2.0.0" - ignore "^3.3.3" - import-lazy "^3.1.0" - imurmurhash "^0.1.4" - known-css-properties "^0.6.0" - lodash "^4.17.4" - log-symbols "^2.0.0" - mathml-tag-names "^2.0.1" - meow "^4.0.0" - micromatch "^2.3.11" - normalize-selector "^0.2.0" - pify "^3.0.0" - postcss "^6.0.16" - postcss-html "^0.18.0" - postcss-less "^1.1.5" - postcss-media-query-parser "^0.2.3" - postcss-reporter "^5.0.0" - postcss-resolve-nested-selector "^0.1.1" - postcss-safe-parser "^3.0.1" - postcss-sass "^0.3.0" - postcss-scss "^1.0.2" - postcss-selector-parser "^3.1.0" - postcss-value-parser "^3.3.0" - resolve-from "^4.0.0" - signal-exit "^3.0.2" - specificity "^0.3.1" - string-width "^2.1.0" - style-search "^0.1.0" - sugarss "^1.0.0" - svg-tags "^1.0.0" - table "^4.0.1" - sugarss@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" + integrity sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA== dependencies: postcss "^6.0.14" +sugarss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" + integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== + dependencies: + postcss "^7.0.2" + supports-color@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" -supports-color@^5.2.0, supports-color@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== dependencies: has-flag "^3.0.0" +sver-compat@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" + integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + dependencies: + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + svg-tags@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= -svgo@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" +svgo@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" + integrity sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g== dependencies: - coa "~1.0.1" + coa "~2.0.1" colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" + css-select "^2.0.0" + css-select-base-adapter "~0.1.0" + css-tree "1.0.0-alpha.28" + css-url-regex "^1.1.0" + csso "^3.5.0" + js-yaml "^3.12.0" mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" + object.values "^1.0.4" + sax "~1.2.4" + stable "~0.1.6" + unquote "~1.1.1" + util.promisify "~1.0.0" table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -7304,6 +7663,7 @@ table@4.0.2: table@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" + integrity sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg== dependencies: ajv "^6.0.1" ajv-keywords "^3.0.0" @@ -7312,33 +7672,47 @@ table@^4.0.1: slice-ansi "1.0.0" string-width "^2.1.1" +table@^5.0.0, table@^5.0.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.2.1.tgz#e78463702b1be9f7131c39860bcfb1b81114c2a1" + integrity sha512-qmhNs2GEHNqY5fd2Mo+8N1r2sw/rvTAAvBZTaTx+Y7PHLypqyrxr1MdIu0pLw6Xvl/Gi4ONu/sdceP8vvUjkyA== + dependencies: + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "2.0.0" + string-width "^2.1.1" + tar@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" inherits "2" -tar@^4.4.0, tar@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.1.tgz#b25d5a8470c976fd7a9a8a350f42c59e9fa81749" +tar@^4: + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== dependencies: - chownr "^1.0.1" + chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.2.4" - minizlib "^1.1.0" + minipass "^2.3.4" + minizlib "^1.1.1" mkdirp "^0.5.0" - safe-buffer "^5.1.1" + safe-buffer "^5.1.2" yallist "^3.0.2" temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" + integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= temp-write@^3.3.0: version "3.4.0" resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492" + integrity sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI= dependencies: graceful-fs "^4.1.2" is-stream "^1.1.0" @@ -7350,6 +7724,7 @@ temp-write@^3.3.0: tempy@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.2.1.tgz#9038e4dbd1c201b74472214179bc2c6f7776e54c" + integrity sha512-LB83o9bfZGrntdqPuRdanIVCPReam9SOZKW0fOy5I9X3A854GGWi0tjCqoXEk84XIEYBc/x9Hq3EFop/H5wJaw== dependencies: temp-dir "^1.0.0" unique-string "^1.0.0" @@ -7357,90 +7732,115 @@ tempy@^0.2.1: term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= dependencies: execa "^0.7.0" -text-table@~0.2.0: +terser@^3.7.5: + version "3.14.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32" + integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw== + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + source-map-support "~0.5.6" + +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -textextensions@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-1.0.2.tgz#65486393ee1f2bb039a60cbba05b0b68bd9501d2" +textextensions@2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.4.0.tgz#6a143a985464384cc2cff11aea448cd5b018e72b" + integrity sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA== -through2@2.0.3, through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" +through2-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== dependencies: - readable-stream "^2.1.5" + through2 "~2.0.0" + xtend "~4.0.0" + +through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@3.0.0, through2@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.0.tgz#468b461df9cd9fcc170f22ebf6852e467e578ff2" + integrity sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ== + dependencies: + readable-stream "2 || 3" xtend "~4.0.1" through2@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" + integrity sha1-390BLrnHAOIyP9M084rGIqs3Lac= dependencies: readable-stream "~1.0.17" xtend "~3.0.0" -through2@^0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: +through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -tildify@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - dependencies: - os-homedir "^1.0.0" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= -timers-ext@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.5.tgz#77147dd4e76b660c2abb8785db96574cbbd12922" +timers-ext@^0.1.5: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: - es5-ext "~0.10.14" + es5-ext "~0.10.46" next-tick "1" -tiny-relative-date@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -7448,124 +7848,240 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= dependencies: + through2 "^2.0.3" + +to-vfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-4.0.0.tgz#465ade5fc2b9e97e6c80b854d378a5d0f4b5d04a" + integrity sha512-Y7EDM+uoU8TZxF5ej2mUR0dLO4qbuuNRnJKxEht2QJWEq2421pyG1D1x8YxPKmyTc6nHh7Td/jLGFxYo+9vkLA== + dependencies: + is-buffer "^2.0.0" + vfile "^3.0.0" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" punycode "^1.4.1" trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= trim-newlines@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim-trailing-lines@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz#7aefbb7808df9d669f6da2e438cac8c46ada7684" + version "1.1.1" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" + integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg== trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= trough@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" + version "1.0.3" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24" + integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw== "true-case-path@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + version "1.0.3" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== dependencies: - glob "^6.0.4" + glob "^7.1.2" + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-eslint-parser@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-11.0.0.tgz#37dba6a0130dd307504aa4b4b21b0d3dc7d4e9f2" +typescript-eslint-parser@^16.0.0: + version "16.0.1" + resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz#b40681c7043b222b9772748b700a000b241c031b" + integrity sha512-IKawLTu4A2xN3aN/cPLxvZ0bhxZHILGDKTZWvWNJ3sLNhJ3PjfMEDQmR2VMpdRPrmWOadgWXRwjLBzSA8AGsaQ== dependencies: lodash.unescape "4.0.1" - semver "5.4.1" + semver "5.5.0" typescript@^2.5.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" - -uglify-es@^3.3.9: - version "3.3.9" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - dependencies: - commander "~2.13.0" - source-map "~0.6.1" - -uid-number@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -umask@^1.1.0, umask@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +undertaker-registry@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" + integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= + +undertaker@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.0.tgz#339da4646252d082dc378e708067299750e11b49" + integrity sha1-M52kZGJS0ILcN45wgGcpl1DhG0k= + dependencies: + arr-flatten "^1.0.1" + arr-map "^2.0.0" + bach "^1.0.0" + collection-map "^1.0.0" + es6-weak-map "^2.0.1" + last-run "^1.1.0" + object.defaults "^1.0.0" + object.reduce "^1.0.0" + undertaker-registry "^1.0.0" unherit@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.0.tgz#6b9aaedfbf73df1756ad9e316dd981885840cd7d" + version "1.1.1" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" + integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g== dependencies: inherits "^2.0.1" xtend "^4.0.1" +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" + integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" + integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== + +unified-args@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/unified-args/-/unified-args-6.0.0.tgz#ffa3be9372ebe311099b30435b17269b0000d04c" + integrity sha512-1m2pGiTClgcCtCvgtABkJLze8JJiZpzsqujRhzBjZsRwaIIU1Yj36YHY6t2RvidO8d6fucZdk3KX+8eS4+uv9g== + dependencies: + camelcase "^5.0.0" + chalk "^2.0.0" + chokidar "^2.0.0" + fault "^1.0.2" + json5 "^1.0.0" + minimist "^1.2.0" + text-table "^0.2.0" + unified-engine "^6.0.0" + +unified-engine@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unified-engine/-/unified-engine-6.0.1.tgz#22236f1d253a6d07b6605eca83a2bcce08fc6f05" + integrity sha512-iDJYH82TgcezQA4IZzhCNJQx7vBsGk4h9s4Q7Fscrb3qcPsxBqVrVNYez2W3sBVTxuU1bFAhyRpA6ba/R4j93A== + dependencies: + concat-stream "^1.5.1" + debug "^3.1.0" + fault "^1.0.0" + fn-name "^2.0.1" + glob "^7.0.3" + ignore "^3.2.0" + is-empty "^1.0.0" + is-hidden "^1.0.1" + is-object "^1.0.1" + js-yaml "^3.6.1" + load-plugin "^2.0.0" + parse-json "^4.0.0" + to-vfile "^4.0.0" + trough "^1.0.0" + unist-util-inspect "^4.1.2" + vfile-reporter "^5.0.0" + vfile-statistics "^1.1.0" + x-is-string "^0.1.0" + xtend "^4.0.1" + unified@^6.0.0: - version "6.1.6" - resolved "https://registry.yarnpkg.com/unified/-/unified-6.1.6.tgz#5ea7f807a0898f1f8acdeefe5f25faa010cc42b1" + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" + integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== dependencies: bail "^1.0.0" extend "^3.0.0" is-plain-obj "^1.1.0" trough "^1.0.0" vfile "^2.0.0" - x-is-function "^1.0.4" + x-is-string "^0.1.0" + +unified@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" + integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== + dependencies: + "@types/unist" "^2.0.0" + "@types/vfile" "^3.0.0" + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^3.0.0" x-is-string "^0.1.0" union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -7575,93 +8091,102 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= -unique-filename@^1.1.0, unique-filename@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" +unique-stream@^2.0.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== dependencies: - imurmurhash "^0.1.4" - -unique-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" + json-stable-stringify-without-jsonify "^1.0.1" + through2-filter "^3.0.0" unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= dependencies: crypto-random-string "^1.0.0" -unist-util-find-all-after@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.1.tgz#4e5512abfef7e0616781aecf7b1ed751c00af908" +unist-util-find-all-after@^1.0.1, unist-util-find-all-after@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz#9be49cfbae5ca1566b27536670a92836bf2f8d6d" + integrity sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w== dependencies: unist-util-is "^2.0.0" -unist-util-is@^2.0.0, unist-util-is@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.1.tgz#0c312629e3f960c66e931e812d3d80e77010947b" - -unist-util-modify-children@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz#66d7e6a449e6f67220b976ab3cb8b5ebac39e51d" +unist-util-inspect@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/unist-util-inspect/-/unist-util-inspect-4.1.3.tgz#39470e6d77485db285966df78431219aa1287822" + integrity sha512-Fv9R88ZBbDp7mHN+wsbxS1r8VW3unyhZh/F18dcJRQsg0+g3DxNQnMS+AEG/uotB8Md+HMK/TfzSU5lUDWxkZg== dependencies: - array-iterate "^1.0.0" + is-empty "^1.0.0" + +unist-util-is@^2.0.0, unist-util-is@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" + integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw== unist-util-remove-position@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" + integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q== dependencies: unist-util-visit "^1.1.0" unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== -unist-util-visit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444" +unist-util-visit-parents@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" + integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== dependencies: - unist-util-is "^2.1.1" + unist-util-is "^2.1.2" -unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unist-util-visit@^1.0.0, unist-util-visit@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1" + integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw== + dependencies: + unist-util-visit-parents "^2.0.0" + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" +untildify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" + integrity sha1-F+soB5h/dpUunASF/DEdBqgmouA= + dependencies: + os-homedir "^1.0.0" + unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= -update-notifier@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" - dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== -update-notifier@^2.3.0, update-notifier@^2.4.0: +update-notifier@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== dependencies: boxen "^1.2.1" chalk "^2.0.1" @@ -7674,127 +8199,206 @@ update-notifier@^2.3.0, update-notifier@^2.4.0: semver-diff "^2.0.0" xdg-basedir "^3.0.0" -urix@^0.1.0, urix@~0.1.0: +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" -use@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" +url-polyfill@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/url-polyfill/-/url-polyfill-1.1.3.tgz#ce0bdf2e923aa6f66bc198ab776323dfc5a91e62" + integrity sha512-xIAXc0DyXJCd767sSeRu4eqisyYhR0z0sohWArCn+WPwIatD39xGrc09l+tluIUi6jGkpGa8Gz8TKwkKYxMQvQ== + +urljoin@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/urljoin/-/urljoin-0.1.5.tgz#b25d2c6112c55ac9d50096a49a0f1fb7f4f53921" + integrity sha1-sl0sYRLFWsnVAJakmg8ft/T1OSE= dependencies: - kind-of "^6.0.2" + extend "~2.0.0" -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util-extend@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" +util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" +uuid@^3.0.1, uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -v8flags@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" +v8flags@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.2.tgz#fc5cd0c227428181e6c29b2992e4f8f1da5e0c9f" + integrity sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw== dependencies: - user-home "^1.1.1" + homedir-polyfill "^1.0.1" -validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: +value-or-function@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - dependencies: - builtins "^1.0.3" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" vfile-location@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.4.tgz#2a5e7297dd0d9e2da4381464d04acc6b834d3e55" + integrity sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w== vfile-message@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.0.tgz#a6adb0474ea400fa25d929f1d673abea6a17e359" + version "1.1.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" + integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== dependencies: unist-util-stringify-position "^1.1.1" +vfile-reporter@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-5.1.1.tgz#419688c7e9dcaf65ba81bfdb0ad443e9e0248e09" + integrity sha512-A/cfKvfVmeEmAKx1yyOWggCjC/k184Vkl5pVJAw5CEdppHd5FHBVcdyJ1JBSqIdJjJqyhZY4ZD3JycHr/uwmlA== + dependencies: + repeat-string "^1.5.0" + string-width "^2.0.0" + supports-color "^5.4.0" + unist-util-stringify-position "^1.0.0" + vfile-sort "^2.1.2" + vfile-statistics "^1.1.0" + +vfile-sort@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vfile-sort/-/vfile-sort-2.2.0.tgz#383a8727ec4c5daf37c05683684a5eb686366d39" + integrity sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ== + +vfile-statistics@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.2.tgz#c50132627e4669a3afa07c64ff1e7aa7695e8151" + integrity sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w== + vfile@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== dependencies: is-buffer "^1.1.4" replace-ext "1.0.0" unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" -vinyl-fs@^0.3.0: - version "0.3.14" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" +vfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" + integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== dependencies: - defaults "^1.0.0" - glob-stream "^3.1.5" - glob-watcher "^0.0.6" - graceful-fs "^3.0.0" - mkdirp "^0.5.0" - strip-bom "^1.0.0" - through2 "^0.6.1" - vinyl "^0.4.0" + is-buffer "^2.0.0" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + +vinyl-fs@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" vinyl-sourcemaps-apply@0.2.1, vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= dependencies: source-map "^0.5.1" vinyl@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" + integrity sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI= dependencies: clone-stats "~0.0.1" -vinyl@^0.4.0: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - vinyl@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= dependencies: clone "^1.0.0" clone-stats "^0.0.1" replace-ext "0.0.1" vinyl@^2.0.0, vinyl@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== dependencies: clone "^2.1.1" clone-buffer "^1.0.0" @@ -7803,96 +8407,104 @@ vinyl@^2.0.0, vinyl@^2.1.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vlq@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - -wcwidth@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" +vue-eslint-parser@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1" + integrity sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw== dependencies: - defaults "^1.0.3" - -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + debug "^3.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.2" + esquery "^1.0.0" + lodash "^4.17.4" which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" +which@1, which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: - string-width "^1.0.2" + string-width "^1.0.2 || 2" widest-line@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== dependencies: string-width "^2.1.1" wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -worker-farm@^1.5.4, worker-farm@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - dependencies: - errno "~0.1.7" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" -wrappy@1, wrappy@~1.0.2: +wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" +write-file-atomic@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9" + integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" -x-is-function@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" - x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= xml2js@^0.4.4: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== dependencies: sax ">=0.6.0" xmlbuilder "~9.0.1" @@ -7900,46 +8512,58 @@ xml2js@^0.4.4: xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" + integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= dependencies: camelcase "^3.0.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" -yargs@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7952,11 +8576,12 @@ yargs@^11.0.0: string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^9.0.2" + yargs-parser "^8.1.0" -yargs@^7.0.0: +yargs@^7.0.0, yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= dependencies: camelcase "^3.0.0" cliui "^3.2.0" |